Skip to content

Commit

Permalink
feat: introduce anclafx
Browse files Browse the repository at this point in the history
- anclafx provides an all in 1 `fx.Provide()` functionality
- simplify metrics setup and names
  • Loading branch information
denopink committed Oct 8, 2024
1 parent b3ef5de commit 37a4b62
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 98 deletions.
19 changes: 19 additions & 0 deletions anclafx/provide.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2024 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0
package anclafx

import (
"github.com/xmidt-org/ancla"
"go.uber.org/fx"
)

const Module = "ancla"

func Provide() fx.Option {
return fx.Module(
Module,
ancla.ProvideMetrics(),
ancla.ProvideListener(),
ancla.ProvideService(),
)
}
2 changes: 1 addition & 1 deletion chrysom/listenerClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (c *ListenerClient) Start(ctx context.Context) error {
outcome = FailureOutcome
c.logger.Error("Failed to get items for listeners", zap.Error(err))
}
c.observer.measures.Polls.With(prometheus.Labels{
c.observer.measures.PollsTotalCounter.With(prometheus.Labels{
OutcomeLabel: outcome}).Add(1)
}
}
Expand Down
2 changes: 1 addition & 1 deletion chrysom/listenerClient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var (
time.Sleep(time.Millisecond * 100)
}))
mockMeasures = &Measures{
Polls: prometheus.NewCounterVec(
PollsTotalCounter: prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "testPollsCounter",
Help: "testPollsCounter",
Expand Down
40 changes: 32 additions & 8 deletions chrysom/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import (

// Names
const (
PollCounter = "chrysom_polls_total"
WebhookListSizeGaugeName = "webhook_list_size"
WebhookListSizeGaugeHelp = "Size of the current list of webhooks."
PollsTotalCounterName = "chrysom_polls_total"
PollsTotalCounterHelp = "Counter for the number of polls (and their success/failure outcomes) to fetch new items."
)

// Labels
Expand All @@ -25,20 +28,41 @@ const (
FailureOutcome = "failure"
)

// Measures describes the defined metrics that will be used by clients.
type Measures struct {
WebhookListSizeGauge prometheus.Gauge `name:"webhook_list_size"`
PollsTotalCounter *prometheus.CounterVec `name:"chrysom_polls_total"`
}

// MeasuresIn is an uber/fx parameter with the webhook registration counter.
type MeasuresIn struct {
fx.In
Measures
}

// NewMeasures realizes desired metrics.
func NewMeasures(in MeasuresIn) *Measures {
return &Measures{
WebhookListSizeGauge: in.WebhookListSizeGauge,
PollsTotalCounter: in.PollsTotalCounter,
}
}

// Metrics returns the Metrics relevant to this package
func ProvideMetrics() fx.Option {
return fx.Options(
fx.Provide(NewMeasures),
touchstone.Gauge(
prometheus.GaugeOpts{
Name: WebhookListSizeGaugeName,
Help: WebhookListSizeGaugeHelp,
}),
touchstone.CounterVec(
prometheus.CounterOpts{
Name: PollCounter,
Help: "Counter for the number of polls (and their success/failure outcomes) to fetch new items.",
Name: PollsTotalCounterName,
Help: PollsTotalCounterHelp,
},
OutcomeLabel,
),
)
}

type Measures struct {
fx.In
Polls *prometheus.CounterVec `name:"chrysom_polls_total"`
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ require (
github.com/xmidt-org/urlegit v0.1.12
github.com/xmidt-org/webhook-schema v0.1.1-0.20240718124820-b8c1ba1f19a9
go.uber.org/fx v1.22.1
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
)

Expand Down Expand Up @@ -48,6 +47,7 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xmidt-org/arrange v0.4.0 // indirect
go.uber.org/dig v1.17.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
Expand Down
70 changes: 1 addition & 69 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,13 @@
package ancla

import (
"github.com/prometheus/client_golang/prometheus"
"github.com/xmidt-org/ancla/chrysom"
"github.com/xmidt-org/touchstone"
"go.uber.org/fx"
"go.uber.org/multierr"
)

// Names
const (
WebhookListSizeGaugeName = "webhook_list_size"
WebhookListSizeGaugeHelp = "Size of the current list of webhooks."
ChrysomPollsTotalCounterName = chrysom.PollCounter
ChrysomPollsTotalCounterHelp = "Counter for the number of polls (and their success/failure outcomes) to fetch new items."
)

// Labels
const (
OutcomeLabel = "outcome"
)

// Outcomes
const (
SuccessOutcome = "success"
FailureOutcome = "failure"
)

// Measures describes the defined metrics that will be used by clients.
type Measures struct {
WebhookListSizeGaugeName prometheus.Gauge `name:"webhook_list_size"`
ChrysomPollsTotalCounterName *prometheus.CounterVec `name:"chrysom_polls_total"`
}

type MeasuresOut struct {
fx.Out

M *Measures
}

// MeasuresIn is an uber/fx parameter with the webhook registration counter.
type MeasuresIn struct {
fx.In

Factory *touchstone.Factory `optional:"true"`
}

// NewMeasures realizes desired metrics.
func NewMeasures(in MeasuresIn) (MeasuresOut, error) {
var metricErr error
wlm, err := in.Factory.NewGauge(
prometheus.GaugeOpts{
Name: WebhookListSizeGaugeName,
Help: WebhookListSizeGaugeHelp,
},
)
err = multierr.Append(err, metricErr)
cpm, err2 := in.Factory.NewCounterVec(
prometheus.CounterOpts{
Name: ChrysomPollsTotalCounterName,
Help: ChrysomPollsTotalCounterHelp,
},
OutcomeLabel,
)
err = multierr.Append(err, err2)

return MeasuresOut{
M: &Measures{
WebhookListSizeGaugeName: wlm,
ChrysomPollsTotalCounterName: cpm,
},
}, multierr.Append(err, metricErr)
}

// ProvideMetrics provides the metrics relevant to this package as uber/fx options.
func ProvideMetrics() fx.Option {
return fx.Options(
fx.Provide(NewMeasures),
chrysom.ProvideMetrics(),
)
}
56 changes: 38 additions & 18 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var (
errFailedWebhookConversion = errors.New("failed to convert webhook to argus item")
errFailedItemConversion = errors.New("failed to convert argus item to webhook")
errFailedWebhooksFetch = errors.New("failed to fetch webhooks")
errFailedConfig = errors.New("ancla configuration error")
)

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

// Measures for instrumenting this package.
// Gets passed to Argus config before initializing the client.
Measures Measures
Measures chrysom.Measures
}

type ClientService struct {
Expand Down Expand Up @@ -113,10 +114,7 @@ func (s *ClientService) StartListener(cfg ListenerConfig, setLogger func(context
cfg.Logger = sallust.Default()
}
prepArgusListenerClientConfig(&cfg, watches...)
m := &chrysom.Measures{
Polls: cfg.Measures.ChrysomPollsTotalCounterName,
}
listener, err := chrysom.NewListenerClient(cfg.Config, setLogger, m, s.argus)
listener, err := chrysom.NewListenerClient(cfg.Config, setLogger, &cfg.Measures, s.argus)
if err != nil {
return nil, fmt.Errorf("failed to create chrysom listener client: %v", err)
}
Expand Down Expand Up @@ -174,7 +172,7 @@ func prepArgusBasicClientConfig(cfg *Config) error {

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

type ServiceIn struct {
fx.In
Config Config
Listener ListenerConfig
Client *http.Client
Config Config
Client *http.Client
}

func ProvideService() fx.Option {
return fx.Provide(
func(in ServiceIn) (*ClientService, error) {
svc, err := NewService(in.Config, getLogger)
if err != nil {
return nil, errors.Join(errFailedConfig, err)
}

svc.config.BasicClientConfig.HTTPClient = in.Client
return svc, err
},
Expand All @@ -206,22 +207,41 @@ func ProvideService() fx.Option {

type ListenerIn struct {
fx.In
Measures *Measures

Measures chrysom.Measures
Logger *zap.Logger
Svc *ClientService
Watcher Watch
LC fx.Lifecycle
}

func ProvideListener() fx.Option {
return fx.Provide(
func(in ListenerIn) ListenerConfig {
listener := ListenerConfig{
Measures: *in.Measures,
Logger: in.Logger,
}
return listener
},
return fx.Options(
fx.Provide(
func(in ListenerIn) (listener ListenerConfig, err error) {
listener = ListenerConfig{
Measures: in.Measures,
Logger: in.Logger,
}

stopWatches, err := in.Svc.StartListener(listener, setLoggerInContext(), in.Watcher)
if err != nil {
return listener, fmt.Errorf("webhook service start listener error: %v", err)
}
in.LC.Append(fx.StopHook(stopWatches))

return listener, nil
},
),
)
}

func setLoggerInContext() func(context.Context, *zap.Logger) context.Context {
return func(parent context.Context, logger *zap.Logger) context.Context {
return sallust.With(parent, logger)
}
}

func getLogger(ctx context.Context) *zap.Logger {
logger := sallust.Get(ctx).With(zap.Time("ts", time.Now().UTC()), zap.Any("caller", zap.WithCaller(true)))
return logger
Expand Down

0 comments on commit 37a4b62

Please sign in to comment.