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 { return strconv.FormatInt(v.i, 10) }
49 func (v *Int) Add(delta int64) {
55 func (v *Int) Set(value int64) {
61 // Float is a 64-bit float variable that satisfies the Var interface.
67 func (v *Float) String() string { return strconv.FormatFloat(v.f, 'g', -1, 64) }
69 // Add adds delta to v.
70 func (v *Float) Add(delta float64) {
76 // Set sets v to value.
77 func (v *Float) Set(value float64) {
83 // Map is a string-to-Var map variable that satisfies the Var interface.
89 // KeyValue represents a single entry in a Map.
90 type KeyValue struct {
95 func (v *Map) String() string {
98 b := new(bytes.Buffer)
101 for key, val := range v.m {
105 fmt.Fprintf(b, "\"%s\": %v", key, val)
112 func (v *Map) Init() *Map {
113 v.m = make(map[string]Var)
117 func (v *Map) Get(key string) Var {
123 func (v *Map) Set(key string, av Var) {
129 func (v *Map) Add(key string, delta int64) {
134 // check again under the write lock
136 if _, ok = v.m[key]; !ok {
143 // Add to Int; ignore otherwise.
144 if iv, ok := av.(*Int); ok {
149 // AddFloat adds delta to the *Float value stored under the given map key.
150 func (v *Map) AddFloat(key string, delta float64) {
155 // check again under the write lock
157 if _, ok = v.m[key]; !ok {
164 // Add to Float; ignore otherwise.
165 if iv, ok := av.(*Float); ok {
170 // Do calls f for each entry in the map.
171 // The map is locked during the iteration,
172 // but existing entries may be concurrently updated.
173 func (v *Map) Do(f func(KeyValue)) {
176 for k, v := range v.m {
181 // String is a string variable, and satisfies the Var interface.
186 func (v *String) String() string { return strconv.Quote(v.s) }
188 func (v *String) Set(value string) { v.s = value }
190 // Func implements Var by calling the function
191 // and formatting the returned value using JSON.
192 type Func func() interface{}
194 func (f Func) String() string {
195 v, _ := json.Marshal(f())
199 // All published variables.
202 vars map[string]Var = make(map[string]Var)
205 // Publish declares a named exported variable. This should be called from a
206 // package's init function when it creates its Vars. If the name is already
207 // registered then this will log.Panic.
208 func Publish(name string, v Var) {
211 if _, existing := vars[name]; existing {
212 log.Panicln("Reuse of exported var name:", name)
217 // Get retrieves a named exported variable.
218 func Get(name string) Var {
220 defer mutex.RUnlock()
224 // Convenience functions for creating new exported variables.
226 func NewInt(name string) *Int {
232 func NewFloat(name string) *Float {
238 func NewMap(name string) *Map {
244 func NewString(name string) *String {
250 // Do calls f for each exported variable.
251 // The global variable map is locked during the iteration,
252 // but existing entries may be concurrently updated.
253 func Do(f func(KeyValue)) {
255 defer mutex.RUnlock()
256 for k, v := range vars {
261 func expvarHandler(w http.ResponseWriter, r *http.Request) {
262 w.Header().Set("Content-Type", "application/json; charset=utf-8")
263 fmt.Fprintf(w, "{\n")
265 Do(func(kv KeyValue) {
267 fmt.Fprintf(w, ",\n")
270 fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
272 fmt.Fprintf(w, "\n}\n")
275 func cmdline() interface{} {
279 func memstats() interface{} {
280 stats := new(runtime.MemStats)
281 runtime.ReadMemStats(stats)
286 http.HandleFunc("/debug/vars", expvarHandler)
287 Publish("cmdline", Func(cmdline))
288 Publish("memstats", Func(memstats))