master
go 110 lines 2.23 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package oldmetrix
4
5 import (
6 "github.com/axiomhq/hyperloglog"
7
8 "github.com/netdata/netdata/go/plugins/pkg/stm"
9 )
10
11 type (
12 UniqueCounter interface {
13 stm.Value
14 Insert(s string)
15 Value() int
16 Reset()
17 }
18
19 mapUniqueCounter struct {
20 m map[string]bool
21 }
22
23 hyperLogLogUniqueCounter struct {
24 sketch *hyperloglog.Sketch
25 }
26
27 UniqueCounterVec struct {
28 useHyperLogLog bool
29 Items map[string]UniqueCounter
30 }
31 )
32
33 var (
34 _ stm.Value = mapUniqueCounter{}
35 _ stm.Value = hyperLogLogUniqueCounter{}
36 _ stm.Value = UniqueCounterVec{}
37 )
38
39 func NewUniqueCounter(useHyperLogLog bool) UniqueCounter {
40 if useHyperLogLog {
41 return &hyperLogLogUniqueCounter{hyperloglog.New()}
42 }
43 return mapUniqueCounter{map[string]bool{}}
44 }
45
46 func (c mapUniqueCounter) WriteTo(rv map[string]int64, key string, mul, div int) {
47 rv[key] = int64(float64(c.Value()*mul) / float64(div))
48 }
49
50 func (c mapUniqueCounter) Insert(s string) {
51 c.m[s] = true
52 }
53
54 func (c mapUniqueCounter) Value() int {
55 return len(c.m)
56 }
57
58 func (c mapUniqueCounter) Reset() {
59 for key := range c.m {
60 delete(c.m, key)
61 }
62 }
63
64 // WriteTo writes its value into given map.
65 func (c hyperLogLogUniqueCounter) WriteTo(rv map[string]int64, key string, mul, div int) {
66 rv[key] = int64(float64(c.Value()*mul) / float64(div))
67 }
68
69 func (c *hyperLogLogUniqueCounter) Insert(s string) {
70 c.sketch.Insert([]byte(s))
71 }
72
73 func (c *hyperLogLogUniqueCounter) Value() int {
74 return int(c.sketch.Estimate())
75 }
76
77 func (c *hyperLogLogUniqueCounter) Reset() {
78 c.sketch = hyperloglog.New()
79 }
80
81 func NewUniqueCounterVec(useHyperLogLog bool) UniqueCounterVec {
82 return UniqueCounterVec{
83 Items: map[string]UniqueCounter{},
84 useHyperLogLog: useHyperLogLog,
85 }
86 }
87
88 // WriteTo writes its value into given map.
89 func (c UniqueCounterVec) WriteTo(rv map[string]int64, key string, mul, div int) {
90 for name, value := range c.Items {
91 value.WriteTo(rv, key+"_"+name, mul, div)
92 }
93 }
94
95 // Get gets UniqueCounter instance by name
96 func (c UniqueCounterVec) Get(name string) UniqueCounter {
97 item, ok := c.Items[name]
98 if ok {
99 return item
100 }
101 item = NewUniqueCounter(c.useHyperLogLog)
102 c.Items[name] = item
103 return item
104 }
105
106 func (c UniqueCounterVec) Reset() {
107 for _, value := range c.Items {
108 value.Reset()
109 }
110 }