Skip to content

Commit be5e9a4

Browse files
committed
add stats
1 parent 326ed70 commit be5e9a4

File tree

7 files changed

+519
-12
lines changed

7 files changed

+519
-12
lines changed

Corefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
. {
1+
.:5333 {
22
datahub {
33
debug
44
geoip_path data/geoip.dat

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ module github.com/ca17/datahub
33
go 1.16
44

55
require (
6+
github.com/ahmetb/go-linq v3.0.0+incompatible
67
github.com/allegro/bigcache v1.2.1
78
github.com/c-robinson/iplib v1.0.3
89
github.com/ca17/dnssrc v0.0.2
910
github.com/coredns/caddy v1.1.1
1011
github.com/coredns/coredns v1.8.6
1112
github.com/dnstap/golang-dnstap v0.4.0
1213
github.com/form3tech-oss/jwt-go v3.2.3+incompatible
13-
github.com/go-ozzo/ozzo-routing v2.1.4+incompatible // indirect
14-
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f // indirect
1514
github.com/golang/protobuf v1.5.2
15+
github.com/metaslink/metasdns v0.0.0-20211230190103-80ba25a91d75
1616
github.com/miekg/dns v1.1.43
17-
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc
17+
github.com/orcaman/concurrent-map v1.0.0
1818
github.com/qiangxue/fasthttp-routing v0.0.0-20160225050629-6ccdc2a18d87
1919
github.com/robfig/cron/v3 v3.0.1
2020
github.com/valyala/fasthttp v1.31.0

go.sum

+290-8
Large diffs are not rendered by default.

plugin/pkg/stats/dns.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package stats
2+
3+
import (
4+
"sort"
5+
"sync"
6+
"time"
7+
8+
_ "github.com/ahmetb/go-linq"
9+
)
10+
11+
type DayDnsStat struct {
12+
sync.RWMutex
13+
LastRolling time.Time
14+
Interval time.Duration
15+
Values map[int64]map[string]int64
16+
}
17+
18+
func NewDayDnsStat(ival time.Duration) *DayDnsStat {
19+
return &DayDnsStat{LastRolling: time.Now(), Interval: ival, Values: map[int64]map[string]int64{}}
20+
}
21+
22+
// Rolling 滚动清除老数据
23+
func (d *DayDnsStat) Rolling() {
24+
d.Lock()
25+
defer d.Unlock()
26+
d.LastRolling = time.Now()
27+
keys := make([]int64, 0)
28+
for _k, _ := range d.Values {
29+
keys = append(keys, _k)
30+
}
31+
sort.Slice(keys, func(i, j int) bool {
32+
return keys[i] < keys[j]
33+
})
34+
s := time.Now().Add(-d.Interval).Unix() * 1000
35+
for _, key := range keys {
36+
if s > key {
37+
d.Values[key] = nil
38+
delete(d.Values, key)
39+
}
40+
}
41+
}
42+
43+
func (d *DayDnsStat) Update(c *CounterStat) {
44+
if time.Now().Sub(d.LastRolling).Seconds() > 120 {
45+
d.Rolling()
46+
}
47+
v := c.MapValues()
48+
d.Lock()
49+
defer d.Unlock()
50+
if len(v) > 0 {
51+
d.Values[time.Now().Unix()*1000] = v
52+
}
53+
}
54+
55+
func (d *DayDnsStat) LineChartData(name string) *LineChartData {
56+
d.RLock()
57+
defer d.RUnlock()
58+
keys := make([]int64, 0)
59+
for _k, _ := range d.Values {
60+
keys = append(keys, _k)
61+
}
62+
sort.Slice(keys, func(i, j int) bool {
63+
return keys[i] < keys[j]
64+
})
65+
ld := NewLineChartData(name, "")
66+
for _, key := range keys {
67+
ld.Times = append(ld.Times, time.UnixMilli(key).Format(time.RFC3339))
68+
for ik, iv := range d.Values[key] {
69+
if _, ok := ld.Datas[ik]; !ok {
70+
ld.Datas[ik] = make([]int64, 0)
71+
}
72+
ld.Datas[ik] = append(ld.Datas[ik], iv)
73+
}
74+
}
75+
76+
return ld
77+
}

plugin/pkg/stats/dns_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package stats
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/metaslink/metasdns/plugin/pkg/common"
8+
)
9+
10+
func TestNewDayDnsStat(t *testing.T) {
11+
ds := NewDayDnsStat(time.Second * 15)
12+
c := NewCounterStat()
13+
start := time.Now()
14+
for {
15+
if time.Now().Sub(start).Seconds() > 12 {
16+
break
17+
}
18+
c.Incr("cn", 1)
19+
time.Sleep(time.Second * 3)
20+
c.Incr("cn", 1)
21+
c.Incr("ads", 1)
22+
t.Log("...")
23+
ds.Update(c)
24+
}
25+
ds.Rolling()
26+
t.Log(common.ToJson(ds.LineChartData("最近24小时统计").ChartData()))
27+
}

plugin/pkg/stats/line.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package stats
2+
3+
import (
4+
"github.com/ahmetb/go-linq"
5+
)
6+
7+
type LineChartData struct {
8+
Title string `json:"title"`
9+
YaxisName string `json:"yaxis_name"`
10+
Times []string `json:"times"`
11+
Datas map[string][]int64 `json:"datas"`
12+
}
13+
14+
func NewLineChartData(title string, yaxisName string) *LineChartData {
15+
return &LineChartData{Title: title, YaxisName: yaxisName, Times: make([]string, 0), Datas: make(map[string][]int64, 0)}
16+
}
17+
18+
func (l *LineChartData) ChartData() *LineChartData {
19+
linq.From(l.Datas).ForEachT(func(kv linq.KeyValue) {
20+
var last int64 = 0
21+
vals := make([]int64, 0)
22+
linq.From(kv.Value).ForEachT(func(v int64) {
23+
var val int64 = 0
24+
if last == 0 {
25+
val = 0
26+
last = v
27+
} else {
28+
val = v - last
29+
if val < 0 {
30+
val = 0
31+
}
32+
last = v
33+
}
34+
vals = append(vals, val)
35+
})
36+
l.Datas[kv.Key.(string)] = vals
37+
})
38+
return l
39+
}

plugin/pkg/stats/stats.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package stats
2+
3+
import (
4+
"sync"
5+
"sync/atomic"
6+
)
7+
8+
type Metrics struct {
9+
Icon string
10+
Value interface{}
11+
Title string
12+
}
13+
14+
func NewMetrics(icon string, value interface{}, title string) *Metrics {
15+
return &Metrics{Icon: icon, Value: value, Title: title}
16+
}
17+
18+
type Counter struct {
19+
Name string `json:"name"`
20+
Value int64 `json:"value"`
21+
}
22+
23+
func NewCounter(name string, value int64) *Counter {
24+
return &Counter{Name: name, Value: value}
25+
}
26+
27+
func (d *Counter) Incr(v int64) {
28+
atomic.AddInt64(&d.Value, v)
29+
}
30+
31+
func (d *Counter) Val() int64 {
32+
return d.Value
33+
}
34+
35+
type CounterStat struct {
36+
sync.RWMutex
37+
cmap map[string]*Counter
38+
}
39+
40+
func NewCounterStat() *CounterStat {
41+
return &CounterStat{cmap: make(map[string]*Counter)}
42+
}
43+
44+
func (c *CounterStat) Incr(name string, v int64) {
45+
c.Lock()
46+
defer c.Unlock()
47+
if ct, ok := c.cmap[name]; ok {
48+
ct.Incr(v)
49+
} else {
50+
c.cmap[name] = NewCounter(name, v)
51+
}
52+
}
53+
54+
func (c *CounterStat) MapValues() map[string]int64 {
55+
mv := make(map[string]int64)
56+
c.RLock()
57+
defer c.RUnlock()
58+
for k, counter := range c.cmap {
59+
mv[k] = counter.Val()
60+
}
61+
return mv
62+
}
63+
64+
func (c *CounterStat) Values() []Counter {
65+
c.RLock()
66+
defer c.RUnlock()
67+
var result = make([]Counter, 0)
68+
for _, v := range c.cmap {
69+
result = append(result, *v)
70+
}
71+
return result
72+
}
73+
74+
func (c *CounterStat) GetValue(name string) int64 {
75+
c.RLock()
76+
defer c.RUnlock()
77+
if ct, ok := c.cmap[name]; ok {
78+
return ct.Val()
79+
} else {
80+
return 0
81+
}
82+
}

0 commit comments

Comments
 (0)