Skip to content

Commit 7c98705

Browse files
committed
Refactor to use Interceptor options & introduce default Client/Server metrics
1 parent a08c265 commit 7c98705

File tree

3 files changed

+105
-38
lines changed

3 files changed

+105
-38
lines changed

interceptor.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ import (
88
"github.com/bufbuild/connect-go"
99
)
1010

11-
var ()
11+
func NewInterceptor(opts ...InterecptorOption) *Interceptor {
12+
options := evaluteInterceptorOptions(&interceptorOptions{
13+
client: DefaultClientMetrics,
14+
server: DefaultServerMetrics,
15+
}, opts...)
1216

13-
func NewInterceptor(client *Metrics, server *Metrics) *Interceptor {
1417
return &Interceptor{
15-
client: client,
16-
server: server,
18+
client: options.client,
19+
server: options.server,
1720
}
1821
}
1922

@@ -95,3 +98,29 @@ func codeOf(err error) string {
9598
}
9699
return connect.CodeOf(err).String()
97100
}
101+
102+
type interceptorOptions struct {
103+
client *Metrics
104+
server *Metrics
105+
}
106+
107+
type InterecptorOption func(*interceptorOptions)
108+
109+
func WithClientMetrics(m *Metrics) InterecptorOption {
110+
return func(io *interceptorOptions) {
111+
io.client = m
112+
}
113+
}
114+
115+
func WithServerMetrics(m *Metrics) InterecptorOption {
116+
return func(io *interceptorOptions) {
117+
io.server = m
118+
}
119+
}
120+
121+
func evaluteInterceptorOptions(defaults *interceptorOptions, opts ...InterecptorOption) *interceptorOptions {
122+
for _, opt := range opts {
123+
opt(defaults)
124+
}
125+
return defaults
126+
}

interceptor_test.go

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,25 @@ import (
1414
"github.com/stretchr/testify/require"
1515
)
1616

17-
func TestInterceptor_WithHistogram(t *testing.T) {
18-
reg := prom.NewRegistry()
19-
opts := []MetricsOption{
17+
var (
18+
testMetricOptions = []MetricsOption{
2019
WithHistogram(true),
2120
WithNamespace("namespace"),
2221
WithSubsystem("subsystem"),
2322
WithConstLabels(prom.Labels{"component": "foo"}),
2423
WithHistogramBuckets([]float64{1, 5}),
2524
}
26-
clientMetrics := NewClientMetrics(opts...)
27-
serverMetrics := NewServerMetrics(opts...)
25+
)
26+
27+
func TestInterceptor_WithClient_WithServer_Histogram(t *testing.T) {
28+
reg := prom.NewRegistry()
29+
30+
clientMetrics := NewClientMetrics(testMetricOptions...)
31+
serverMetrics := NewServerMetrics(testMetricOptions...)
2832

2933
reg.MustRegister(clientMetrics, serverMetrics)
3034

31-
intereceptor := NewInterceptor(clientMetrics, serverMetrics)
35+
intereceptor := NewInterceptor(WithClientMetrics(clientMetrics), WithServerMetrics(serverMetrics))
3236

3337
_, handler := greetconnect.NewGreetServiceHandler(greetconnect.UnimplementedGreetServiceHandler{}, connect.WithInterceptors(intereceptor))
3438
srv := httptest.NewServer(handler)
@@ -54,19 +58,37 @@ func TestInterceptor_WithHistogram(t *testing.T) {
5458
require.Equal(t, len(expectedMetrics), count)
5559
}
5660

57-
func TestInterceptor_WithoutHistogram(t *testing.T) {
58-
reg := prom.NewRegistry()
59-
opts := []MetricsOption{
60-
WithNamespace("namespace"),
61-
WithSubsystem("subsystem"),
62-
WithConstLabels(prom.Labels{"component": "foo"}),
61+
func TestInterceptor_Default(t *testing.T) {
62+
intereceptor := NewInterceptor()
63+
64+
_, handler := greetconnect.NewGreetServiceHandler(greetconnect.UnimplementedGreetServiceHandler{}, connect.WithInterceptors(intereceptor))
65+
srv := httptest.NewServer(handler)
66+
67+
client := greetconnect.NewGreetServiceClient(http.DefaultClient, srv.URL, connect.WithInterceptors(intereceptor))
68+
_, err := client.Greet(context.Background(), connect.NewRequest(&greet.GreetRequest{
69+
Name: "elza",
70+
}))
71+
require.Error(t, err)
72+
require.Equal(t, connect.CodeOf(err), connect.CodeUnimplemented)
73+
74+
expectedMetrics := []string{
75+
"connect_client_handled_total",
76+
"connect_client_started_total",
77+
78+
"connect_server_handled_total",
79+
"connect_server_started_total",
6380
}
64-
clientMetrics := NewClientMetrics(opts...)
65-
serverMetrics := NewServerMetrics(opts...)
81+
count, err := testutil.GatherAndCount(prom.DefaultGatherer, expectedMetrics...)
82+
require.NoError(t, err)
83+
require.Equal(t, len(expectedMetrics), count)
84+
}
6685

67-
reg.MustRegister(clientMetrics, serverMetrics)
86+
func TestInterceptor_WithClientMetrics(t *testing.T) {
87+
reg := prom.NewRegistry()
88+
clientMetrics := NewClientMetrics(testMetricOptions...)
89+
require.NoError(t, reg.Register(clientMetrics))
6890

69-
intereceptor := NewInterceptor(clientMetrics, serverMetrics)
91+
intereceptor := NewInterceptor(WithClientMetrics(clientMetrics))
7092

7193
_, handler := greetconnect.NewGreetServiceHandler(greetconnect.UnimplementedGreetServiceHandler{}, connect.WithInterceptors(intereceptor))
7294
srv := httptest.NewServer(handler)
@@ -81,7 +103,30 @@ func TestInterceptor_WithoutHistogram(t *testing.T) {
81103
expectedMetrics := []string{
82104
"namespace_subsystem_connect_client_handled_total",
83105
"namespace_subsystem_connect_client_started_total",
106+
}
107+
count, err := testutil.GatherAndCount(reg, expectedMetrics...)
108+
require.NoError(t, err)
109+
require.Equal(t, len(expectedMetrics), count)
110+
}
111+
112+
func TestInterceptor_WithServerMetrics(t *testing.T) {
113+
reg := prom.NewRegistry()
114+
serverMetrics := NewServerMetrics(testMetricOptions...)
115+
require.NoError(t, reg.Register(serverMetrics))
116+
117+
intereceptor := NewInterceptor(WithServerMetrics(serverMetrics))
84118

119+
_, handler := greetconnect.NewGreetServiceHandler(greetconnect.UnimplementedGreetServiceHandler{}, connect.WithInterceptors(intereceptor))
120+
srv := httptest.NewServer(handler)
121+
122+
client := greetconnect.NewGreetServiceClient(http.DefaultClient, srv.URL, connect.WithInterceptors(intereceptor))
123+
_, err := client.Greet(context.Background(), connect.NewRequest(&greet.GreetRequest{
124+
Name: "elza",
125+
}))
126+
require.Error(t, err)
127+
require.Equal(t, connect.CodeOf(err), connect.CodeUnimplemented)
128+
129+
expectedMetrics := []string{
85130
"namespace_subsystem_connect_server_handled_total",
86131
"namespace_subsystem_connect_server_started_total",
87132
}

metrics.go

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ import (
44
prom "github.com/prometheus/client_golang/prometheus"
55
)
66

7+
var (
8+
DefaultClientMetrics = NewClientMetrics()
9+
DefaultServerMetrics = NewServerMetrics()
10+
)
11+
12+
func init() {
13+
// Register default metrics against default prometheus metrics registry.
14+
prom.MustRegister(DefaultServerMetrics)
15+
prom.MustRegister(DefaultClientMetrics)
16+
}
17+
718
// NewServerMetrics creates new Connect metrics for server-side handling.
819
func NewServerMetrics(opts ...MetricsOption) *Metrics {
920
config := evaluateMetricsOptions(&metricsOptions{
@@ -163,24 +174,6 @@ func WithSubsystem(subsystem string) MetricsOption {
163174
}
164175
}
165176

166-
func withRequestStartedName(name string) MetricsOption {
167-
return func(opts *metricsOptions) {
168-
opts.requestStartedName = name
169-
}
170-
}
171-
172-
func withrequestHandledName(name string) MetricsOption {
173-
return func(opts *metricsOptions) {
174-
opts.requestHandledName = name
175-
}
176-
}
177-
178-
func withRequestedHandledSecondsName(name string) MetricsOption {
179-
return func(opts *metricsOptions) {
180-
opts.requestHandledSecondsName = name
181-
}
182-
}
183-
184177
func WithConstLabels(labels prom.Labels) MetricsOption {
185178
return func(opts *metricsOptions) {
186179
opts.constLabels = labels

0 commit comments

Comments
 (0)