summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorWolfy-J <[email protected]>2019-06-26 16:38:52 +0300
committerWolfy-J <[email protected]>2019-06-26 16:38:52 +0300
commit4968bc66f01922cdf0e5bb6cbf891e99a10bb814 (patch)
treec187b73a55b4c1f891c8dbb488f71d231afd3638 /service
parent73ce97e6fccfc59ab759787891d2cc2f8d3f88a5 (diff)
custom application metrics
Diffstat (limited to 'service')
-rw-r--r--service/metrics/config.go20
-rw-r--r--service/metrics/rpc.go72
-rw-r--r--service/metrics/service.go31
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
+}