forked from j2gg0s/otsql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdbstats.go
More file actions
116 lines (94 loc) · 2.94 KB
/
dbstats.go
File metadata and controls
116 lines (94 loc) · 2.94 KB
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
package otsql
import (
"context"
"database/sql"
"fmt"
"sync"
"time"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/label"
)
var dbs = map[*sql.DB]string{}
var dbsLock sync.Mutex
var (
batchObserver metric.BatchObserver
connIdle metric.Int64UpDownSumObserver
connInUse metric.Int64UpDownSumObserver
connWait metric.Int64SumObserver
connIdleClosed metric.Int64SumObserver
connLifetimeClosed metric.Int64SumObserver
connWaitDurationNS metric.Int64SumObserver
lastDBStats time.Time
dbStats sql.DBStats
)
// RecordStats records database statistics for provided sql.DB.
// The interval is controlled by meter, default more than 10 seconds.
func RecordStats(db *sql.DB, instanceName string) (err error) {
dbsLock.Lock()
defer dbsLock.Unlock()
defer func() {
if err == nil {
dbs[db] = instanceName
}
}()
if len(dbs) > 0 {
return nil
}
batchObserver = meter.NewBatchObserver(func(ctx context.Context, result metric.BatchObserverResult) {
now := time.Now()
if now.Sub(lastDBStats) < time.Second {
return
}
lastDBStats = now
for db, instanceName := range dbs {
dbStats = db.Stats()
result.Observe(
[]label.KeyValue{label.String(sqlInstance, instanceName)},
connInUse.Observation(int64(dbStats.InUse)),
connIdle.Observation(int64(dbStats.Idle)),
connWait.Observation(dbStats.WaitCount),
connIdleClosed.Observation(dbStats.MaxIdleClosed),
connLifetimeClosed.Observation(dbStats.MaxLifetimeClosed),
connWaitDurationNS.Observation(dbStats.WaitDuration.Nanoseconds()),
)
}
})
formatter := func(s string) string { return s }
if connInUse, err = batchObserver.NewInt64UpDownSumObserver(
formatter("go.sql.conn.in_use"),
metric.WithDescription(fmt.Sprintf("The number of connections currently in use: %s", instanceName)),
); err != nil {
return err
}
if connIdle, err = batchObserver.NewInt64UpDownSumObserver(
formatter("go.sql.conn.idle"),
metric.WithDescription(fmt.Sprintf("The number of idle connections: %s", instanceName)),
); err != nil {
return err
}
if connWait, err = batchObserver.NewInt64SumObserver(
formatter("go.sql.conn.wait"),
metric.WithDescription("The total number of connections wait for"),
); err != nil {
return err
}
if connIdleClosed, err = batchObserver.NewInt64SumObserver(
formatter("go.sql.conn.idle_closed"),
metric.WithDescription("The total number of connections closed because of SetMaxIdleConns"),
); err != nil {
return err
}
if connLifetimeClosed, err = batchObserver.NewInt64SumObserver(
formatter("go.sql.conn.lifetime_closed"),
metric.WithDescription("The total number of connections closed because of SetConnMaxLifetime"),
); err != nil {
return err
}
if connWaitDurationNS, err = batchObserver.NewInt64SumObserver(
formatter("go.sql.conn.wait_ns"),
metric.WithDescription("The total time blocked by waiting for a new connection, nanosecond."),
); err != nil {
return err
}
return nil
}