diff options
Diffstat (limited to 'service/metrics')
-rw-r--r-- | service/metrics/config.go | 27 | ||||
-rw-r--r-- | service/metrics/rpc.go | 10 | ||||
-rw-r--r-- | service/metrics/rpc_test.go | 168 |
3 files changed, 177 insertions, 28 deletions
diff --git a/service/metrics/config.go b/service/metrics/config.go index 341d0c70..bee4f3d1 100644 --- a/service/metrics/config.go +++ b/service/metrics/config.go @@ -23,6 +23,23 @@ type NamedCollector struct { 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. @@ -32,7 +49,7 @@ type Collector struct { Subsystem string // Collector type (histogram, gauge, counter, summary). - Type string + Type CollectorType // Help of collector. Help string @@ -60,7 +77,7 @@ func (c *Config) getCollectors() (map[string]prometheus.Collector, error) { for name, m := range c.Collect { var collector prometheus.Collector switch m.Type { - case "histogram": + case Histogram: opts := prometheus.HistogramOpts{ Name: name, Namespace: m.Namespace, @@ -74,7 +91,7 @@ func (c *Config) getCollectors() (map[string]prometheus.Collector, error) { } else { collector = prometheus.NewHistogram(opts) } - case "gauge": + case Gauge: opts := prometheus.GaugeOpts{ Name: name, Namespace: m.Namespace, @@ -87,7 +104,7 @@ func (c *Config) getCollectors() (map[string]prometheus.Collector, error) { } else { collector = prometheus.NewGauge(opts) } - case "counter": + case Counter: opts := prometheus.CounterOpts{ Name: name, Namespace: m.Namespace, @@ -100,7 +117,7 @@ func (c *Config) getCollectors() (map[string]prometheus.Collector, error) { } else { collector = prometheus.NewCounter(opts) } - case "summary": + case Summary: opts := prometheus.SummaryOpts{ Name: name, Namespace: m.Namespace, diff --git a/service/metrics/rpc.go b/service/metrics/rpc.go index 285feee1..9a36f14c 100644 --- a/service/metrics/rpc.go +++ b/service/metrics/rpc.go @@ -158,7 +158,7 @@ func (rpc *rpcServer) Register(c *NamedCollector, ok *bool) (err error) { var collector prometheus.Collector switch c.Type { - case "histogram": + case Histogram: opts := prometheus.HistogramOpts{ Name: c.Name, Namespace: c.Namespace, @@ -172,7 +172,7 @@ func (rpc *rpcServer) Register(c *NamedCollector, ok *bool) (err error) { } else { collector = prometheus.NewHistogram(opts) } - case "gauge": + case Gauge: opts := prometheus.GaugeOpts{ Name: c.Name, Namespace: c.Namespace, @@ -185,7 +185,7 @@ func (rpc *rpcServer) Register(c *NamedCollector, ok *bool) (err error) { } else { collector = prometheus.NewGauge(opts) } - case "counter": + case Counter: opts := prometheus.CounterOpts{ Name: c.Name, Namespace: c.Namespace, @@ -198,7 +198,7 @@ func (rpc *rpcServer) Register(c *NamedCollector, ok *bool) (err error) { } else { collector = prometheus.NewCounter(opts) } - case "summary": + case Summary: opts := prometheus.SummaryOpts{ Name: c.Name, Namespace: c.Namespace, @@ -217,6 +217,8 @@ func (rpc *rpcServer) Register(c *NamedCollector, ok *bool) (err error) { } + // add collector to sync.Map + rpc.svc.collectors.Store(c.Name, collector) // that method might panic, we handle it by recover rpc.svc.MustRegister(collector) diff --git a/service/metrics/rpc_test.go b/service/metrics/rpc_test.go index 332f0f65..3ef205c4 100644 --- a/service/metrics/rpc_test.go +++ b/service/metrics/rpc_test.go @@ -240,7 +240,7 @@ func Test_Sub_RPC_Vector(t *testing.T) { assert.Contains(t, out, `user_gauge{section="first",type="core"} 90`) } -func Test_Register_RPC(t *testing.T) { +func Test_Register_RPC_Histogram(t *testing.T) { client, c := setup( t, `"user_gauge":{ @@ -250,17 +250,17 @@ func Test_Register_RPC(t *testing.T) { "2319", ) defer c.Stop() - + var ok bool assert.NoError(t, client.Call("metrics.Register", &NamedCollector{ - Name: "custom_histogram", + Name: "custom_histogram", Collector: Collector{ Namespace: "test_histogram", Subsystem: "test_histogram", - Type: "histogram", + Type: Histogram, Help: "test_histogram", Labels: nil, - Buckets: nil, + Buckets: []float64{0.1, 0.2, 0.5}, }, }, &ok)) assert.True(t, ok) @@ -268,28 +268,152 @@ func Test_Register_RPC(t *testing.T) { var ok2 bool // histogram does not support Add, should be an error assert.Error(t, client.Call("metrics.Add", Metric{ - Name: "custom_histogram", + Name: "custom_histogram", }, &ok2)) // ok should became false assert.False(t, ok2) + out, _, err := get("http://localhost:2319/metrics") + assert.NoError(t, err) + assert.Contains(t, out, `TYPE test_histogram_test_histogram_custom_histogram histogram`) + + // check buckets + assert.Contains(t, out, `test_histogram_test_histogram_custom_histogram_bucket{le="0.1"} 0`) + assert.Contains(t, out, `test_histogram_test_histogram_custom_histogram_bucket{le="0.2"} 0`) + assert.Contains(t, out, `test_histogram_test_histogram_custom_histogram_bucket{le="0.5"} 0`) +} + +func Test_Register_RPC_Gauge(t *testing.T) { + // FOR register method, setup used just to init the rpc + client, c := setup( + t, + `"user_gauge":{ + "type": "gauge", + "labels": ["type", "section"] + }`, + "2324", + ) + defer c.Stop() + + var ok bool + assert.NoError(t, client.Call("metrics.Register", &NamedCollector{ + Name: "custom_gauge", + Collector: Collector{ + Namespace: "test_gauge", + Subsystem: "test_gauge", + Type: Gauge, + Help: "test_gauge", + Labels: []string{"type", "section"}, + Buckets: nil, + }, + }, &ok)) + assert.True(t, ok) + + var ok2 bool + // Add to custom_gauge + assert.NoError(t, client.Call("metrics.Add", Metric{ + Name: "custom_gauge", + Value: 100.0, + Labels: []string{"core", "first"}, + }, &ok2)) + // ok should became true + assert.True(t, ok2) + + // Subtract from custom runtime metric + var ok3 bool + assert.NoError(t, client.Call("metrics.Sub", Metric{ + Name: "custom_gauge", + Value: 10.0, + Labels: []string{"core", "first"}, + }, &ok3)) + assert.True(t, ok3) + + out, _, err := get("http://localhost:2324/metrics") + assert.NoError(t, err) + assert.Contains(t, out, `test_gauge_test_gauge_custom_gauge{section="first",type="core"} 90`) +} + +func Test_Register_RPC_Counter(t *testing.T) { + // FOR register method, setup used just to init the rpc + client, c := setup( + t, + `"user_gauge":{ + "type": "gauge", + "labels": ["type", "section"] + }`, + "2328", + ) + defer c.Stop() + + var ok bool + assert.NoError(t, client.Call("metrics.Register", &NamedCollector{ + Name: "custom_counter", + Collector: Collector{ + Namespace: "test_counter", + Subsystem: "test_counter", + Type: Counter, + Help: "test_counter", + Labels: []string{"type", "section"}, + Buckets: nil, + }, + }, &ok)) + assert.True(t, ok) + var ok2 bool + // Add to custom_counter + assert.NoError(t, client.Call("metrics.Add", Metric{ + Name: "custom_counter", + Value: 100.0, + Labels: []string{"type2", "section2"}, + }, &ok2)) + // ok should became true + assert.True(t, ok2) + out, _, err := get("http://localhost:2328/metrics") + assert.NoError(t, err) + assert.Contains(t, out, `test_counter_test_counter_custom_counter{section="section2",type="type2"} 100`) +} +func Test_Register_RPC_Summary(t *testing.T) { + // FOR register method, setup used just to init the rpc + client, c := setup( + t, + `"user_gauge":{ + "type": "gauge", + "labels": ["type", "section"] + }`, + "6666", + ) + defer c.Stop() - // reset ok - //ok = false - // - //assert.NoError(t, client.Call("metrics.Sub", Metric{ - // Name: "user_gauge", - // Value: 10.0, - // Labels: []string{"core", "first"}, - //}, &ok)) - //assert.True(t, ok) - // - //out, _, err := get("http://localhost:2119/metrics") - //assert.NoError(t, err) - //assert.Contains(t, out, `user_gauge{section="first",type="core"} 90`) + var ok bool + assert.NoError(t, client.Call("metrics.Register", &NamedCollector{ + Name: "custom_summary", + Collector: Collector{ + Namespace: "test_summary", + Subsystem: "test_summary", + Type: Summary, + Help: "test_summary", + Labels: nil, + Buckets: nil, + }, + }, &ok)) + assert.True(t, ok) + + var ok2 bool + // Add to custom_summary is not supported + assert.Error(t, client.Call("metrics.Add", Metric{ + Name: "custom_summary", + Value: 100.0, + Labels: []string{"type22", "section22"}, + }, &ok2)) + // ok should became false + assert.False(t, ok2) + + out, _, err := get("http://localhost:6666/metrics") + assert.NoError(t, err) + assert.Contains(t, out, `test_summary_test_summary_custom_summary_sum 0`) + assert.Contains(t, out, `test_summary_test_summary_custom_summary_count 0`) } func Test_Sub_RPC_CollectorError(t *testing.T) { @@ -673,6 +797,8 @@ func Test_Add_RPC_CollectorError(t *testing.T) { Value: 100.0, Labels: []string{"missing"}, }, &ok)) + + assert.False(t, ok) } func Test_Add_RPC_MetricError(t *testing.T) { @@ -692,6 +818,8 @@ func Test_Add_RPC_MetricError(t *testing.T) { Value: 100.0, Labels: []string{"missing"}, }, &ok)) + + assert.False(t, ok) } func Test_Add_RPC_MetricError_2(t *testing.T) { @@ -710,6 +838,8 @@ func Test_Add_RPC_MetricError_2(t *testing.T) { Name: "user_gauge", Value: 100.0, }, &ok)) + + assert.False(t, ok) } func Test_Add_RPC_MetricError_3(t *testing.T) { |