-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
metrics: add statsd instrumentation (#3)
- Loading branch information
Showing
7 changed files
with
261 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,28 @@ | ||
github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= | ||
github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= | ||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= | ||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= | ||
github.com/adevinta/vulcan-report v1.0.0 h1:44aICPZ+4svucgCSA5KmjlT3ZGzrvZXiSnkbnj6AC2k= | ||
github.com/adevinta/vulcan-report v1.0.0/go.mod h1:k34KaeoXc3H77WNMwI9F4F1G28hBjB95PeMUp9oHbEE= | ||
github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA= | ||
github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
github.com/google/go-github/v67 v67.0.0 h1:g11NDAmfaBaCO8qYdI9fsmbaRipHNWRIU/2YGvlh4rg= | ||
github.com/google/go-github/v67 v67.0.0/go.mod h1:zH3K7BxjFndr9QSeFibx4lTKkYS3K9nDanoI1NjaOtY= | ||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= | ||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= | ||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | ||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= | ||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2025 Adevinta | ||
|
||
// Package metrics provides a wrapper to interact with StatsD. | ||
package metrics | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log/slog" | ||
|
||
"github.com/DataDog/datadog-go/statsd" | ||
|
||
"github.com/adevinta/ghe-reposec/internal/config" | ||
) | ||
|
||
var ( | ||
// ClientNotInitializedMsg is logged when the metrics client is not | ||
// initialized and metrics are enabled. | ||
ClientNotInitializedMsg = "metrics client not initialized" | ||
) | ||
|
||
const ( | ||
// DefaultMetricsClientAddr is the default metrics client address. | ||
DefaultMetricsClientAddr = "localhost:8125" | ||
) | ||
|
||
// Client represents a metrics service client. | ||
type Client struct { | ||
cfg config.MetricsConfig | ||
client *statsd.Client | ||
logger *slog.Logger | ||
ctx context.Context | ||
} | ||
|
||
// NewClient creates a new metrics client based on environment variables config. | ||
func NewClient(ctx context.Context, logger *slog.Logger, cfg config.MetricsConfig) (*Client, error) { | ||
if !cfg.Enabled { | ||
logger.Info("metrics reporting disabled") | ||
return &Client{}, nil | ||
} | ||
address := cfg.Address | ||
if address == "" { | ||
logger.Warn("metrics address not provided, using default", "address", DefaultMetricsClientAddr) | ||
address = DefaultMetricsClientAddr | ||
} | ||
|
||
statsd, err := statsd.New(address) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Client{ | ||
cfg: cfg, | ||
client: statsd, | ||
logger: logger, | ||
ctx: ctx, | ||
}, nil | ||
} | ||
|
||
// Gauge sends a gauge metric to the metrics service. | ||
func (c *Client) Gauge(name string, value int, tags []string) { | ||
if !c.cfg.Enabled { | ||
return | ||
} | ||
if c.client == nil { | ||
c.logger.Warn(ClientNotInitializedMsg) | ||
return | ||
} | ||
tags = append(tags, c.cfg.Tags...) | ||
name = fmt.Sprintf("%s.%s", c.cfg.Namespace, name) | ||
err := c.client.Gauge(name, float64(value), tags, 1) | ||
if err != nil { | ||
c.logger.Error("gauge metric push error", "error", err) | ||
return | ||
} | ||
c.logger.Debug("gauge metric pushed", "name", name, "value", value, "tags", tags) | ||
} | ||
|
||
// ServiceCheck sends a service satus signal to the metrics service. | ||
func (c *Client) ServiceCheck(status byte, message string, tags []string) { | ||
if !c.cfg.Enabled { | ||
return | ||
} | ||
if c.client == nil { | ||
c.logger.Warn(ClientNotInitializedMsg) | ||
return | ||
} | ||
tags = append(tags, c.cfg.Tags...) | ||
name := fmt.Sprintf("%s.service_check", c.cfg.Namespace) | ||
err := c.client.ServiceCheck(&statsd.ServiceCheck{ | ||
Name: name, | ||
Status: statsd.ServiceCheckStatus(status), | ||
Tags: tags, | ||
Message: message, | ||
}) | ||
if err != nil { | ||
c.logger.Error("service check push error", "error", err) | ||
return | ||
} | ||
c.logger.Debug("service check pushed", "status", status, "message", message) | ||
} | ||
|
||
// Close closes the metrics client. | ||
func (c *Client) Close() { | ||
if !c.cfg.Enabled { | ||
return | ||
} | ||
if c.client == nil { | ||
c.logger.Warn(ClientNotInitializedMsg) | ||
return | ||
} | ||
err := c.client.Close() | ||
if err != nil { | ||
c.logger.Error("metrics client close error", "error", err) | ||
return | ||
} | ||
c.logger.Debug("metrics client closed") | ||
} | ||
|
||
// Flush flushes the metrics client. | ||
func (c *Client) Flush() { | ||
if !c.cfg.Enabled { | ||
return | ||
} | ||
if c.client == nil { | ||
c.logger.Warn(ClientNotInitializedMsg) | ||
return | ||
} | ||
err := c.client.Flush() | ||
if err != nil { | ||
c.logger.Error("metrics client flush error", "error", err) | ||
return | ||
} | ||
c.logger.Debug("metrics client flushed") | ||
} |
Oops, something went wrong.