OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // The expvar package provides a standardized interface to public variables, | 5 // The expvar package provides a standardized interface to public variables, |
6 // such as operation counters in servers. It exposes these variables via | 6 // such as operation counters in servers. It exposes these variables via |
7 // HTTP at /debug/vars in JSON format. | 7 // HTTP at /debug/vars in JSON format. |
8 // | 8 // |
9 // Operations to set or modify these public variables are atomic. | 9 // Operations to set or modify these public variables are atomic. |
10 // | 10 // |
(...skipping 20 matching lines...) Expand all Loading... |
31 "runtime" | 31 "runtime" |
32 "strconv" | 32 "strconv" |
33 "sync" | 33 "sync" |
34 ) | 34 ) |
35 | 35 |
36 // Var is an abstract type for all exported variables. | 36 // Var is an abstract type for all exported variables. |
37 type Var interface { | 37 type Var interface { |
38 String() string | 38 String() string |
39 } | 39 } |
40 | 40 |
41 // Int is a 64-bit integer variable, and satisfies the Var interface. | 41 // Int is a 64-bit integer variable that satisfies the Var interface. |
42 type Int struct { | 42 type Int struct { |
43 i int64 | 43 i int64 |
44 mu sync.Mutex | 44 mu sync.Mutex |
45 } | 45 } |
46 | 46 |
47 func (v *Int) String() string { return strconv.Itoa64(v.i) } | 47 func (v *Int) String() string { return strconv.Itoa64(v.i) } |
48 | 48 |
49 func (v *Int) Add(delta int64) { | 49 func (v *Int) Add(delta int64) { |
50 v.mu.Lock() | 50 v.mu.Lock() |
51 defer v.mu.Unlock() | 51 defer v.mu.Unlock() |
52 v.i += delta | 52 v.i += delta |
53 } | 53 } |
54 | 54 |
55 func (v *Int) Set(value int64) { | 55 func (v *Int) Set(value int64) { |
56 v.mu.Lock() | 56 v.mu.Lock() |
57 defer v.mu.Unlock() | 57 defer v.mu.Unlock() |
58 v.i = value | 58 v.i = value |
59 } | 59 } |
60 | 60 |
61 // Map is a string-to-Var map variable, and satisfies the Var interface. | 61 // Float is a 64-bit float variable that satisfies the Var interface. |
| 62 type Float struct { |
| 63 » f float64 |
| 64 » mu sync.Mutex |
| 65 } |
| 66 |
| 67 func (v *Float) String() string { return strconv.Ftoa64(v.f, 'g', -1) } |
| 68 |
| 69 // Add adds delta to v. |
| 70 func (v *Float) Add(delta float64) { |
| 71 » v.mu.Lock() |
| 72 » defer v.mu.Unlock() |
| 73 » v.f += delta |
| 74 } |
| 75 |
| 76 // Set sets v to value. |
| 77 func (v *Float) Set(value float64) { |
| 78 » v.mu.Lock() |
| 79 » defer v.mu.Unlock() |
| 80 » v.f = value |
| 81 } |
| 82 |
| 83 // Map is a string-to-Var map variable that satisfies the Var interface. |
62 type Map struct { | 84 type Map struct { |
63 m map[string]Var | 85 m map[string]Var |
64 mu sync.Mutex | 86 mu sync.Mutex |
65 } | 87 } |
66 | 88 |
67 // KeyValue represents a single entry in a Map. | 89 // KeyValue represents a single entry in a Map. |
68 type KeyValue struct { | 90 type KeyValue struct { |
69 Key string | 91 Key string |
70 Value Var | 92 Value Var |
71 } | 93 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 av = new(Int) | 134 av = new(Int) |
113 v.m[key] = av | 135 v.m[key] = av |
114 } | 136 } |
115 | 137 |
116 // Add to Int; ignore otherwise. | 138 // Add to Int; ignore otherwise. |
117 if iv, ok := av.(*Int); ok { | 139 if iv, ok := av.(*Int); ok { |
118 iv.Add(delta) | 140 iv.Add(delta) |
119 } | 141 } |
120 } | 142 } |
121 | 143 |
| 144 // AddFloat adds delta to the *Float value stored under the given map key. |
| 145 func (v *Map) AddFloat(key string, delta float64) { |
| 146 v.mu.Lock() |
| 147 defer v.mu.Unlock() |
| 148 av, ok := v.m[key] |
| 149 if !ok { |
| 150 av = new(Float) |
| 151 v.m[key] = av |
| 152 } |
| 153 |
| 154 // Add to Float; ignore otherwise. |
| 155 if iv, ok := av.(*Float); ok { |
| 156 iv.Add(delta) |
| 157 } |
| 158 } |
| 159 |
122 // TODO(rsc): Make sure map access in separate thread is safe. | 160 // TODO(rsc): Make sure map access in separate thread is safe. |
123 func (v *Map) iterate(c chan<- KeyValue) { | 161 func (v *Map) iterate(c chan<- KeyValue) { |
124 for k, v := range v.m { | 162 for k, v := range v.m { |
125 c <- KeyValue{k, v} | 163 c <- KeyValue{k, v} |
126 } | 164 } |
127 close(c) | 165 close(c) |
128 } | 166 } |
129 | 167 |
130 func (v *Map) Iter() <-chan KeyValue { | 168 func (v *Map) Iter() <-chan KeyValue { |
131 c := make(chan KeyValue) | 169 c := make(chan KeyValue) |
132 go v.iterate(c) | 170 go v.iterate(c) |
133 return c | 171 return c |
134 } | 172 } |
135 | 173 |
136 // String is a string variable, and satisfies the Var interface. | 174 // String is a string variable, and satisfies the Var interface. |
137 type String struct { | 175 type String struct { |
138 s string | 176 s string |
139 } | 177 } |
140 | 178 |
141 func (v *String) String() string { return strconv.Quote(v.s) } | 179 func (v *String) String() string { return strconv.Quote(v.s) } |
142 | 180 |
143 func (v *String) Set(value string) { v.s = value } | 181 func (v *String) Set(value string) { v.s = value } |
144 | 182 |
145 // IntFunc wraps a func() int64 to create a value that satisfies the Var interfa
ce. | 183 // IntFunc wraps a func() int64 to create a value that satisfies the Var interfa
ce. |
146 // The function will be called each time the Var is evaluated. | 184 // The function will be called each time the Var is evaluated. |
147 type IntFunc func() int64 | 185 type IntFunc func() int64 |
148 | 186 |
149 func (v IntFunc) String() string { return strconv.Itoa64(v()) } | 187 func (v IntFunc) String() string { return strconv.Itoa64(v()) } |
150 | 188 |
| 189 // FloatFunc wraps a func() float64 to create a value that satisfies the Var int
erface. |
| 190 // The function will be called each time the Var is evaluated. |
| 191 type FloatFunc func() float64 |
| 192 |
| 193 func (v FloatFunc) String() string { return strconv.Ftoa64(v(), 'g', -1) } |
| 194 |
151 // StringFunc wraps a func() string to create value that satisfies the Var inter
face. | 195 // StringFunc wraps a func() string to create value that satisfies the Var inter
face. |
152 // The function will be called each time the Var is evaluated. | 196 // The function will be called each time the Var is evaluated. |
153 type StringFunc func() string | 197 type StringFunc func() string |
154 | 198 |
155 func (f StringFunc) String() string { return f() } | 199 func (f StringFunc) String() string { return strconv.Quote(f()) } |
156 | 200 |
157 | 201 |
158 // All published variables. | 202 // All published variables. |
159 var vars map[string]Var = make(map[string]Var) | 203 var vars map[string]Var = make(map[string]Var) |
160 var mutex sync.Mutex | 204 var mutex sync.Mutex |
161 | 205 |
162 // Publish declares an named exported variable. This should be called from a | 206 // Publish declares an named exported variable. This should be called from a |
163 // package's init function when it creates its Vars. If the name is already | 207 // package's init function when it creates its Vars. If the name is already |
164 // registered then this will log.Panic. | 208 // registered then this will log.Panic. |
165 func Publish(name string, v Var) { | 209 func Publish(name string, v Var) { |
(...skipping 19 matching lines...) Expand all Loading... |
185 } | 229 } |
186 | 230 |
187 // Convenience functions for creating new exported variables. | 231 // Convenience functions for creating new exported variables. |
188 | 232 |
189 func NewInt(name string) *Int { | 233 func NewInt(name string) *Int { |
190 v := new(Int) | 234 v := new(Int) |
191 Publish(name, v) | 235 Publish(name, v) |
192 return v | 236 return v |
193 } | 237 } |
194 | 238 |
| 239 func NewFloat(name string) *Float { |
| 240 v := new(Float) |
| 241 Publish(name, v) |
| 242 return v |
| 243 } |
| 244 |
195 func NewMap(name string) *Map { | 245 func NewMap(name string) *Map { |
196 v := new(Map).Init() | 246 v := new(Map).Init() |
197 Publish(name, v) | 247 Publish(name, v) |
198 return v | 248 return v |
199 } | 249 } |
200 | 250 |
201 func NewString(name string) *String { | 251 func NewString(name string) *String { |
202 v := new(String) | 252 v := new(String) |
203 Publish(name, v) | 253 Publish(name, v) |
204 return v | 254 return v |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 func cmdline() string { | 290 func cmdline() string { |
241 b, _ := json.Marshal(os.Args) | 291 b, _ := json.Marshal(os.Args) |
242 return string(b) | 292 return string(b) |
243 } | 293 } |
244 | 294 |
245 func init() { | 295 func init() { |
246 http.Handle("/debug/vars", http.HandlerFunc(expvarHandler)) | 296 http.Handle("/debug/vars", http.HandlerFunc(expvarHandler)) |
247 Publish("cmdline", StringFunc(cmdline)) | 297 Publish("cmdline", StringFunc(cmdline)) |
248 Publish("memstats", StringFunc(memstats)) | 298 Publish("memstats", StringFunc(memstats)) |
249 } | 299 } |
OLD | NEW |