Shorthand for OTEL metrics initialization.
go get github.com/ofeefo/em
type metrics struct {
Counter em.Counter[int64] `id:"a_counter"`
Gauge em.Gauge[int64] `id:"a_gauge"`
UpDownCounter em.UpDownCounter[float64] `id:"a_updowncounter"`
Histogram em.Histogram[float64] `id:"a_histogram" buckets:"1.0,2.0,3.0"`
}
// ...
func main() {
// Setup receives the application identifier and optional attributes.
// It creates a basic meter provider setup to help you get started quickly.
// For more advanced configurations (exporters, resources, etc.),
// use SetupWithMeter.
err := em.Setup("my-app", attribute.String("some", "attr"))
if err != nil {
// ...
}
// Initialize your metrics.
m, err := em.Init[metrics]()
if err != nil {
//...
}
// Record your measurements
i.Counter.Inc(em.Attrs(attribute.String("some", "attr")))
// Serve your metrics.
if err = http.ListenAndServe(":8080", promhttp.Handler()); err != nil {
panic(err)
}
}
All available metrics are wrappers for the official Go OTEL sdk,
and can be created using both int64
and float64
, which are the available
types for creating metrics with the official sdk (and limited in this package
through the n64
interface).
type Counter[T n64] interface {
// Add records a change of n to the counter.
Add(n T, opts ...metric.AddOption)
// AddCtx records a change of n to the counter.
AddCtx(ctx context.Context, n T, opts ...metric.AddOption)
// Inc records a change of 1 to the counter.
Inc(opts ...metric.AddOption)
// IncCtx records a change of 1 to the counter.
IncCtx(ctx context.Context, opts ...metric.AddOption)
}
type UpDownCounter[T n64] interface {
// Add records a change of n to the counter.
Add(n T, opts ...metric.AddOption)
// AddCtx records a change of n to the counter.
AddCtx(ctx context.Context, n T, opts ...metric.AddOption)
// Inc records a change of 1 to the counter.
Inc(opts ...metric.AddOption)
// IncCtx records a change of 1 to the counter.
IncCtx(ctx context.Context, opts ...metric.AddOption)
// Dec records a change of -1 to the counter.
Dec(opts ...metric.AddOption)
// DecCtx records a change of -1 to the counter.
DecCtx(ctx context.Context, opts ...metric.AddOption)
}
type Gauge[T n64] interface {
// Record records the value of n to the gauge.
Record(n T, opts ...metric.RecordOption)
// RecordCtx records the value of n to the gauge.
RecordCtx(ctx context.Context, n T, opts ...metric.RecordOption)
}
type Histogram[T n64] interface {
// Record adds a value to the distribution.
Record(n T, opts ...metric.RecordOption)
// RecordCtx adds a value to the distribution.
RecordCtx(ctx context.Context, n T, opts ...metric.RecordOption)
// Measure creates a starting point using time.Now and returns a function
// that records the time elapsed since the starting point. The returned
// function may also receive record options to further support information
// that may vary along a given procedure.
Measure(transform timeSub[T], opts ...metric.RecordOption) func(opts ...metric.RecordOption)
// MeasureCtx creates a starting point using time.Now and returns a function
// that records the time elapsed since the starting point. The returned
// function may also receive record options to further support information
// that may vary along a given procedure.
MeasureCtx(ctx context.Context, transform timeTransform[T], opts ...metric.RecordOption) func(opts ...metric.RecordOption)
}
id [required]
: The metric identifier.buckets [optional]
: Defines bucket boundaries for histograms.attrs [optional]
: Defines additional identifiers for different components and subsystems.
The following example demonstrates how to build metrics subsystems with nested and embedded structs:
type PostgresMetrics struct{
OpCount em.Counter[int64] `id:"operations_performed"`
OpTime em.Histogram[int64] `id:"operation_time"`
}
type dbMetrics struct {
Master struct {
PostgresMetrics
WriteCounter em.Counter[int64] `id:"db_write_counter"`
} `attrs:"sub, master"`
PostgresMetrics `attrs:"sub, replica"`
}
type Metrics struct {
DbMetrics dbMetrics `attrs:"sub,postgres"`
}
timeSub[T]
: Functions that return the time elapsed since a given starting point. Already present in this package:Micros
Millis
Seconds
When no Setup
functions are called, a noop
handler is used to avoid issues
regarding metric identifier collision, allowing metrics to be initialized as usual
without risking errors or nil pointer issues.
- Only synchronous metrics are supported.
- Initialization of instruments only allows for identifiers and
bucket boundaries for
histograms
.