Skip to content

Commit

Permalink
feat(instrumentation): allow passing in any prometheus.Registerer (#369)
Browse files Browse the repository at this point in the history
The prometheus client_go library primarily uses the prometheus.Registerer
interface instead of the prometheus.Registry struct for registering
metrics.

Especially the global default registry is only exposed as the interfaces
`prometheus.Registerer` and `prometheus.Gatherer`[0]. Users that want to
use the default registry currently need to make a type assertion to get
the struct from the exported interface:

    hcloud.WithInstrumentation(prometheus.DefaultGatherer.(*prometheus.Registry))

This could fail at any point if the library changes the underlying
implmentation to a different struct.

controller-runtime is another example of an SDK that only exports the
registry as the interface. I had to implement the above type assertation
to get hcloud-go metrics in cluster-api-provider-hetzner[1].

This will not break any user code, because the struct we currently
accept implements the interface we will accept from now on.

[0]: https://github.com/prometheus/client_golang/blob/046e3203b61d1b5000b162e210a91975f098d742/prometheus/registry.go#L54-L58
[1]: https://github.com/syself/cluster-api-provider-hetzner/blob/b421af694d62a6b66ecbb7a6db2ea1f78a620179/pkg/services/hcloud/client/client.go#L88-L92
  • Loading branch information
apricote authored Jan 9, 2024
1 parent 42c6aa3 commit 0821c07
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 7 deletions.
4 changes: 2 additions & 2 deletions hcloud/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type Client struct {
applicationVersion string
userAgent string
debugWriter io.Writer
instrumentationRegistry *prometheus.Registry
instrumentationRegistry prometheus.Registerer

Action ActionClient
Certificate CertificateClient
Expand Down Expand Up @@ -163,7 +163,7 @@ func WithHTTPClient(httpClient *http.Client) ClientOption {
}

// WithInstrumentation configures a Client to collect metrics about the performed HTTP requests.
func WithInstrumentation(registry *prometheus.Registry) ClientOption {
func WithInstrumentation(registry prometheus.Registerer) ClientOption {
return func(client *Client) {
client.instrumentationRegistry = registry
}
Expand Down
6 changes: 3 additions & 3 deletions hcloud/internal/instrumentation/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import (

type Instrumenter struct {
subsystemIdentifier string // will be used as part of the metric name (hcloud_<identifier>_requests_total)
instrumentationRegistry *prometheus.Registry
instrumentationRegistry prometheus.Registerer
}

// New creates a new Instrumenter. The subsystemIdentifier will be used as part of the metric names (e.g. hcloud_<identifier>_requests_total).
func New(subsystemIdentifier string, instrumentationRegistry *prometheus.Registry) *Instrumenter {
func New(subsystemIdentifier string, instrumentationRegistry prometheus.Registerer) *Instrumenter {
return &Instrumenter{subsystemIdentifier: subsystemIdentifier, instrumentationRegistry: instrumentationRegistry}
}

Expand Down Expand Up @@ -84,7 +84,7 @@ func (i *Instrumenter) instrumentRoundTripperEndpoint(counter *prometheus.Counte
// registerOrReuse will try to register the passed Collector, but in case a conflicting collector was already registered,
// it will instead return that collector. Make sure to always use the collector return by this method.
// Similar to [Registry.MustRegister] it will panic if any other error occurs.
func registerOrReuse[C prometheus.Collector](registry *prometheus.Registry, collector C) C {
func registerOrReuse[C prometheus.Collector](registry prometheus.Registerer, collector C) C {
err := registry.Register(collector)
if err != nil {
// If we get a AlreadyRegisteredError we can return the existing collector
Expand Down
4 changes: 2 additions & 2 deletions hcloud/metadata/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Client struct {
timeout time.Duration

httpClient *http.Client
instrumentationRegistry *prometheus.Registry
instrumentationRegistry prometheus.Registerer
}

// A ClientOption is used to configure a [Client].
Expand All @@ -43,7 +43,7 @@ func WithHTTPClient(httpClient *http.Client) ClientOption {
}

// WithInstrumentation configures a [Client] to collect metrics about the performed HTTP requests.
func WithInstrumentation(registry *prometheus.Registry) ClientOption {
func WithInstrumentation(registry prometheus.Registerer) ClientOption {
return func(client *Client) {
client.instrumentationRegistry = registry
}
Expand Down

0 comments on commit 0821c07

Please sign in to comment.