package account import ( "context" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/noop" ) // meterName scopes the account domain's OpenTelemetry instruments. const meterName = "scrabble/backend/account" // kindGuest labels guest accounts in accounts_created_total. Guests carry no // identity, so they have no identity Kind; this is the metric label for them. const kindGuest = "guest" // accountMetrics holds the account domain's operational instruments. It defaults // to no-ops (see defaultAccountMetrics); SetMetrics installs the real meter during // startup wiring. type accountMetrics struct { created metric.Int64Counter } // defaultAccountMetrics returns instruments backed by a no-op meter. func defaultAccountMetrics() *accountMetrics { return newAccountMetrics(noop.NewMeterProvider().Meter(meterName)) } // newAccountMetrics builds the instruments on meter, falling back to a no-op // counter on the (rare) construction error. func newAccountMetrics(meter metric.Meter) *accountMetrics { c, err := meter.Int64Counter("accounts_created_total", metric.WithDescription("New accounts created, labelled by kind (telegram/email/guest); robots are not counted.")) if err != nil { c, _ = noop.NewMeterProvider().Meter(meterName).Int64Counter("accounts_created_total") } return &accountMetrics{created: c} } // SetMetrics installs the meter the account store records to. It must be called // during startup wiring; the default is a no-op meter. func (s *Store) SetMetrics(meter metric.Meter) { if meter == nil { return } s.metrics = newAccountMetrics(meter) } // recordCreated counts one newly created account of the given kind. func (m *accountMetrics) recordCreated(ctx context.Context, kind string) { m.created.Add(ctx, 1, metric.WithAttributes(attribute.String("kind", kind))) }