package metrics import ( "github.com/go-kit/kit/metrics" "github.com/go-kit/kit/metrics/multi" ) // Registry has to implemented by any system that wants to monitor and expose metrics. type Registry interface { // IsEpEnabled shows whether metrics instrumentation is enabled on entry points. IsEpEnabled() bool // IsSvcEnabled shows whether metrics instrumentation is enabled on services. IsSvcEnabled() bool // server metrics ConfigReloadsCounter() metrics.Counter ConfigReloadsFailureCounter() metrics.Counter LastConfigReloadSuccessGauge() metrics.Gauge LastConfigReloadFailureGauge() metrics.Gauge // entry point metrics EntryPointReqsCounter() metrics.Counter EntryPointReqsTLSCounter() metrics.Counter EntryPointReqDurationHistogram() metrics.Histogram EntryPointOpenConnsGauge() metrics.Gauge // service metrics ServiceReqsCounter() metrics.Counter ServiceReqsTLSCounter() metrics.Counter ServiceReqDurationHistogram() metrics.Histogram ServiceOpenConnsGauge() metrics.Gauge ServiceRetriesCounter() metrics.Counter ServiceServerUpGauge() metrics.Gauge } // NewVoidRegistry is a noop implementation of metrics.Registry. // It is used to avoid nil checking in components that do metric collections. func NewVoidRegistry() Registry { return NewMultiRegistry([]Registry{}) } // NewMultiRegistry is an implementation of metrics.Registry that wraps multiple registries. // It handles the case when a registry hasn't registered some metric and returns nil. // This allows for feature imparity between the different metric implementations. func NewMultiRegistry(registries []Registry) Registry { var configReloadsCounter []metrics.Counter var configReloadsFailureCounter []metrics.Counter var lastConfigReloadSuccessGauge []metrics.Gauge var lastConfigReloadFailureGauge []metrics.Gauge var entryPointReqsCounter []metrics.Counter var entryPointReqsTLSCounter []metrics.Counter var entryPointReqDurationHistogram []metrics.Histogram var entryPointOpenConnsGauge []metrics.Gauge var serviceReqsCounter []metrics.Counter var serviceReqsTLSCounter []metrics.Counter var serviceReqDurationHistogram []metrics.Histogram var serviceOpenConnsGauge []metrics.Gauge var serviceRetriesCounter []metrics.Counter var serviceServerUpGauge []metrics.Gauge for _, r := range registries { if r.ConfigReloadsCounter() != nil { configReloadsCounter = append(configReloadsCounter, r.ConfigReloadsCounter()) } if r.ConfigReloadsFailureCounter() != nil { configReloadsFailureCounter = append(configReloadsFailureCounter, r.ConfigReloadsFailureCounter()) } if r.LastConfigReloadSuccessGauge() != nil { lastConfigReloadSuccessGauge = append(lastConfigReloadSuccessGauge, r.LastConfigReloadSuccessGauge()) } if r.LastConfigReloadFailureGauge() != nil { lastConfigReloadFailureGauge = append(lastConfigReloadFailureGauge, r.LastConfigReloadFailureGauge()) } if r.EntryPointReqsCounter() != nil { entryPointReqsCounter = append(entryPointReqsCounter, r.EntryPointReqsCounter()) } if r.EntryPointReqsTLSCounter() != nil { entryPointReqsTLSCounter = append(entryPointReqsTLSCounter, r.EntryPointReqsTLSCounter()) } if r.EntryPointReqDurationHistogram() != nil { entryPointReqDurationHistogram = append(entryPointReqDurationHistogram, r.EntryPointReqDurationHistogram()) } if r.EntryPointOpenConnsGauge() != nil { entryPointOpenConnsGauge = append(entryPointOpenConnsGauge, r.EntryPointOpenConnsGauge()) } if r.ServiceReqsCounter() != nil { serviceReqsCounter = append(serviceReqsCounter, r.ServiceReqsCounter()) } if r.ServiceReqsTLSCounter() != nil { serviceReqsTLSCounter = append(serviceReqsTLSCounter, r.ServiceReqsTLSCounter()) } if r.ServiceReqDurationHistogram() != nil { serviceReqDurationHistogram = append(serviceReqDurationHistogram, r.ServiceReqDurationHistogram()) } if r.ServiceOpenConnsGauge() != nil { serviceOpenConnsGauge = append(serviceOpenConnsGauge, r.ServiceOpenConnsGauge()) } if r.ServiceRetriesCounter() != nil { serviceRetriesCounter = append(serviceRetriesCounter, r.ServiceRetriesCounter()) } if r.ServiceServerUpGauge() != nil { serviceServerUpGauge = append(serviceServerUpGauge, r.ServiceServerUpGauge()) } } return &standardRegistry{ epEnabled: len(entryPointReqsCounter) > 0 || len(entryPointReqDurationHistogram) > 0 || len(entryPointOpenConnsGauge) > 0, svcEnabled: len(serviceReqsCounter) > 0 || len(serviceReqDurationHistogram) > 0 || len(serviceOpenConnsGauge) > 0 || len(serviceRetriesCounter) > 0 || len(serviceServerUpGauge) > 0, configReloadsCounter: multi.NewCounter(configReloadsCounter...), configReloadsFailureCounter: multi.NewCounter(configReloadsFailureCounter...), lastConfigReloadSuccessGauge: multi.NewGauge(lastConfigReloadSuccessGauge...), lastConfigReloadFailureGauge: multi.NewGauge(lastConfigReloadFailureGauge...), entryPointReqsCounter: multi.NewCounter(entryPointReqsCounter...), entryPointReqsTLSCounter: multi.NewCounter(entryPointReqsTLSCounter...), entryPointReqDurationHistogram: multi.NewHistogram(entryPointReqDurationHistogram...), entryPointOpenConnsGauge: multi.NewGauge(entryPointOpenConnsGauge...), serviceReqsCounter: multi.NewCounter(serviceReqsCounter...), serviceReqsTLSCounter: multi.NewCounter(serviceReqsTLSCounter...), serviceReqDurationHistogram: multi.NewHistogram(serviceReqDurationHistogram...), serviceOpenConnsGauge: multi.NewGauge(serviceOpenConnsGauge...), serviceRetriesCounter: multi.NewCounter(serviceRetriesCounter...), serviceServerUpGauge: multi.NewGauge(serviceServerUpGauge...), } } type standardRegistry struct { epEnabled bool svcEnabled bool configReloadsCounter metrics.Counter configReloadsFailureCounter metrics.Counter lastConfigReloadSuccessGauge metrics.Gauge lastConfigReloadFailureGauge metrics.Gauge entryPointReqsCounter metrics.Counter entryPointReqsTLSCounter metrics.Counter entryPointReqDurationHistogram metrics.Histogram entryPointOpenConnsGauge metrics.Gauge serviceReqsCounter metrics.Counter serviceReqsTLSCounter metrics.Counter serviceReqDurationHistogram metrics.Histogram serviceOpenConnsGauge metrics.Gauge serviceRetriesCounter metrics.Counter serviceServerUpGauge metrics.Gauge } func (r *standardRegistry) IsEpEnabled() bool { return r.epEnabled } func (r *standardRegistry) IsSvcEnabled() bool { return r.svcEnabled } func (r *standardRegistry) ConfigReloadsCounter() metrics.Counter { return r.configReloadsCounter } func (r *standardRegistry) ConfigReloadsFailureCounter() metrics.Counter { return r.configReloadsFailureCounter } func (r *standardRegistry) LastConfigReloadSuccessGauge() metrics.Gauge { return r.lastConfigReloadSuccessGauge } func (r *standardRegistry) LastConfigReloadFailureGauge() metrics.Gauge { return r.lastConfigReloadFailureGauge } func (r *standardRegistry) EntryPointReqsCounter() metrics.Counter { return r.entryPointReqsCounter } func (r *standardRegistry) EntryPointReqsTLSCounter() metrics.Counter { return r.entryPointReqsTLSCounter } func (r *standardRegistry) EntryPointReqDurationHistogram() metrics.Histogram { return r.entryPointReqDurationHistogram } func (r *standardRegistry) EntryPointOpenConnsGauge() metrics.Gauge { return r.entryPointOpenConnsGauge } func (r *standardRegistry) ServiceReqsCounter() metrics.Counter { return r.serviceReqsCounter } func (r *standardRegistry) ServiceReqsTLSCounter() metrics.Counter { return r.serviceReqsTLSCounter } func (r *standardRegistry) ServiceReqDurationHistogram() metrics.Histogram { return r.serviceReqDurationHistogram } func (r *standardRegistry) ServiceOpenConnsGauge() metrics.Gauge { return r.serviceOpenConnsGauge } func (r *standardRegistry) ServiceRetriesCounter() metrics.Counter { return r.serviceRetriesCounter } func (r *standardRegistry) ServiceServerUpGauge() metrics.Gauge { return r.serviceServerUpGauge }