Skip to content

Commit e2613be

Browse files
authored
Merge pull request weaveworks#289 from thampiotr/reuse-existing-metrics
Allow users to manually register metrics
2 parents 129a61a + 421647b commit e2613be

File tree

3 files changed

+136
-98
lines changed

3 files changed

+136
-98
lines changed

server/metrics.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package server
2+
3+
import (
4+
"github.com/prometheus/client_golang/prometheus"
5+
"github.com/weaveworks/common/instrument"
6+
"github.com/weaveworks/common/middleware"
7+
"time"
8+
)
9+
10+
type Metrics struct {
11+
TcpConnections *prometheus.GaugeVec
12+
TcpConnectionsLimit *prometheus.GaugeVec
13+
RequestDuration *prometheus.HistogramVec
14+
ReceivedMessageSize *prometheus.HistogramVec
15+
SentMessageSize *prometheus.HistogramVec
16+
InflightRequests *prometheus.GaugeVec
17+
}
18+
19+
func NewServerMetrics(cfg Config) *Metrics {
20+
return &Metrics{
21+
TcpConnections: prometheus.NewGaugeVec(prometheus.GaugeOpts{
22+
Namespace: cfg.MetricsNamespace,
23+
Name: "tcp_connections",
24+
Help: "Current number of accepted TCP connections.",
25+
}, []string{"protocol"}),
26+
TcpConnectionsLimit: prometheus.NewGaugeVec(prometheus.GaugeOpts{
27+
Namespace: cfg.MetricsNamespace,
28+
Name: "tcp_connections_limit",
29+
Help: "The max number of TCP connections that can be accepted (0 means no limit).",
30+
}, []string{"protocol"}),
31+
RequestDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
32+
Namespace: cfg.MetricsNamespace,
33+
Name: "request_duration_seconds",
34+
Help: "Time (in seconds) spent serving HTTP requests.",
35+
Buckets: instrument.DefBuckets,
36+
NativeHistogramBucketFactor: cfg.MetricsNativeHistogramFactor,
37+
NativeHistogramMaxBucketNumber: 100,
38+
NativeHistogramMinResetDuration: time.Hour,
39+
}, []string{"method", "route", "status_code", "ws"}),
40+
ReceivedMessageSize: prometheus.NewHistogramVec(prometheus.HistogramOpts{
41+
Namespace: cfg.MetricsNamespace,
42+
Name: "request_message_bytes",
43+
Help: "Size (in bytes) of messages received in the request.",
44+
Buckets: middleware.BodySizeBuckets,
45+
}, []string{"method", "route"}),
46+
SentMessageSize: prometheus.NewHistogramVec(prometheus.HistogramOpts{
47+
Namespace: cfg.MetricsNamespace,
48+
Name: "response_message_bytes",
49+
Help: "Size (in bytes) of messages sent in response.",
50+
Buckets: middleware.BodySizeBuckets,
51+
}, []string{"method", "route"}),
52+
InflightRequests: prometheus.NewGaugeVec(prometheus.GaugeOpts{
53+
Namespace: cfg.MetricsNamespace,
54+
Name: "inflight_requests",
55+
Help: "Current number of inflight requests.",
56+
}, []string{"method", "route"}),
57+
}
58+
}
59+
60+
func (s *Metrics) MustRegister(registerer prometheus.Registerer) {
61+
registerer.MustRegister(
62+
s.TcpConnections,
63+
s.TcpConnectionsLimit,
64+
s.RequestDuration,
65+
s.ReceivedMessageSize,
66+
s.SentMessageSize,
67+
s.InflightRequests,
68+
)
69+
}

server/server.go

Lines changed: 37 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626

2727
"github.com/weaveworks/common/httpgrpc"
2828
httpgrpc_server "github.com/weaveworks/common/httpgrpc/server"
29-
"github.com/weaveworks/common/instrument"
3029
"github.com/weaveworks/common/logging"
3130
"github.com/weaveworks/common/middleware"
3231
"github.com/weaveworks/common/signals"
@@ -178,6 +177,14 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
178177
f.BoolVar(&cfg.LogRequestAtInfoLevel, "server.log-request-at-info-level-enabled", false, "Optionally log requests at info level instead of debug level. Applies to request headers as well if server.log-request-headers is enabled.")
179178
}
180179

180+
func (cfg *Config) registererOrDefault() prometheus.Registerer {
181+
// If user doesn't supply a Registerer/gatherer, use Prometheus' by default.
182+
if cfg.Registerer != nil {
183+
return cfg.Registerer
184+
}
185+
return prometheus.DefaultRegisterer
186+
}
187+
181188
// Server wraps a HTTP and gRPC server, and some common initialization.
182189
//
183190
// Servers will be automatically instrumented for Prometheus metrics.
@@ -202,39 +209,32 @@ type Server struct {
202209
Gatherer prometheus.Gatherer
203210
}
204211

205-
// New makes a new Server
212+
// New makes a new Server. It will panic if the metrics cannot be registered.
206213
func New(cfg Config) (*Server, error) {
214+
metrics := NewServerMetrics(cfg)
215+
metrics.MustRegister(cfg.registererOrDefault())
216+
return newServer(cfg, metrics)
217+
}
218+
219+
// NewWithMetrics makes a new Server using the provided Metrics. It will not attempt to register the metrics,
220+
// the user is responsible for doing so.
221+
func NewWithMetrics(cfg Config, metrics *Metrics) (*Server, error) {
222+
return newServer(cfg, metrics)
223+
}
224+
225+
func newServer(cfg Config, metrics *Metrics) (*Server, error) {
207226
// If user doesn't supply a logging implementation, by default instantiate
208227
// logrus.
209228
log := cfg.Log
210229
if log == nil {
211230
log = logging.NewLogrus(cfg.LogLevel)
212231
}
213232

214-
// If user doesn't supply a registerer/gatherer, use Prometheus' by default.
215-
reg := cfg.Registerer
216-
if reg == nil {
217-
reg = prometheus.DefaultRegisterer
218-
}
219233
gatherer := cfg.Gatherer
220234
if gatherer == nil {
221235
gatherer = prometheus.DefaultGatherer
222236
}
223237

224-
tcpConnections := prometheus.NewGaugeVec(prometheus.GaugeOpts{
225-
Namespace: cfg.MetricsNamespace,
226-
Name: "tcp_connections",
227-
Help: "Current number of accepted TCP connections.",
228-
}, []string{"protocol"})
229-
reg.MustRegister(tcpConnections)
230-
231-
tcpConnectionsLimit := prometheus.NewGaugeVec(prometheus.GaugeOpts{
232-
Namespace: cfg.MetricsNamespace,
233-
Name: "tcp_connections_limit",
234-
Help: "The max number of TCP connections that can be accepted (0 means no limit).",
235-
}, []string{"protocol"})
236-
reg.MustRegister(tcpConnectionsLimit)
237-
238238
network := cfg.HTTPListenNetwork
239239
if network == "" {
240240
network = DefaultNetwork
@@ -244,9 +244,9 @@ func New(cfg Config) (*Server, error) {
244244
if err != nil {
245245
return nil, err
246246
}
247-
httpListener = middleware.CountingListener(httpListener, tcpConnections.WithLabelValues("http"))
247+
httpListener = middleware.CountingListener(httpListener, metrics.TcpConnections.WithLabelValues("http"))
248248

249-
tcpConnectionsLimit.WithLabelValues("http").Set(float64(cfg.HTTPConnLimit))
249+
metrics.TcpConnectionsLimit.WithLabelValues("http").Set(float64(cfg.HTTPConnLimit))
250250
if cfg.HTTPConnLimit > 0 {
251251
httpListener = netutil.LimitListener(httpListener, cfg.HTTPConnLimit)
252252
}
@@ -268,9 +268,9 @@ func New(cfg Config) (*Server, error) {
268268
if err != nil {
269269
return nil, err
270270
}
271-
grpcListener = middleware.CountingListener(grpcListener, tcpConnections.WithLabelValues("grpc"))
271+
grpcListener = middleware.CountingListener(grpcListener, metrics.TcpConnections.WithLabelValues("grpc"))
272272

273-
tcpConnectionsLimit.WithLabelValues("grpc").Set(float64(cfg.GRPCConnLimit))
273+
metrics.TcpConnectionsLimit.WithLabelValues("grpc").Set(float64(cfg.GRPCConnLimit))
274274
if cfg.GRPCConnLimit > 0 {
275275
grpcListener = netutil.LimitListener(grpcListener, cfg.GRPCConnLimit)
276276
}
@@ -316,41 +316,6 @@ func New(cfg Config) (*Server, error) {
316316
}
317317
}
318318

319-
// Prometheus histograms for requests.
320-
requestDuration := prometheus.NewHistogramVec(prometheus.HistogramOpts{
321-
Namespace: cfg.MetricsNamespace,
322-
Name: "request_duration_seconds",
323-
Help: "Time (in seconds) spent serving HTTP requests.",
324-
Buckets: instrument.DefBuckets,
325-
NativeHistogramBucketFactor: cfg.MetricsNativeHistogramFactor,
326-
NativeHistogramMaxBucketNumber: 100,
327-
NativeHistogramMinResetDuration: time.Hour,
328-
}, []string{"method", "route", "status_code", "ws"})
329-
reg.MustRegister(requestDuration)
330-
331-
receivedMessageSize := prometheus.NewHistogramVec(prometheus.HistogramOpts{
332-
Namespace: cfg.MetricsNamespace,
333-
Name: "request_message_bytes",
334-
Help: "Size (in bytes) of messages received in the request.",
335-
Buckets: middleware.BodySizeBuckets,
336-
}, []string{"method", "route"})
337-
reg.MustRegister(receivedMessageSize)
338-
339-
sentMessageSize := prometheus.NewHistogramVec(prometheus.HistogramOpts{
340-
Namespace: cfg.MetricsNamespace,
341-
Name: "response_message_bytes",
342-
Help: "Size (in bytes) of messages sent in response.",
343-
Buckets: middleware.BodySizeBuckets,
344-
}, []string{"method", "route"})
345-
reg.MustRegister(sentMessageSize)
346-
347-
inflightRequests := prometheus.NewGaugeVec(prometheus.GaugeOpts{
348-
Namespace: cfg.MetricsNamespace,
349-
Name: "inflight_requests",
350-
Help: "Current number of inflight requests.",
351-
}, []string{"method", "route"})
352-
reg.MustRegister(inflightRequests)
353-
354319
log.WithField("http", httpListener.Addr()).WithField("grpc", grpcListener.Addr()).Infof("server listening on addresses")
355320

356321
// Setup gRPC server
@@ -362,14 +327,14 @@ func New(cfg Config) (*Server, error) {
362327
grpcMiddleware := []grpc.UnaryServerInterceptor{
363328
serverLog.UnaryServerInterceptor,
364329
otgrpc.OpenTracingServerInterceptor(opentracing.GlobalTracer()),
365-
middleware.UnaryServerInstrumentInterceptor(requestDuration),
330+
middleware.UnaryServerInstrumentInterceptor(metrics.RequestDuration),
366331
}
367332
grpcMiddleware = append(grpcMiddleware, cfg.GRPCMiddleware...)
368333

369334
grpcStreamMiddleware := []grpc.StreamServerInterceptor{
370335
serverLog.StreamServerInterceptor,
371336
otgrpc.OpenTracingStreamServerInterceptor(opentracing.GlobalTracer()),
372-
middleware.StreamServerInstrumentInterceptor(requestDuration),
337+
middleware.StreamServerInstrumentInterceptor(metrics.RequestDuration),
373338
}
374339
grpcStreamMiddleware = append(grpcStreamMiddleware, cfg.GRPCStreamMiddleware...)
375340

@@ -394,7 +359,11 @@ func New(cfg Config) (*Server, error) {
394359
grpc.MaxRecvMsgSize(cfg.GPRCServerMaxRecvMsgSize),
395360
grpc.MaxSendMsgSize(cfg.GRPCServerMaxSendMsgSize),
396361
grpc.MaxConcurrentStreams(uint32(cfg.GPRCServerMaxConcurrentStreams)),
397-
grpc.StatsHandler(middleware.NewStatsHandler(receivedMessageSize, sentMessageSize, inflightRequests)),
362+
grpc.StatsHandler(middleware.NewStatsHandler(
363+
metrics.ReceivedMessageSize,
364+
metrics.SentMessageSize,
365+
metrics.InflightRequests,
366+
)),
398367
}
399368
grpcOptions = append(grpcOptions, cfg.GRPCOptions...)
400369
if grpcTLSConfig != nil {
@@ -439,10 +408,10 @@ func New(cfg Config) (*Server, error) {
439408
defaultLogMiddleware,
440409
middleware.Instrument{
441410
RouteMatcher: router,
442-
Duration: requestDuration,
443-
RequestBodySize: receivedMessageSize,
444-
ResponseBodySize: sentMessageSize,
445-
InflightRequests: inflightRequests,
411+
Duration: metrics.RequestDuration,
412+
RequestBodySize: metrics.ReceivedMessageSize,
413+
ResponseBodySize: metrics.SentMessageSize,
414+
InflightRequests: metrics.InflightRequests,
446415
},
447416
}
448417
var httpMiddleware []middleware.Interface
@@ -480,7 +449,7 @@ func New(cfg Config) (*Server, error) {
480449
GRPC: grpcServer,
481450
GRPCOnHTTPServer: grpcOnHttpServer,
482451
Log: log,
483-
Registerer: reg,
452+
Registerer: cfg.registererOrDefault(),
484453
Gatherer: gatherer,
485454
}, nil
486455
}

0 commit comments

Comments
 (0)