Skip to content

Commit 37a4b62

Browse files
committed
feat: introduce anclafx
- anclafx provides an all in 1 `fx.Provide()` functionality - simplify metrics setup and names
1 parent b3ef5de commit 37a4b62

File tree

7 files changed

+93
-98
lines changed

7 files changed

+93
-98
lines changed

anclafx/provide.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-FileCopyrightText: 2024 Comcast Cable Communications Management, LLC
2+
// SPDX-License-Identifier: Apache-2.0
3+
package anclafx
4+
5+
import (
6+
"github.com/xmidt-org/ancla"
7+
"go.uber.org/fx"
8+
)
9+
10+
const Module = "ancla"
11+
12+
func Provide() fx.Option {
13+
return fx.Module(
14+
Module,
15+
ancla.ProvideMetrics(),
16+
ancla.ProvideListener(),
17+
ancla.ProvideService(),
18+
)
19+
}

chrysom/listenerClient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func (c *ListenerClient) Start(ctx context.Context) error {
140140
outcome = FailureOutcome
141141
c.logger.Error("Failed to get items for listeners", zap.Error(err))
142142
}
143-
c.observer.measures.Polls.With(prometheus.Labels{
143+
c.observer.measures.PollsTotalCounter.With(prometheus.Labels{
144144
OutcomeLabel: outcome}).Add(1)
145145
}
146146
}

chrysom/listenerClient_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var (
2525
time.Sleep(time.Millisecond * 100)
2626
}))
2727
mockMeasures = &Measures{
28-
Polls: prometheus.NewCounterVec(
28+
PollsTotalCounter: prometheus.NewCounterVec(
2929
prometheus.CounterOpts{
3030
Name: "testPollsCounter",
3131
Help: "testPollsCounter",

chrysom/metrics.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import (
1111

1212
// Names
1313
const (
14-
PollCounter = "chrysom_polls_total"
14+
WebhookListSizeGaugeName = "webhook_list_size"
15+
WebhookListSizeGaugeHelp = "Size of the current list of webhooks."
16+
PollsTotalCounterName = "chrysom_polls_total"
17+
PollsTotalCounterHelp = "Counter for the number of polls (and their success/failure outcomes) to fetch new items."
1518
)
1619

1720
// Labels
@@ -25,20 +28,41 @@ const (
2528
FailureOutcome = "failure"
2629
)
2730

31+
// Measures describes the defined metrics that will be used by clients.
32+
type Measures struct {
33+
WebhookListSizeGauge prometheus.Gauge `name:"webhook_list_size"`
34+
PollsTotalCounter *prometheus.CounterVec `name:"chrysom_polls_total"`
35+
}
36+
37+
// MeasuresIn is an uber/fx parameter with the webhook registration counter.
38+
type MeasuresIn struct {
39+
fx.In
40+
Measures
41+
}
42+
43+
// NewMeasures realizes desired metrics.
44+
func NewMeasures(in MeasuresIn) *Measures {
45+
return &Measures{
46+
WebhookListSizeGauge: in.WebhookListSizeGauge,
47+
PollsTotalCounter: in.PollsTotalCounter,
48+
}
49+
}
50+
2851
// Metrics returns the Metrics relevant to this package
2952
func ProvideMetrics() fx.Option {
3053
return fx.Options(
54+
fx.Provide(NewMeasures),
55+
touchstone.Gauge(
56+
prometheus.GaugeOpts{
57+
Name: WebhookListSizeGaugeName,
58+
Help: WebhookListSizeGaugeHelp,
59+
}),
3160
touchstone.CounterVec(
3261
prometheus.CounterOpts{
33-
Name: PollCounter,
34-
Help: "Counter for the number of polls (and their success/failure outcomes) to fetch new items.",
62+
Name: PollsTotalCounterName,
63+
Help: PollsTotalCounterHelp,
3564
},
3665
OutcomeLabel,
3766
),
3867
)
3968
}
40-
41-
type Measures struct {
42-
fx.In
43-
Polls *prometheus.CounterVec `name:"chrysom_polls_total"`
44-
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ require (
1919
github.com/xmidt-org/urlegit v0.1.12
2020
github.com/xmidt-org/webhook-schema v0.1.1-0.20240718124820-b8c1ba1f19a9
2121
go.uber.org/fx v1.22.1
22-
go.uber.org/multierr v1.11.0
2322
go.uber.org/zap v1.27.0
2423
)
2524

@@ -48,6 +47,7 @@ require (
4847
github.com/subosito/gotenv v1.6.0 // indirect
4948
github.com/xmidt-org/arrange v0.4.0 // indirect
5049
go.uber.org/dig v1.17.1 // indirect
50+
go.uber.org/multierr v1.11.0 // indirect
5151
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
5252
golang.org/x/sys v0.18.0 // indirect
5353
golang.org/x/text v0.14.0 // indirect

metrics.go

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,13 @@
44
package ancla
55

66
import (
7-
"github.com/prometheus/client_golang/prometheus"
87
"github.com/xmidt-org/ancla/chrysom"
9-
"github.com/xmidt-org/touchstone"
108
"go.uber.org/fx"
11-
"go.uber.org/multierr"
129
)
1310

14-
// Names
15-
const (
16-
WebhookListSizeGaugeName = "webhook_list_size"
17-
WebhookListSizeGaugeHelp = "Size of the current list of webhooks."
18-
ChrysomPollsTotalCounterName = chrysom.PollCounter
19-
ChrysomPollsTotalCounterHelp = "Counter for the number of polls (and their success/failure outcomes) to fetch new items."
20-
)
21-
22-
// Labels
23-
const (
24-
OutcomeLabel = "outcome"
25-
)
26-
27-
// Outcomes
28-
const (
29-
SuccessOutcome = "success"
30-
FailureOutcome = "failure"
31-
)
32-
33-
// Measures describes the defined metrics that will be used by clients.
34-
type Measures struct {
35-
WebhookListSizeGaugeName prometheus.Gauge `name:"webhook_list_size"`
36-
ChrysomPollsTotalCounterName *prometheus.CounterVec `name:"chrysom_polls_total"`
37-
}
38-
39-
type MeasuresOut struct {
40-
fx.Out
41-
42-
M *Measures
43-
}
44-
45-
// MeasuresIn is an uber/fx parameter with the webhook registration counter.
46-
type MeasuresIn struct {
47-
fx.In
48-
49-
Factory *touchstone.Factory `optional:"true"`
50-
}
51-
52-
// NewMeasures realizes desired metrics.
53-
func NewMeasures(in MeasuresIn) (MeasuresOut, error) {
54-
var metricErr error
55-
wlm, err := in.Factory.NewGauge(
56-
prometheus.GaugeOpts{
57-
Name: WebhookListSizeGaugeName,
58-
Help: WebhookListSizeGaugeHelp,
59-
},
60-
)
61-
err = multierr.Append(err, metricErr)
62-
cpm, err2 := in.Factory.NewCounterVec(
63-
prometheus.CounterOpts{
64-
Name: ChrysomPollsTotalCounterName,
65-
Help: ChrysomPollsTotalCounterHelp,
66-
},
67-
OutcomeLabel,
68-
)
69-
err = multierr.Append(err, err2)
70-
71-
return MeasuresOut{
72-
M: &Measures{
73-
WebhookListSizeGaugeName: wlm,
74-
ChrysomPollsTotalCounterName: cpm,
75-
},
76-
}, multierr.Append(err, metricErr)
77-
}
78-
7911
// ProvideMetrics provides the metrics relevant to this package as uber/fx options.
8012
func ProvideMetrics() fx.Option {
8113
return fx.Options(
82-
fx.Provide(NewMeasures),
14+
chrysom.ProvideMetrics(),
8315
)
8416
}

service.go

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var (
2424
errFailedWebhookConversion = errors.New("failed to convert webhook to argus item")
2525
errFailedItemConversion = errors.New("failed to convert argus item to webhook")
2626
errFailedWebhooksFetch = errors.New("failed to fetch webhooks")
27+
errFailedConfig = errors.New("ancla configuration error")
2728
)
2829

2930
// Service describes the core operations around webhook subscriptions.
@@ -76,7 +77,7 @@ type ListenerConfig struct {
7677

7778
// Measures for instrumenting this package.
7879
// Gets passed to Argus config before initializing the client.
79-
Measures Measures
80+
Measures chrysom.Measures
8081
}
8182

8283
type ClientService struct {
@@ -113,10 +114,7 @@ func (s *ClientService) StartListener(cfg ListenerConfig, setLogger func(context
113114
cfg.Logger = sallust.Default()
114115
}
115116
prepArgusListenerClientConfig(&cfg, watches...)
116-
m := &chrysom.Measures{
117-
Polls: cfg.Measures.ChrysomPollsTotalCounterName,
118-
}
119-
listener, err := chrysom.NewListenerClient(cfg.Config, setLogger, m, s.argus)
117+
listener, err := chrysom.NewListenerClient(cfg.Config, setLogger, &cfg.Measures, s.argus)
120118
if err != nil {
121119
return nil, fmt.Errorf("failed to create chrysom listener client: %v", err)
122120
}
@@ -174,7 +172,7 @@ func prepArgusBasicClientConfig(cfg *Config) error {
174172

175173
func prepArgusListenerClientConfig(cfg *ListenerConfig, watches ...Watch) {
176174
logger := cfg.Logger
177-
watches = append(watches, webhookListSizeWatch(cfg.Measures.WebhookListSizeGaugeName))
175+
watches = append(watches, webhookListSizeWatch(cfg.Measures.WebhookListSizeGauge))
178176
cfg.Config.Listener = chrysom.ListenerFunc(func(items chrysom.Items) {
179177
iws, err := ItemsToInternalWebhooks(items)
180178
if err != nil {
@@ -189,15 +187,18 @@ func prepArgusListenerClientConfig(cfg *ListenerConfig, watches ...Watch) {
189187

190188
type ServiceIn struct {
191189
fx.In
192-
Config Config
193-
Listener ListenerConfig
194-
Client *http.Client
190+
Config Config
191+
Client *http.Client
195192
}
196193

197194
func ProvideService() fx.Option {
198195
return fx.Provide(
199196
func(in ServiceIn) (*ClientService, error) {
200197
svc, err := NewService(in.Config, getLogger)
198+
if err != nil {
199+
return nil, errors.Join(errFailedConfig, err)
200+
}
201+
201202
svc.config.BasicClientConfig.HTTPClient = in.Client
202203
return svc, err
203204
},
@@ -206,22 +207,41 @@ func ProvideService() fx.Option {
206207

207208
type ListenerIn struct {
208209
fx.In
209-
Measures *Measures
210+
211+
Measures chrysom.Measures
210212
Logger *zap.Logger
213+
Svc *ClientService
214+
Watcher Watch
215+
LC fx.Lifecycle
211216
}
212217

213218
func ProvideListener() fx.Option {
214-
return fx.Provide(
215-
func(in ListenerIn) ListenerConfig {
216-
listener := ListenerConfig{
217-
Measures: *in.Measures,
218-
Logger: in.Logger,
219-
}
220-
return listener
221-
},
219+
return fx.Options(
220+
fx.Provide(
221+
func(in ListenerIn) (listener ListenerConfig, err error) {
222+
listener = ListenerConfig{
223+
Measures: in.Measures,
224+
Logger: in.Logger,
225+
}
226+
227+
stopWatches, err := in.Svc.StartListener(listener, setLoggerInContext(), in.Watcher)
228+
if err != nil {
229+
return listener, fmt.Errorf("webhook service start listener error: %v", err)
230+
}
231+
in.LC.Append(fx.StopHook(stopWatches))
232+
233+
return listener, nil
234+
},
235+
),
222236
)
223237
}
224238

239+
func setLoggerInContext() func(context.Context, *zap.Logger) context.Context {
240+
return func(parent context.Context, logger *zap.Logger) context.Context {
241+
return sallust.With(parent, logger)
242+
}
243+
}
244+
225245
func getLogger(ctx context.Context) *zap.Logger {
226246
logger := sallust.Get(ctx).With(zap.Time("ts", time.Now().UTC()), zap.Any("caller", zap.WithCaller(true)))
227247
return logger

0 commit comments

Comments
 (0)