This repository has been archived by the owner on Sep 17, 2020. It is now read-only.
forked from instana/go-sensor
-
Notifications
You must be signed in to change notification settings - Fork 1
/
meter.go
157 lines (136 loc) · 3.75 KB
/
meter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package instana
import (
"runtime"
"strconv"
"time"
)
const (
// SnapshotPeriod is the amount of time in seconds between snapshot reports.
SnapshotPeriod = 600
)
// SnapshotS struct to hold snapshot data.
type SnapshotS struct {
Name string `json:"name"`
Version string `json:"version"`
Root string `json:"goroot"`
MaxProcs int `json:"maxprocs"`
Compiler string `json:"compiler"`
NumCPU int `json:"cpu"`
}
// MemoryS struct to hold snapshot data.
type MemoryS struct {
Alloc uint64 `json:"alloc"`
TotalAlloc uint64 `json:"total_alloc"`
Sys uint64 `json:"sys"`
Lookups uint64 `json:"lookups"`
Mallocs uint64 `json:"mallocs"`
Frees uint64 `json:"frees"`
HeapAlloc uint64 `json:"heap_alloc"`
HeapSys uint64 `json:"heap_sys"`
HeapIdle uint64 `json:"heap_idle"`
HeapInuse uint64 `json:"heap_in_use"`
HeapReleased uint64 `json:"heap_released"`
HeapObjects uint64 `json:"heap_objects"`
PauseTotalNs uint64 `json:"pause_total_ns"`
PauseNs uint64 `json:"pause_ns"`
NumGC uint32 `json:"num_gc"`
GCCPUFraction float64 `json:"gc_cpu_fraction"`
}
// MetricsS struct to hold snapshot data.
type MetricsS struct {
CgoCall int64 `json:"cgo_call"`
Goroutine int `json:"goroutine"`
Memory *MemoryS `json:"memory"`
}
// EntityData struct to hold snapshot data.
type EntityData struct {
PID int `json:"pid"`
Snapshot *SnapshotS `json:"snapshot,omitempty"`
Metrics *MetricsS `json:"metrics"`
}
type meterS struct {
sensor *sensorS
numGC uint32
ticker *time.Ticker
snapshotCountdown int
}
func (r *meterS) init() {
r.ticker = time.NewTicker(1 * time.Second)
go func() {
r.snapshotCountdown = 1
for range r.ticker.C {
if r.sensor.agent.canSend() {
r.snapshotCountdown--
var s *SnapshotS
if r.snapshotCountdown == 0 {
r.snapshotCountdown = SnapshotPeriod
s = r.collectSnapshot()
log.debug("collected snapshot")
} else {
s = nil
}
pid, _ := strconv.Atoi(r.sensor.agent.from.PID)
d := &EntityData{
PID: pid,
Snapshot: s,
Metrics: r.collectMetrics()}
go r.send(d)
}
}
}()
}
func (r *meterS) send(d *EntityData) {
_, err := r.sensor.agent.request(r.sensor.agent.makeURL(agentDataURL), "POST", d)
if err != nil {
r.sensor.agent.reset()
}
}
func (r *meterS) collectMemoryMetrics() *MemoryS {
var memStats runtime.MemStats
runtime.ReadMemStats(&memStats)
ret := &MemoryS{
Alloc: memStats.Alloc,
TotalAlloc: memStats.TotalAlloc,
Sys: memStats.Sys,
Lookups: memStats.Lookups,
Mallocs: memStats.Mallocs,
Frees: memStats.Frees,
HeapAlloc: memStats.HeapAlloc,
HeapSys: memStats.HeapSys,
HeapIdle: memStats.HeapIdle,
HeapInuse: memStats.HeapInuse,
HeapReleased: memStats.HeapReleased,
HeapObjects: memStats.HeapObjects,
PauseTotalNs: memStats.PauseTotalNs,
NumGC: memStats.NumGC,
GCCPUFraction: memStats.GCCPUFraction}
if r.numGC < memStats.NumGC {
ret.PauseNs = memStats.PauseNs[(memStats.NumGC+255)%256]
r.numGC = memStats.NumGC
} else {
ret.PauseNs = 0
}
return ret
}
func (r *meterS) collectMetrics() *MetricsS {
return &MetricsS{
CgoCall: runtime.NumCgoCall(),
Goroutine: runtime.NumGoroutine(),
Memory: r.collectMemoryMetrics()}
}
func (r *meterS) collectSnapshot() *SnapshotS {
return &SnapshotS{
Name: r.sensor.serviceName,
Version: runtime.Version(),
Root: runtime.GOROOT(),
MaxProcs: runtime.GOMAXPROCS(0),
Compiler: runtime.Compiler,
NumCPU: runtime.NumCPU()}
}
func (r *sensorS) initMeter() *meterS {
log.debug("initializing meter")
ret := new(meterS)
ret.sensor = r
ret.init()
return ret
}