11package stats
22
3- import "time "
3+ import "sync "
44
5- // Counter is an immutable data strcture that can be used to represent metrics
6- // that accumulate values.
5+ // A Counter represent a metric that is monotonically increasing.
76type Counter struct {
8- eng * Engine // the parent engine
9- key string // cached metric key
10- name string // the name of the counter
11- tags []Tag // the tags set on the counter
12- }
13-
14- // C returns a new counter that produces metrics on the default engine.
15- func C (name string , tags ... Tag ) Counter {
16- return MakeCounter (nil , name , tags ... )
17- }
18-
19- // MakeCounter returns a new counter that produces metrics on the given engine.
20- func MakeCounter (engine * Engine , name string , tags ... Tag ) Counter {
21- return makeCounter (engine , name , copyTags (tags ))
7+ mutex sync.Mutex
8+ value float64 // current value of the counter
9+ eng * Engine // the engine to produce metrics on
10+ name string // the name of the counter
11+ tags []Tag // the tags set on the counter
2212}
2313
2414// Name returns the name of the counter.
25- func (c Counter ) Name () string {
15+ func (c * Counter ) Name () string {
2616 return c .name
2717}
2818
2919// Tags returns the list of tags set on the counter.
3020//
31- // The returned slice is a copy of the internal slice maintained by the counter,
32- // the program owns it and can safely modify it without affecting the counter.
33- func (c Counter ) Tags () []Tag {
34- return copyTags (c .tags )
21+ // The method returns a reference to the counter's internal tag slice, it does
22+ // not make a copy. It's expected that the program will treat this value as a
23+ // read-only list and won't modify its content.
24+ func (c * Counter ) Tags () []Tag {
25+ return c .tags
3526}
3627
37- // Clone returns a copy of the counter, potentially setting tags on the returned
28+ // Value returns the current value of the counter.
29+ func (c * Counter ) Value () float64 {
30+ return c .value
31+ }
32+
33+ // WithTags returns a copy of the counter, potentially setting tags on the returned
3834// object.
39- func (c Counter ) Clone (tags ... Tag ) Counter {
40- if len (tags ) == 0 {
41- return c
35+ //
36+ // The internal value of the returned counter is set to zero.
37+ func (c * Counter ) WithTags (tags ... Tag ) * Counter {
38+ return & Counter {
39+ eng : c .eng ,
40+ name : c .name ,
41+ tags : concatTags (c .tags , tags ),
4242 }
43- return makeCounter (c .eng , c .name , concatTags (c .tags , tags ))
4443}
4544
4645// Incr increments the counter by a value of 1.
47- func (c Counter ) Incr () {
46+ func (c * Counter ) Incr () {
4847 c .Add (1 )
4948}
5049
5150// Add adds a value to the counter.
5251//
5352// Note that most data collection systems expect counters to be monotonically
5453// increasing so the program should not call this method with negative values.
55- func (c Counter ) Add (value float64 ) {
56- c .eng .Add (CounterType , c .key , c .name , c .tags , value , time .Now ())
54+ func (c * Counter ) Add (value float64 ) {
55+ c .mutex .Lock ()
56+ c .value += value
57+ c .mutex .Unlock ()
58+ c .eng .Add (c .name , value , c .tags ... )
5759}
5860
5961// Set sets the value of the counter.
@@ -64,16 +66,13 @@ func (c Counter) Add(value float64) {
6466//
6567// This method is useful for reporting values of counters that aren't managed
6668// by the application itself, like CPU ticks for example.
67- func (c Counter ) Set (value float64 ) {
68- c .eng .Add (CounterType , c .key , c .name , c .tags , value , time .Now ())
69- }
70-
71- func makeCounter (eng * Engine , name string , tags []Tag ) Counter {
72- sortTags (tags )
73- return Counter {
74- eng : eng ,
75- key : MetricKey (name , tags ),
76- name : name ,
77- tags : tags ,
69+ func (c * Counter ) Set (value float64 ) {
70+ c .mutex .Lock ()
71+ if value < c .value {
72+ c .value = value
73+ } else {
74+ c .value , value = value , value - c .value
7875 }
76+ c .mutex .Unlock ()
77+ c .eng .Add (c .name , value , c .tags ... )
7978}
0 commit comments