diff options
author | Wolfy-J <[email protected]> | 2019-06-26 16:38:52 +0300 |
---|---|---|
committer | Wolfy-J <[email protected]> | 2019-06-26 16:38:52 +0300 |
commit | 4968bc66f01922cdf0e5bb6cbf891e99a10bb814 (patch) | |
tree | c187b73a55b4c1f891c8dbb488f71d231afd3638 /service | |
parent | 73ce97e6fccfc59ab759787891d2cc2f8d3f88a5 (diff) |
custom application metrics
Diffstat (limited to 'service')
-rw-r--r-- | service/metrics/config.go | 20 | ||||
-rw-r--r-- | service/metrics/rpc.go | 72 | ||||
-rw-r--r-- | service/metrics/service.go | 31 |
3 files changed, 109 insertions, 14 deletions
diff --git a/service/metrics/config.go b/service/metrics/config.go index b93d8f50..b9b21ea9 100644 --- a/service/metrics/config.go +++ b/service/metrics/config.go @@ -11,11 +11,11 @@ type Config struct { Address string // Collect define application specific metrics. - Collect map[string]Metric + Collect map[string]Collector } -// Metric describes single application specific metric. -type Metric struct { +// Collector describes single application specific metric. +type Collector struct { // Namespace of the metric. Namespace string @@ -41,11 +41,13 @@ func (c *Config) Hydrate(cfg service.Config) error { } // register application specific metrics. -func (c *Config) registerMetrics() error { +func (c *Config) initCollectors() (map[string]prometheus.Collector, error) { if c.Collect == nil { - return nil + return nil, nil } + collectors := make(map[string]prometheus.Collector) + for name, m := range c.Collect { var collector prometheus.Collector switch m.Type { @@ -103,13 +105,15 @@ func (c *Config) registerMetrics() error { collector = prometheus.NewSummary(opts) } default: - return fmt.Errorf("invalid metric type %s", m.Type) + return nil, fmt.Errorf("invalid metric type `%s` for `%s`", m.Type, name) } if err := prometheus.Register(collector); err != nil { - return err + return nil, err } + + collectors[name] = collector } - return nil + return collectors, nil } diff --git a/service/metrics/rpc.go b/service/metrics/rpc.go new file mode 100644 index 00000000..5d1b8102 --- /dev/null +++ b/service/metrics/rpc.go @@ -0,0 +1,72 @@ +package metrics + +import ( + "fmt" + "github.com/prometheus/client_golang/prometheus" +) + +type rpcServer struct{ svc *Service } + +type Metric struct { + // Collector name. + Name string + + // Collector value. + Value float64 + + // Labels associated with metric. Only for vector metrics. + Labels []string +} + +// Add new metric to the designated collector. +func (rpc *rpcServer) Add(m *Metric, ok *bool) error { + c := rpc.svc.Collector(m.Name) + if c == nil { + return fmt.Errorf("undefined collector `%s`", m.Name) + } + + switch c.(type) { + case prometheus.Gauge: + c.(prometheus.Gauge).Add(m.Value) + + case *prometheus.GaugeVec: + if len(m.Labels) == 0 { + return fmt.Errorf("required labels for collector `%s`", m.Name) + } + + c.(*prometheus.GaugeVec).WithLabelValues(m.Labels...).Add(m.Value) + + case prometheus.Counter: + c.(prometheus.Counter).Add(m.Value) + + case *prometheus.CounterVec: + if len(m.Labels) == 0 { + return fmt.Errorf("required labels for collector `%s`", m.Name) + } + + c.(*prometheus.CounterVec).WithLabelValues(m.Labels...).Add(m.Value) + + case prometheus.Summary: + c.(prometheus.Counter).Add(m.Value) + + case *prometheus.SummaryVec: + if len(m.Labels) == 0 { + return fmt.Errorf("required labels for collector `%s`", m.Name) + } + + c.(*prometheus.SummaryVec).WithLabelValues(m.Labels...).Observe(m.Value) + + case prometheus.Histogram: + c.(prometheus.Histogram).Observe(m.Value) + + case *prometheus.HistogramVec: + if len(m.Labels) == 0 { + return fmt.Errorf("required labels for collector `%s`", m.Name) + } + + c.(*prometheus.HistogramVec).WithLabelValues(m.Labels...).Observe(m.Value) + } + + *ok = true + return nil +} diff --git a/service/metrics/service.go b/service/metrics/service.go index 2823b1a4..c7cfa376 100644 --- a/service/metrics/service.go +++ b/service/metrics/service.go @@ -4,6 +4,7 @@ import ( "context" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/spiral/roadrunner/service/rpc" "net/http" "sync" ) @@ -13,14 +14,22 @@ const ID = "metrics" // Service to manage application metrics using Prometheus. type Service struct { - cfg *Config - mu sync.Mutex - http *http.Server + cfg *Config + mu sync.Mutex + http *http.Server + collectors map[string]prometheus.Collector } // Init service. -func (s *Service) Init(cfg *Config) (bool, error) { +func (s *Service) Init(cfg *Config, r *rpc.Service) (bool, error) { s.cfg = cfg + + if r != nil { + if err := r.Register(ID, &rpcServer{s}); err != nil { + return false, err + } + } + return true, nil } @@ -42,9 +51,9 @@ func (s *Service) MustRegister(c prometheus.Collector) { } // Serve prometheus metrics service. -func (s *Service) Serve() error { +func (s *Service) Serve() (err error) { // register application specific metrics - if err := s.cfg.registerMetrics(); err != nil { + if s.collectors, err = s.cfg.initCollectors(); err != nil { return err } @@ -65,3 +74,13 @@ func (s *Service) Stop() { go s.http.Shutdown(context.Background()) } } + +// Collector returns application specific collector by name or nil if collector not found. +func (s *Service) Collector(name string) prometheus.Collector { + collector, ok := s.collectors[name] + if !ok { + return nil + } + + return collector +} |