@@ -24,19 +24,18 @@ import (
24
24
"fmt"
25
25
"io"
26
26
"net/http"
27
- "strconv"
28
27
"strings"
29
28
"sync"
30
29
"time"
31
30
32
- "github.com/prometheus/client_golang/prometheus"
33
- "github.com/prometheus/client_golang/prometheus/promauto"
31
+ "github.com/transparency-dev/static-ct/internal/otel"
34
32
"github.com/transparency-dev/static-ct/internal/types/rfc6962"
35
33
"github.com/transparency-dev/static-ct/internal/types/tls"
36
34
"github.com/transparency-dev/static-ct/internal/x509util"
37
35
"github.com/transparency-dev/static-ct/modules/dedup"
38
36
tessera "github.com/transparency-dev/trillian-tessera"
39
37
"github.com/transparency-dev/trillian-tessera/ctonly"
38
+ "go.opentelemetry.io/otel/metric"
40
39
"k8s.io/klog/v2"
41
40
)
42
41
@@ -50,7 +49,7 @@ const (
50
49
)
51
50
52
51
// entrypointName identifies a CT entrypoint as defined in section 4 of RFC 6962.
53
- type entrypointName string
52
+ type entrypointName = string
54
53
55
54
// Constants for entrypoint names, as exposed in statistics/logging.
56
55
const (
@@ -63,53 +62,38 @@ var (
63
62
// Metrics are all per-log (label "origin"), but may also be
64
63
// per-entrypoint (label "ep") or per-return-code (label "rc").
65
64
once sync.Once
66
- knownLogs * prometheus. GaugeVec // origin => value (always 1.0)
67
- lastSCTIndex * prometheus. GaugeVec // origin => value
68
- lastSCTTimestamp * prometheus. GaugeVec // origin => value
69
- reqsCounter * prometheus. CounterVec // origin, op => value
70
- rspsCounter * prometheus. CounterVec // origin, op, code => value
71
- rspLatency * prometheus. HistogramVec // origin, op, code => value
65
+ knownLogs metric. Int64Gauge // origin => value (always 1.0)
66
+ lastSCTIndex metric. Int64Gauge // origin => value
67
+ lastSCTTimestamp metric. Int64Gauge // origin => value
68
+ reqsCounter metric. Int64Counter // origin, op => value
69
+ rspsCounter metric. Int64Counter // origin, op, code => value
70
+ rspLatency metric. Float64Histogram // origin, op, code => value
72
71
)
73
72
74
73
// setupMetrics initializes all the exported metrics.
75
74
func setupMetrics () {
76
75
// TODO(phboneff): add metrics for deduplication and chain storage.
77
- knownLogs = promauto .NewGaugeVec (
78
- prometheus.GaugeOpts {
79
- Name : "known_logs" ,
80
- Help : "Set to 1 for known logs" ,
81
- },
82
- []string {"origin" })
83
- lastSCTTimestamp = promauto .NewGaugeVec (
84
- prometheus.GaugeOpts {
85
- Name : "last_sct_timestamp" ,
86
- Help : "Time of last SCT in ms since epoch" ,
87
- },
88
- []string {"origin" })
89
- lastSCTIndex = promauto .NewGaugeVec (
90
- prometheus.GaugeOpts {
91
- Name : "last_sct_index" ,
92
- Help : "Index of last SCT" ,
93
- },
94
- []string {"origin" })
95
- reqsCounter = promauto .NewCounterVec (
96
- prometheus.CounterOpts {
97
- Name : "http_reqs" ,
98
- Help : "Number of requests" ,
99
- },
100
- []string {"origin" , "ep" })
101
- rspsCounter = promauto .NewCounterVec (
102
- prometheus.CounterOpts {
103
- Name : "http_rsps" ,
104
- Help : "Number of responses" ,
105
- },
106
- []string {"origin" , "op" , "code" })
107
- rspLatency = promauto .NewHistogramVec (
108
- prometheus.HistogramOpts {
109
- Name : "http_latency" ,
110
- Help : "Latency of responses in seconds" ,
111
- },
112
- []string {"origin" , "op" , "code" })
76
+ knownLogs = mustCreate (meter .Int64Gauge ("tesseract.known_logs" ,
77
+ metric .WithDescription ("Set to 1 for known logs" )))
78
+
79
+ lastSCTTimestamp = mustCreate (meter .Int64Gauge ("tesseract.last_sct.timestamp" ,
80
+ metric .WithDescription ("Time of last SCT since epoch" ),
81
+ metric .WithUnit ("ms" )))
82
+
83
+ lastSCTIndex = mustCreate (meter .Int64Gauge ("tesseract.last_sct.index" ,
84
+ metric .WithDescription ("Index of last SCT" ),
85
+ metric .WithUnit ("{entry}" )))
86
+
87
+ reqsCounter = mustCreate (meter .Int64Counter ("tesseract.http_request.count" ,
88
+ metric .WithDescription ("CT HTTP requests" )))
89
+
90
+ rspsCounter = mustCreate (meter .Int64Counter ("tesseract.http_response.count" ,
91
+ metric .WithDescription ("CT HTTP responses" )))
92
+
93
+ rspLatency = mustCreate (meter .Float64Histogram ("tesseract.http_response.duration" ,
94
+ metric .WithDescription ("CT HTTP response duration" ),
95
+ metric .WithExplicitBucketBoundaries (otel .LatencyHistogramBuckets ... ),
96
+ metric .WithUnit ("ms" )))
113
97
}
114
98
115
99
// entrypoints is a list of entrypoint names as exposed in statistics/logging.
@@ -132,16 +116,18 @@ type appHandler struct {
132
116
// does additional common error and stats processing.
133
117
func (a appHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
134
118
var statusCode int
135
- label0 := a .log .origin
136
- label1 := string (a .name )
137
- reqsCounter .WithLabelValues (label0 , label1 ).Inc ()
119
+
120
+ originAttr := originKey .String (a .log .origin )
121
+ operationAttr := operationKey .String (a .name )
122
+ reqsCounter .Add (r .Context (), 1 , metric .WithAttributes (originAttr , operationAttr ))
138
123
startTime := a .opts .TimeSource .Now ()
139
124
logCtx := a .opts .RequestLog .start (r .Context ())
140
125
a .opts .RequestLog .origin (logCtx , a .log .origin )
141
126
defer func () {
142
127
latency := a .opts .TimeSource .Now ().Sub (startTime ).Seconds ()
143
- rspLatency .WithLabelValues ( label0 , label1 , strconv . Itoa ( statusCode )). Observe ( latency )
128
+ rspLatency .Record ( r . Context (), latency , metric . WithAttributes ( originAttr , operationAttr , codeKey . Int ( statusCode )))
144
129
}()
130
+
145
131
klog .V (2 ).Infof ("%s: request %v %q => %s" , a .log .origin , r .Method , r .URL , a .name )
146
132
// TODO(phboneff): add a.Method directly on the handler path and remove this test.
147
133
if r .Method != a .method {
@@ -169,7 +155,7 @@ func (a appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
169
155
statusCode , err = a .handler (ctx , a .opts , a .log , w , r )
170
156
a .opts .RequestLog .status (ctx , statusCode )
171
157
klog .V (2 ).Infof ("%s: %s <= st=%d" , a .log .origin , a .name , statusCode )
172
- rspsCounter .WithLabelValues ( label0 , label1 , strconv . Itoa ( statusCode )). Inc ( )
158
+ rspsCounter .Add ( r . Context (), 1 , metric . WithAttributes ( originAttr , operationAttr , codeKey . Int ( statusCode )))
173
159
if err != nil {
174
160
klog .Warningf ("%s: %s handler error: %v" , a .log .origin , a .name , err )
175
161
a .opts .sendHTTPError (w , statusCode , err )
@@ -197,9 +183,9 @@ type HandlerOptions struct {
197
183
TimeSource TimeSource
198
184
}
199
185
200
- func NewPathHandlers (opts * HandlerOptions , log * log ) pathHandlers {
186
+ func NewPathHandlers (ctx context. Context , opts * HandlerOptions , log * log ) pathHandlers {
201
187
once .Do (func () { setupMetrics () })
202
- knownLogs .WithLabelValues ( log . origin ). Set ( 1.0 )
188
+ knownLogs .Record ( ctx , 1 , metric . WithAttributes ( originKey . String ( log . origin )) )
203
189
204
190
prefix := strings .TrimRight (log .origin , "/" )
205
191
if ! strings .HasPrefix (prefix , "/" ) {
@@ -351,8 +337,8 @@ func addChainInternal(ctx context.Context, opts *HandlerOptions, log *log, w htt
351
337
}
352
338
klog .V (3 ).Infof ("%s: %s <= SCT" , log .origin , method )
353
339
if sct .Timestamp == timeMillis {
354
- lastSCTTimestamp .WithLabelValues ( log . origin ). Set ( float64 ( sct . Timestamp ))
355
- lastSCTIndex .WithLabelValues ( log . origin ). Set ( float64 ( idx ))
340
+ lastSCTTimestamp .Record ( ctx , otel . Clamp64 ( sct . Timestamp ), metric . WithAttributes ( originKey . String ( log . origin ) ))
341
+ lastSCTIndex .Record ( ctx , otel . Clamp64 ( idx ), metric . WithAttributes ( originKey . String ( log . origin ) ))
356
342
}
357
343
358
344
return http .StatusOK , nil
0 commit comments