summaryrefslogtreecommitdiff
path: root/plugins/metrics
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/metrics')
-rw-r--r--plugins/metrics/config.go140
-rw-r--r--plugins/metrics/config_test.go89
-rw-r--r--plugins/metrics/doc.go1
-rw-r--r--plugins/metrics/interface.go7
-rw-r--r--plugins/metrics/plugin.go242
-rw-r--r--plugins/metrics/rpc.go294
6 files changed, 0 insertions, 773 deletions
diff --git a/plugins/metrics/config.go b/plugins/metrics/config.go
deleted file mode 100644
index a2835130..00000000
--- a/plugins/metrics/config.go
+++ /dev/null
@@ -1,140 +0,0 @@
-package metrics
-
-import (
- "fmt"
-
- "github.com/prometheus/client_golang/prometheus"
-)
-
-// Config configures metrics service.
-type Config struct {
- // Address to listen
- Address string
-
- // Collect define application specific metrics.
- Collect map[string]Collector
-}
-
-type NamedCollector struct {
- // Name of the collector
- Name string `json:"name"`
-
- // Collector structure
- Collector `json:"collector"`
-}
-
-// CollectorType represents prometheus collector types
-type CollectorType string
-
-const (
- // Histogram type
- Histogram CollectorType = "histogram"
-
- // Gauge type
- Gauge CollectorType = "gauge"
-
- // Counter type
- Counter CollectorType = "counter"
-
- // Summary type
- Summary CollectorType = "summary"
-)
-
-// Collector describes single application specific metric.
-type Collector struct {
- // Namespace of the metric.
- Namespace string `json:"namespace"`
- // Subsystem of the metric.
- Subsystem string `json:"subsystem"`
- // Collector type (histogram, gauge, counter, summary).
- Type CollectorType `json:"type"`
- // Help of collector.
- Help string `json:"help"`
- // Labels for vectorized metrics.
- Labels []string `json:"labels"`
- // Buckets for histogram metric.
- Buckets []float64 `json:"buckets"`
- // Objectives for the summary opts
- Objectives map[float64]float64 `json:"objectives"`
-}
-
-// register application specific metrics.
-func (c *Config) getCollectors() (map[string]prometheus.Collector, error) {
- if c.Collect == nil {
- return nil, nil
- }
-
- collectors := make(map[string]prometheus.Collector)
-
- for name, m := range c.Collect {
- var collector prometheus.Collector
- switch m.Type {
- case Histogram:
- opts := prometheus.HistogramOpts{
- Name: name,
- Namespace: m.Namespace,
- Subsystem: m.Subsystem,
- Help: m.Help,
- Buckets: m.Buckets,
- }
-
- if len(m.Labels) != 0 {
- collector = prometheus.NewHistogramVec(opts, m.Labels)
- } else {
- collector = prometheus.NewHistogram(opts)
- }
- case Gauge:
- opts := prometheus.GaugeOpts{
- Name: name,
- Namespace: m.Namespace,
- Subsystem: m.Subsystem,
- Help: m.Help,
- }
-
- if len(m.Labels) != 0 {
- collector = prometheus.NewGaugeVec(opts, m.Labels)
- } else {
- collector = prometheus.NewGauge(opts)
- }
- case Counter:
- opts := prometheus.CounterOpts{
- Name: name,
- Namespace: m.Namespace,
- Subsystem: m.Subsystem,
- Help: m.Help,
- }
-
- if len(m.Labels) != 0 {
- collector = prometheus.NewCounterVec(opts, m.Labels)
- } else {
- collector = prometheus.NewCounter(opts)
- }
- case Summary:
- opts := prometheus.SummaryOpts{
- Name: name,
- Namespace: m.Namespace,
- Subsystem: m.Subsystem,
- Help: m.Help,
- Objectives: m.Objectives,
- }
-
- if len(m.Labels) != 0 {
- collector = prometheus.NewSummaryVec(opts, m.Labels)
- } else {
- collector = prometheus.NewSummary(opts)
- }
- default:
- return nil, fmt.Errorf("invalid metric type `%s` for `%s`", m.Type, name)
- }
-
- collectors[name] = collector
- }
-
- return collectors, nil
-}
-
-func (c *Config) InitDefaults() {
- if c.Address == "" {
- c.Address = "127.0.0.1:2112"
- }
-}
diff --git a/plugins/metrics/config_test.go b/plugins/metrics/config_test.go
deleted file mode 100644
index 665ec9cd..00000000
--- a/plugins/metrics/config_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package metrics
-
-import (
- "bytes"
- "testing"
-
- j "github.com/json-iterator/go"
- "github.com/prometheus/client_golang/prometheus"
- "github.com/stretchr/testify/assert"
-)
-
-var json = j.ConfigCompatibleWithStandardLibrary
-
-func Test_Config_Hydrate_Error1(t *testing.T) {
- cfg := `{"request": {"From": "Something"}}`
- c := &Config{}
- f := new(bytes.Buffer)
- f.WriteString(cfg)
-
- err := json.Unmarshal(f.Bytes(), &c)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func Test_Config_Hydrate_Error2(t *testing.T) {
- cfg := `{"dir": "/dir/"`
- c := &Config{}
-
- f := new(bytes.Buffer)
- f.WriteString(cfg)
-
- err := json.Unmarshal(f.Bytes(), &c)
- assert.Error(t, err)
-}
-
-func Test_Config_Metrics(t *testing.T) {
- cfg := `{
-"collect":{
- "metric1":{"type": "gauge"},
- "metric2":{ "type": "counter"},
- "metric3":{"type": "summary"},
- "metric4":{"type": "histogram"}
-}
-}`
- c := &Config{}
- f := new(bytes.Buffer)
- f.WriteString(cfg)
-
- err := json.Unmarshal(f.Bytes(), &c)
- if err != nil {
- t.Fatal(err)
- }
-
- m, err := c.getCollectors()
- assert.NoError(t, err)
-
- assert.IsType(t, prometheus.NewGauge(prometheus.GaugeOpts{}), m["metric1"])
- assert.IsType(t, prometheus.NewCounter(prometheus.CounterOpts{}), m["metric2"])
- assert.IsType(t, prometheus.NewSummary(prometheus.SummaryOpts{}), m["metric3"])
- assert.IsType(t, prometheus.NewHistogram(prometheus.HistogramOpts{}), m["metric4"])
-}
-
-func Test_Config_MetricsVector(t *testing.T) {
- cfg := `{
-"collect":{
- "metric1":{"type": "gauge","labels":["label"]},
- "metric2":{ "type": "counter","labels":["label"]},
- "metric3":{"type": "summary","labels":["label"]},
- "metric4":{"type": "histogram","labels":["label"]}
-}
-}`
- c := &Config{}
- f := new(bytes.Buffer)
- f.WriteString(cfg)
-
- err := json.Unmarshal(f.Bytes(), &c)
- if err != nil {
- t.Fatal(err)
- }
-
- m, err := c.getCollectors()
- assert.NoError(t, err)
-
- assert.IsType(t, prometheus.NewGaugeVec(prometheus.GaugeOpts{}, []string{}), m["metric1"])
- assert.IsType(t, prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{}), m["metric2"])
- assert.IsType(t, prometheus.NewSummaryVec(prometheus.SummaryOpts{}, []string{}), m["metric3"])
- assert.IsType(t, prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{}), m["metric4"])
-}
diff --git a/plugins/metrics/doc.go b/plugins/metrics/doc.go
deleted file mode 100644
index 1abe097a..00000000
--- a/plugins/metrics/doc.go
+++ /dev/null
@@ -1 +0,0 @@
-package metrics
diff --git a/plugins/metrics/interface.go b/plugins/metrics/interface.go
deleted file mode 100644
index 87ba4017..00000000
--- a/plugins/metrics/interface.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package metrics
-
-import "github.com/prometheus/client_golang/prometheus"
-
-type StatProvider interface {
- MetricsCollector() []prometheus.Collector
-}
diff --git a/plugins/metrics/plugin.go b/plugins/metrics/plugin.go
deleted file mode 100644
index d285e609..00000000
--- a/plugins/metrics/plugin.go
+++ /dev/null
@@ -1,242 +0,0 @@
-package metrics
-
-import (
- "context"
- "crypto/tls"
- "net/http"
- "sync"
- "time"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/collectors"
- "github.com/prometheus/client_golang/prometheus/promhttp"
- "github.com/spiral/errors"
- "github.com/spiral/roadrunner/v2/plugins/config"
- "github.com/spiral/roadrunner/v2/plugins/logger"
- "golang.org/x/sys/cpu"
-)
-
-const (
- // PluginName declares plugin name.
- PluginName = "metrics"
- // maxHeaderSize declares max header size for prometheus server
- maxHeaderSize = 1024 * 1024 * 100 // 104MB
-)
-
-// Plugin to manage application metrics using Prometheus.
-type Plugin struct {
- cfg *Config
- log logger.Logger
- mu sync.Mutex // all receivers are pointers
- http *http.Server
- collectors sync.Map // all receivers are pointers
- registry *prometheus.Registry
-
- // prometheus Collectors
- statProviders []StatProvider
-}
-
-// Init service.
-func (p *Plugin) Init(cfg config.Configurer, log logger.Logger) error {
- const op = errors.Op("metrics_plugin_init")
- if !cfg.Has(PluginName) {
- return errors.E(op, errors.Disabled)
- }
-
- err := cfg.UnmarshalKey(PluginName, &p.cfg)
- if err != nil {
- return errors.E(op, errors.Disabled, err)
- }
-
- p.cfg.InitDefaults()
-
- p.log = log
- p.registry = prometheus.NewRegistry()
-
- // Default
- err = p.registry.Register(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
- if err != nil {
- return errors.E(op, err)
- }
-
- // Default
- err = p.registry.Register(collectors.NewGoCollector())
- if err != nil {
- return errors.E(op, err)
- }
-
- cl, err := p.cfg.getCollectors()
- if err != nil {
- return errors.E(op, err)
- }
-
- // Register invocation will be later in the Serve method
- for k, v := range cl {
- p.collectors.Store(k, v)
- }
-
- p.statProviders = make([]StatProvider, 0, 2)
-
- return nil
-}
-
-// Register new prometheus collector.
-func (p *Plugin) Register(c prometheus.Collector) error {
- return p.registry.Register(c)
-}
-
-// Serve prometheus metrics service.
-func (p *Plugin) Serve() chan error {
- errCh := make(chan error, 1)
-
- // register Collected stat providers
- for i := 0; i < len(p.statProviders); i++ {
- sp := p.statProviders[i]
- for _, c := range sp.MetricsCollector() {
- err := p.registry.Register(c)
- if err != nil {
- errCh <- err
- return errCh
- }
- }
- }
-
- p.collectors.Range(func(key, value interface{}) bool {
- // key - name
- // value - prometheus.Collector
- c := value.(prometheus.Collector)
- if err := p.registry.Register(c); err != nil {
- errCh <- err
- return false
- }
-
- return true
- })
-
- var topCipherSuites []uint16
- var defaultCipherSuitesTLS13 []uint16
-
- hasGCMAsmAMD64 := cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
- hasGCMAsmARM64 := cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
- // Keep in sync with crypto/aes/cipher_s390x.go.
- hasGCMAsmS390X := cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
-
- hasGCMAsm := hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X
-
- if hasGCMAsm {
- // If AES-GCM hardware is provided then prioritize AES-GCM
- // cipher suites.
- topCipherSuites = []uint16{
- tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
- tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
- }
- defaultCipherSuitesTLS13 = []uint16{
- tls.TLS_AES_128_GCM_SHA256,
- tls.TLS_CHACHA20_POLY1305_SHA256,
- tls.TLS_AES_256_GCM_SHA384,
- }
- } else {
- // Without AES-GCM hardware, we put the ChaCha20-Poly1305
- // cipher suites first.
- topCipherSuites = []uint16{
- tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
- tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
- tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- }
- defaultCipherSuitesTLS13 = []uint16{
- tls.TLS_CHACHA20_POLY1305_SHA256,
- tls.TLS_AES_128_GCM_SHA256,
- tls.TLS_AES_256_GCM_SHA384,
- }
- }
-
- DefaultCipherSuites := make([]uint16, 0, 22)
- DefaultCipherSuites = append(DefaultCipherSuites, topCipherSuites...)
- DefaultCipherSuites = append(DefaultCipherSuites, defaultCipherSuitesTLS13...)
-
- p.http = &http.Server{
- Addr: p.cfg.Address,
- Handler: promhttp.HandlerFor(p.registry, promhttp.HandlerOpts{}),
- IdleTimeout: time.Hour * 24,
- ReadTimeout: time.Minute * 60,
- MaxHeaderBytes: maxHeaderSize,
- ReadHeaderTimeout: time.Minute * 60,
- WriteTimeout: time.Minute * 60,
- TLSConfig: &tls.Config{
- CurvePreferences: []tls.CurveID{
- tls.CurveP256,
- tls.CurveP384,
- tls.CurveP521,
- tls.X25519,
- },
- CipherSuites: DefaultCipherSuites,
- MinVersion: tls.VersionTLS12,
- PreferServerCipherSuites: true,
- },
- }
-
- go func() {
- err := p.http.ListenAndServe()
- if err != nil && err != http.ErrServerClosed {
- errCh <- err
- return
- }
- }()
-
- return errCh
-}
-
-// Stop prometheus metrics service.
-func (p *Plugin) Stop() error {
- p.mu.Lock()
- defer p.mu.Unlock()
-
- if p.http != nil {
- // timeout is 10 seconds
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
- defer cancel()
- err := p.http.Shutdown(ctx)
- if err != nil {
- // Function should be Stop() error
- p.log.Error("stop error", "error", errors.Errorf("error shutting down the metrics server: error %v", err))
- }
- }
- return nil
-}
-
-// Collects used to collect all plugins which implement metrics.StatProvider interface (and Named)
-func (p *Plugin) Collects() []interface{} {
- return []interface{}{
- p.AddStatProvider,
- }
-}
-
-// AddStatProvider adds a metrics provider
-func (p *Plugin) AddStatProvider(stat StatProvider) error {
- p.statProviders = append(p.statProviders, stat)
-
- return nil
-}
-
-// Name returns user friendly plugin name
-func (p *Plugin) Name() string {
- return PluginName
-}
-
-// RPC interface satisfaction
-func (p *Plugin) RPC() interface{} {
- return &rpcServer{
- svc: p,
- log: p.log,
- }
-}
-
-// Available interface implementation
-func (p *Plugin) Available() {}
diff --git a/plugins/metrics/rpc.go b/plugins/metrics/rpc.go
deleted file mode 100644
index 538cdb78..00000000
--- a/plugins/metrics/rpc.go
+++ /dev/null
@@ -1,294 +0,0 @@
-package metrics
-
-import (
- "github.com/prometheus/client_golang/prometheus"
- "github.com/spiral/errors"
- "github.com/spiral/roadrunner/v2/plugins/logger"
-)
-
-type rpcServer struct {
- svc *Plugin
- log logger.Logger
-}
-
-// Metric represent single metric produced by the application.
-type Metric struct {
- // Collector name.
- Name string
-
- // Collector value.
- Value float64
-
- // Labels associated with metric. Only for vector metrics. Must be provided in a form of label values.
- Labels []string
-}
-
-// Add new metric to the designated collector.
-func (rpc *rpcServer) Add(m *Metric, ok *bool) error {
- const op = errors.Op("metrics_plugin_add")
- rpc.log.Info("adding metric", "name", m.Name, "value", m.Value, "labels", m.Labels)
- c, exist := rpc.svc.collectors.Load(m.Name)
- if !exist {
- rpc.log.Error("undefined collector", "collector", m.Name)
- return errors.E(op, errors.Errorf("undefined collector %s, try first Declare the desired collector", m.Name))
- }
-
- switch c := c.(type) {
- case prometheus.Gauge:
- c.Add(m.Value)
-
- case *prometheus.GaugeVec:
- if len(m.Labels) == 0 {
- rpc.log.Error("required labels for collector", "collector", m.Name)
- return errors.E(op, errors.Errorf("required labels for collector %s", m.Name))
- }
-
- gauge, err := c.GetMetricWithLabelValues(m.Labels...)
- if err != nil {
- rpc.log.Error("failed to get metrics with label values", "collector", m.Name, "labels", m.Labels)
- return errors.E(op, err)
- }
- gauge.Add(m.Value)
- case prometheus.Counter:
- c.Add(m.Value)
-
- case *prometheus.CounterVec:
- if len(m.Labels) == 0 {
- return errors.E(op, errors.Errorf("required labels for collector `%s`", m.Name))
- }
-
- gauge, err := c.GetMetricWithLabelValues(m.Labels...)
- if err != nil {
- rpc.log.Error("failed to get metrics with label values", "collector", m.Name, "labels", m.Labels)
- return errors.E(op, err)
- }
- gauge.Add(m.Value)
-
- default:
- return errors.E(op, errors.Errorf("collector %s does not support method `Add`", m.Name))
- }
-
- // RPC, set ok to true as return value. Need by rpc.Call reply argument
- *ok = true
- rpc.log.Info("metric successfully added", "name", m.Name, "labels", m.Labels, "value", m.Value)
- return nil
-}
-
-// Sub subtract the value from the specific metric (gauge only).
-func (rpc *rpcServer) Sub(m *Metric, ok *bool) error {
- const op = errors.Op("metrics_plugin_sub")
- rpc.log.Info("subtracting value from metric", "name", m.Name, "value", m.Value, "labels", m.Labels)
- c, exist := rpc.svc.collectors.Load(m.Name)
- if !exist {
- rpc.log.Error("undefined collector", "name", m.Name, "value", m.Value, "labels", m.Labels)
- return errors.E(op, errors.Errorf("undefined collector %s", m.Name))
- }
- if c == nil {
- // can it be nil ??? I guess can't
- return errors.E(op, errors.Errorf("undefined collector %s", m.Name))
- }
-
- switch c := c.(type) {
- case prometheus.Gauge:
- c.Sub(m.Value)
-
- case *prometheus.GaugeVec:
- if len(m.Labels) == 0 {
- rpc.log.Error("required labels for collector, but none was provided", "name", m.Name, "value", m.Value)
- return errors.E(op, errors.Errorf("required labels for collector %s", m.Name))
- }
-
- gauge, err := c.GetMetricWithLabelValues(m.Labels...)
- if err != nil {
- rpc.log.Error("failed to get metrics with label values", "collector", m.Name, "labels", m.Labels)
- return errors.E(op, err)
- }
- gauge.Sub(m.Value)
- default:
- return errors.E(op, errors.Errorf("collector `%s` does not support method `Sub`", m.Name))
- }
- rpc.log.Info("subtracting operation finished successfully", "name", m.Name, "labels", m.Labels, "value", m.Value)
-
- *ok = true
- return nil
-}
-
-// Observe the value (histogram and summary only).
-func (rpc *rpcServer) Observe(m *Metric, ok *bool) error {
- const op = errors.Op("metrics_plugin_observe")
- rpc.log.Info("observing metric", "name", m.Name, "value", m.Value, "labels", m.Labels)
-
- c, exist := rpc.svc.collectors.Load(m.Name)
- if !exist {
- rpc.log.Error("undefined collector", "name", m.Name, "value", m.Value, "labels", m.Labels)
- return errors.E(op, errors.Errorf("undefined collector %s", m.Name))
- }
- if c == nil {
- return errors.E(op, errors.Errorf("undefined collector %s", m.Name))
- }
-
- switch c := c.(type) {
- case *prometheus.SummaryVec:
- if len(m.Labels) == 0 {
- return errors.E(op, errors.Errorf("required labels for collector `%s`", m.Name))
- }
-
- observer, err := c.GetMetricWithLabelValues(m.Labels...)
- if err != nil {
- return errors.E(op, err)
- }
- observer.Observe(m.Value)
-
- case prometheus.Histogram:
- c.Observe(m.Value)
-
- case *prometheus.HistogramVec:
- if len(m.Labels) == 0 {
- return errors.E(op, errors.Errorf("required labels for collector `%s`", m.Name))
- }
-
- observer, err := c.GetMetricWithLabelValues(m.Labels...)
- if err != nil {
- rpc.log.Error("failed to get metrics with label values", "collector", m.Name, "labels", m.Labels)
- return errors.E(op, err)
- }
- observer.Observe(m.Value)
- default:
- return errors.E(op, errors.Errorf("collector `%s` does not support method `Observe`", m.Name))
- }
-
- rpc.log.Info("observe operation finished successfully", "name", m.Name, "labels", m.Labels, "value", m.Value)
-
- *ok = true
- return nil
-}
-
-// Declare is used to register new collector in prometheus
-// THE TYPES ARE:
-// NamedCollector -> Collector with the name
-// bool -> RPC reply value
-// RETURNS:
-// error
-func (rpc *rpcServer) Declare(nc *NamedCollector, ok *bool) error {
- const op = errors.Op("metrics_plugin_declare")
- rpc.log.Info("declaring new metric", "name", nc.Name, "type", nc.Type, "namespace", nc.Namespace)
- _, exist := rpc.svc.collectors.Load(nc.Name)
- if exist {
- rpc.log.Error("metric with provided name already exist", "name", nc.Name, "type", nc.Type, "namespace", nc.Namespace)
- return errors.E(op, errors.Errorf("tried to register existing collector with the name `%s`", nc.Name))
- }
-
- var collector prometheus.Collector
- switch nc.Type {
- case Histogram:
- opts := prometheus.HistogramOpts{
- Name: nc.Name,
- Namespace: nc.Namespace,
- Subsystem: nc.Subsystem,
- Help: nc.Help,
- Buckets: nc.Buckets,
- }
-
- if len(nc.Labels) != 0 {
- collector = prometheus.NewHistogramVec(opts, nc.Labels)
- } else {
- collector = prometheus.NewHistogram(opts)
- }
- case Gauge:
- opts := prometheus.GaugeOpts{
- Name: nc.Name,
- Namespace: nc.Namespace,
- Subsystem: nc.Subsystem,
- Help: nc.Help,
- }
-
- if len(nc.Labels) != 0 {
- collector = prometheus.NewGaugeVec(opts, nc.Labels)
- } else {
- collector = prometheus.NewGauge(opts)
- }
- case Counter:
- opts := prometheus.CounterOpts{
- Name: nc.Name,
- Namespace: nc.Namespace,
- Subsystem: nc.Subsystem,
- Help: nc.Help,
- }
-
- if len(nc.Labels) != 0 {
- collector = prometheus.NewCounterVec(opts, nc.Labels)
- } else {
- collector = prometheus.NewCounter(opts)
- }
- case Summary:
- opts := prometheus.SummaryOpts{
- Name: nc.Name,
- Namespace: nc.Namespace,
- Subsystem: nc.Subsystem,
- Help: nc.Help,
- }
-
- if len(nc.Labels) != 0 {
- collector = prometheus.NewSummaryVec(opts, nc.Labels)
- } else {
- collector = prometheus.NewSummary(opts)
- }
-
- default:
- return errors.E(op, errors.Errorf("unknown collector type %s", nc.Type))
- }
-
- // add collector to sync.Map
- rpc.svc.collectors.Store(nc.Name, collector)
- // that method might panic, we handle it by recover
- err := rpc.svc.Register(collector)
- if err != nil {
- *ok = false
- return errors.E(op, err)
- }
-
- rpc.log.Info("metric successfully added", "name", nc.Name, "type", nc.Type, "namespace", nc.Namespace)
-
- *ok = true
- return nil
-}
-
-// Set the metric value (only for gaude).
-func (rpc *rpcServer) Set(m *Metric, ok *bool) (err error) {
- const op = errors.Op("metrics_plugin_set")
- rpc.log.Info("observing metric", "name", m.Name, "value", m.Value, "labels", m.Labels)
-
- c, exist := rpc.svc.collectors.Load(m.Name)
- if !exist {
- return errors.E(op, errors.Errorf("undefined collector %s", m.Name))
- }
- if c == nil {
- return errors.E(op, errors.Errorf("undefined collector %s", m.Name))
- }
-
- switch c := c.(type) {
- case prometheus.Gauge:
- c.Set(m.Value)
-
- case *prometheus.GaugeVec:
- if len(m.Labels) == 0 {
- rpc.log.Error("required labels for collector", "collector", m.Name)
- return errors.E(op, errors.Errorf("required labels for collector %s", m.Name))
- }
-
- gauge, err := c.GetMetricWithLabelValues(m.Labels...)
- if err != nil {
- rpc.log.Error("failed to get metrics with label values", "collector", m.Name, "labels", m.Labels)
- return errors.E(op, err)
- }
- gauge.Set(m.Value)
-
- default:
- return errors.E(op, errors.Errorf("collector `%s` does not support method Set", m.Name))
- }
-
- rpc.log.Info("set operation finished successfully", "name", m.Name, "labels", m.Labels, "value", m.Value)
-
- *ok = true
- return nil
-}