1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package expvar provides a standardized interface to public variables, such
6 // as operation counters in servers. It exposes these variables via HTTP at
7 // /debug/vars in JSON format.
9 // Operations to set or modify these public variables are atomic.
11 // In addition to adding the HTTP handler, this package registers the
12 // following variables:
15 // memstats runtime.Memstats
17 // The package is sometimes only imported for the side effect of
18 // registering its HTTP handler and the above variables. To use it
19 // this way, link this package into your program:
36 // Var is an abstract type for all exported variables.
41 // Int is a 64-bit integer variable that satisfies the Var interface.
47 func (v
*Int
) String() string {
50 return strconv
.FormatInt(v
.i
, 10)
53 func (v
*Int
) Add(delta
int64) {
59 func (v
*Int
) Set(value
int64) {
65 // Float is a 64-bit float variable that satisfies the Var interface.
71 func (v
*Float
) String() string {
74 return strconv
.FormatFloat(v
.f
, 'g', -1, 64)
77 // Add adds delta to v.
78 func (v
*Float
) Add(delta
float64) {
84 // Set sets v to value.
85 func (v
*Float
) Set(value
float64) {
91 // Map is a string-to-Var map variable that satisfies the Var interface.
97 // KeyValue represents a single entry in a Map.
98 type KeyValue
struct {
103 func (v
*Map
) String() string {
109 for key
, val
:= range v
.m
{
111 fmt
.Fprintf(&b
, ", ")
113 fmt
.Fprintf(&b
, "\"%s\": %v", key
, val
)
120 func (v
*Map
) Init() *Map
{
121 v
.m
= make(map[string]Var
)
125 func (v
*Map
) Get(key
string) Var
{
131 func (v
*Map
) Set(key
string, av Var
) {
137 func (v
*Map
) Add(key
string, delta
int64) {
142 // check again under the write lock
144 if _
, ok
= v
.m
[key
]; !ok
{
151 // Add to Int; ignore otherwise.
152 if iv
, ok
:= av
.(*Int
); ok
{
157 // AddFloat adds delta to the *Float value stored under the given map key.
158 func (v
*Map
) AddFloat(key
string, delta
float64) {
163 // check again under the write lock
165 if _
, ok
= v
.m
[key
]; !ok
{
172 // Add to Float; ignore otherwise.
173 if iv
, ok
:= av
.(*Float
); ok
{
178 // Do calls f for each entry in the map.
179 // The map is locked during the iteration,
180 // but existing entries may be concurrently updated.
181 func (v
*Map
) Do(f
func(KeyValue
)) {
184 for k
, v
:= range v
.m
{
189 // String is a string variable, and satisfies the Var interface.
195 func (v
*String
) String() string {
198 return strconv
.Quote(v
.s
)
201 func (v
*String
) Set(value
string) {
207 // Func implements Var by calling the function
208 // and formatting the returned value using JSON.
209 type Func
func() interface{}
211 func (f Func
) String() string {
212 v
, _
:= json
.Marshal(f())
216 // All published variables.
219 vars
map[string]Var
= make(map[string]Var
)
222 // Publish declares a named exported variable. This should be called from a
223 // package's init function when it creates its Vars. If the name is already
224 // registered then this will log.Panic.
225 func Publish(name
string, v Var
) {
228 if _
, existing
:= vars
[name
]; existing
{
229 log
.Panicln("Reuse of exported var name:", name
)
234 // Get retrieves a named exported variable.
235 func Get(name
string) Var
{
237 defer mutex
.RUnlock()
241 // Convenience functions for creating new exported variables.
243 func NewInt(name
string) *Int
{
249 func NewFloat(name
string) *Float
{
255 func NewMap(name
string) *Map
{
261 func NewString(name
string) *String
{
267 // Do calls f for each exported variable.
268 // The global variable map is locked during the iteration,
269 // but existing entries may be concurrently updated.
270 func Do(f
func(KeyValue
)) {
272 defer mutex
.RUnlock()
273 for k
, v
:= range vars
{
278 func expvarHandler(w http
.ResponseWriter
, r
*http
.Request
) {
279 w
.Header().Set("Content-Type", "application/json; charset=utf-8")
280 fmt
.Fprintf(w
, "{\n")
282 Do(func(kv KeyValue
) {
284 fmt
.Fprintf(w
, ",\n")
287 fmt
.Fprintf(w
, "%q: %s", kv
.Key
, kv
.Value
)
289 fmt
.Fprintf(w
, "\n}\n")
292 func cmdline() interface{} {
296 func memstats() interface{} {
297 stats
:= new(runtime
.MemStats
)
298 runtime
.ReadMemStats(stats
)
303 http
.HandleFunc("/debug/vars", expvarHandler
)
304 Publish("cmdline", Func(cmdline
))
305 Publish("memstats", Func(memstats
))