9
9
"github.com/go-chi/chi/v5"
10
10
"github.com/go-chi/chi/v5/middleware"
11
11
"github.com/go-logr/logr"
12
+ "github.com/jmoiron/sqlx"
12
13
"github.com/prometheus/client_golang/prometheus"
13
14
"github.com/prometheus/client_golang/prometheus/promauto"
14
15
"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -18,8 +19,9 @@ import (
18
19
const metricsServerDisabledAddr = ""
19
20
20
21
type MetricsServerOptions struct {
21
- Logger logr.Logger
22
- Addr string
22
+ Logger logr.Logger
23
+ Addr string
24
+ Queryer sqlx.QueryerContext
23
25
}
24
26
25
27
func (opts * MetricsServerOptions ) bindCLIFlags (fs * pflag.FlagSet ) {
@@ -34,12 +36,19 @@ func (opts *MetricsServerOptions) defaults() error {
34
36
opts .Logger = logr .Discard ()
35
37
}
36
38
39
+ if opts .Addr != metricsServerDisabledAddr {
40
+ if opts .Queryer == nil {
41
+ return fmt .Errorf (".Queryer is required" )
42
+ }
43
+ }
44
+
37
45
return nil
38
46
}
39
47
40
48
type metricsServer struct {
41
- logger logr.Logger
42
- server * http.Server
49
+ logger logr.Logger
50
+ server * http.Server
51
+ queryer sqlx.QueryerContext
43
52
}
44
53
45
54
func NewMetricsServer (opts MetricsServerOptions ) (* metricsServer , error ) {
@@ -48,7 +57,8 @@ func NewMetricsServer(opts MetricsServerOptions) (*metricsServer, error) {
48
57
}
49
58
50
59
srv := & metricsServer {
51
- logger : opts .Logger ,
60
+ logger : opts .Logger ,
61
+ queryer : opts .Queryer ,
52
62
}
53
63
54
64
if opts .Addr == metricsServerDisabledAddr {
@@ -65,12 +75,48 @@ func NewMetricsServer(opts MetricsServerOptions) (*metricsServer, error) {
65
75
return srv , nil
66
76
}
67
77
78
+ func (server * metricsServer ) monitorDatabaseSize (
79
+ done <- chan struct {},
80
+ observeFn func (sizeInBytes float64 ),
81
+ ) {
82
+ const dbSizeQuery = `SELECT
83
+ page_count * page_size
84
+ FROM pragma_page_count(), pragma_page_size();`
85
+
86
+ observe := func () {
87
+ var size int64
88
+ err := server .queryer .QueryRowxContext (context .Background (), dbSizeQuery ).Scan (& size )
89
+ if err != nil {
90
+ server .logger .Error (err , "failed to get database size" )
91
+ return
92
+ }
93
+
94
+ observeFn (float64 (size ))
95
+ }
96
+ observe ()
97
+
98
+ ticker := time .NewTicker (30 * time .Second )
99
+ defer ticker .Stop ()
100
+ for {
101
+ select {
102
+ case <- done :
103
+ return
104
+ case <- ticker .C :
105
+ observe ()
106
+ }
107
+ }
108
+ }
109
+
68
110
func (server * metricsServer ) Start (done <- chan struct {}) {
69
111
if server .server == nil {
70
112
server .logger .V (8 ).Info ("metrics server is disabled" )
71
113
return
72
114
}
73
115
116
+ go server .monitorDatabaseSize (done , func (sizeInBytes float64 ) {
117
+ metricsDatabaseSize .Set (sizeInBytes )
118
+ server .logger .V (8 ).Info ("database size" , "sizeInBytes" , sizeInBytes )
119
+ })
74
120
go server .server .ListenAndServe ()
75
121
76
122
server .logger .Info ("metrics server started" , "addr" , server .server .Addr )
@@ -124,6 +170,14 @@ var (
124
170
},
125
171
[]string {metricsLabelTarget , metricsLabelTargetOperation , metricsLabelHTTPCode },
126
172
)
173
+
174
+ metricsDatabaseSize = promauto .NewGauge (
175
+ prometheus.GaugeOpts {
176
+ Namespace : metricsNamespace ,
177
+ Name : "database_size_bytes" ,
178
+ Help : "Size of the database file" ,
179
+ },
180
+ )
127
181
)
128
182
129
183
func recordRequestMetrics (op string ) func (http.Handler ) http.Handler {
0 commit comments