Permalink
Browse files

Merge pull request #23 from performancecopilot/custom-metric-types

add custom metric types, closes #5
  • Loading branch information...
2 parents b8cc339 + ec80fee commit 0907c1ee1b56bd6e46111388cd5834d95093a7f0 @suyash suyash committed Aug 11, 2016
Showing with 732 additions and 22 deletions.
  1. +1 −1 Makefile
  2. +25 −0 client.go
  3. +267 −0 client_test.go
  4. +3 −10 examples/http_counter/server.go
  5. +2 −9 examples/singleton_counter/main.go
  6. +430 −1 metrics.go
  7. +4 −1 registry.go
View
@@ -14,7 +14,7 @@ deps:
gometalinter --install
lint:
- gometalinter ./... --vendor --deadline=10000s --dupl-threshold=150 --disable=gas
+ gometalinter ./... --vendor --deadline=10000s --dupl-threshold=150 --disable=interfacer --disable=gas
test:
go test ./...
View
@@ -477,6 +477,31 @@ func (c *PCPClient) writeMetrics() {
c.writeInstanceMetric(metric)
wg.Done()
}(metric)
+ case *PCPCounter:
+ go func(metric *PCPCounter) {
+ c.writeSingletonMetric(metric.PCPSingletonMetric)
+ wg.Done()
+ }(metric)
+ case *PCPGauge:
+ go func(metric *PCPGauge) {
+ c.writeSingletonMetric(metric.PCPSingletonMetric)
+ wg.Done()
+ }(metric)
+ case *PCPTimer:
+ go func(metric *PCPTimer) {
+ c.writeSingletonMetric(metric.PCPSingletonMetric)
+ wg.Done()
+ }(metric)
+ case *PCPCounterVector:
+ go func(metric *PCPCounterVector) {
+ c.writeInstanceMetric(metric.PCPInstanceMetric)
+ wg.Done()
+ }(metric)
+ case *PCPGaugeVector:
+ go func(metric *PCPGaugeVector) {
+ c.writeInstanceMetric(metric.PCPInstanceMetric)
+ wg.Done()
+ }(metric)
}
}
View
@@ -2,8 +2,10 @@ package speed
import (
"fmt"
+ "math"
"os"
"testing"
+ "time"
"github.com/performancecopilot/speed/mmvdump"
)
@@ -843,3 +845,268 @@ func TestMMV2InstanceWriting(t *testing.T) {
t.Errorf("expected two strings in the dump")
}
}
+
+func toFixed(v float64, p int) float64 {
+ return float64(uint64(v*math.Pow(10, float64(p)))) / math.Pow(10, float64(p))
+}
+
+func matchSingleDump(expected interface{}, m PCPMetric, c *PCPClient, t *testing.T) {
+ _, _, metrics, values, _, _, strings, err := mmvdump.Dump(c.writer.Bytes())
+ if err != nil {
+ t.Errorf("cannot get dump: %v", err)
+ return
+ }
+
+ matchMetricsAndValues(metrics, values, strings, c, t)
+
+ off, _ := findMetric(m, metrics)
+ _, v := findValue(off, values)
+
+ if val, err := mmvdump.FixedVal(v.Val, mmvdump.Type(m.Type())); val != expected {
+ t.Errorf("expected metric to be %v, got %v", expected, val)
+ } else if err != nil {
+ t.Errorf("cannot convert stored metric val to float64")
+ }
+}
+
+func matchSingle(expected, val interface{}, m PCPMetric, c *PCPClient, t *testing.T) {
+ if val != expected {
+ t.Errorf("expected Val() to return %v", expected)
+ }
+
+ matchSingleDump(expected, m, c, t)
+}
+
+func TestCounter(t *testing.T) {
+ c, err := NewPCPClient("test")
+ if err != nil {
+ t.Errorf("cannot create client, error: %v", err)
+ return
+ }
+
+ m, err := NewPCPCounter(0, "c.1")
+ if err != nil {
+ t.Errorf("cannot create counter, error: %v", err)
+ return
+ }
+
+ c.MustRegister(m)
+
+ c.MustStart()
+ defer c.MustStop()
+
+ // Up
+
+ m.Up()
+ matchSingle(int64(1), m.Val(), m, c, t)
+
+ // Inc
+
+ m.MustInc(9)
+ matchSingle(int64(10), m.Val(), m, c, t)
+
+ // Inc decrement
+
+ err = m.Inc(-9)
+ if err == nil {
+ t.Errorf("expected decrementing a counter to generate an error")
+ }
+ matchSingle(int64(10), m.Val(), m, c, t)
+
+ // Set less
+
+ err = m.Set(9)
+ if err == nil {
+ t.Errorf("expected setting a counter to a lesser value to generate an error")
+ }
+ matchSingle(int64(10), m.Val(), m, c, t)
+
+ // Set more
+
+ err = m.Set(99)
+ if err != nil {
+ t.Errorf("expected setting a counter to a larger value to not generate an error")
+ }
+ matchSingle(int64(99), m.Val(), m, c, t)
+}
+
+func TestGauge(t *testing.T) {
+ c, err := NewPCPClient("test")
+ if err != nil {
+ t.Errorf("cannot create client, error: %v", err)
+ return
+ }
+
+ m, err := NewPCPGauge(0, "g.1")
+ if err != nil {
+ t.Errorf("cannot create gauge, error: %v", err)
+ return
+ }
+
+ c.MustRegister(m)
+
+ c.MustStart()
+ defer c.MustStop()
+
+ // Inc
+
+ m.MustInc(10)
+ matchSingle(float64(10), m.Val(), m, c, t)
+
+ // Dec
+
+ err = m.Dec(9)
+ if err != nil {
+ t.Errorf("cannot decrement the gauge")
+ }
+ matchSingle(float64(1), m.Val(), m, c, t)
+
+ // Set
+
+ err = m.Set(9)
+ if err != nil {
+ t.Errorf("cannot set the gauge's value")
+ }
+ matchSingle(float64(9), m.Val(), m, c, t)
+}
+
+func TestTimer(t *testing.T) {
+ timer, err := NewPCPTimer("t.1", NanosecondUnit)
+ if err != nil {
+ t.Errorf("cannot create timer, error: %v", err)
+ return
+ }
+
+ c, err := NewPCPClient("test")
+ if err != nil {
+ t.Errorf("cannot create client, error: %v", err)
+ return
+ }
+
+ c.MustRegister(timer)
+
+ c.MustStart()
+ defer c.MustStop()
+
+ err = timer.Start()
+ if err != nil {
+ t.Errorf("cannot start timer, error: %v", err)
+ }
+
+ time.Sleep(time.Second)
+
+ v, err := timer.Stop()
+ if err != nil {
+ t.Errorf("cannot stop timer, error: %v", err)
+ }
+
+ matchSingleDump(v, timer, c, t)
+}
+
+func TestCounterVector(t *testing.T) {
+ cv, err := NewPCPCounterVector(map[string]int64{
+ "m1": 1,
+ "m2": 2,
+ }, "m.1")
+
+ if err != nil {
+ t.Errorf("cannot create CounterVector, error: %v", err)
+ return
+ }
+
+ c, err := NewPCPClient("c")
+ if err != nil {
+ t.Errorf("cannot create client, error: %v", err)
+ }
+
+ c.MustRegister(cv)
+
+ c.MustStart()
+ defer c.MustStop()
+
+ var val int64
+
+ // Set
+
+ cv.MustSet(10, "m1")
+
+ if val, err = cv.Val("m1"); val != 10 {
+ t.Errorf("expected m.1[m1] to be 10, got %v", val)
+ } else if err != nil {
+ t.Errorf("cannot retrieve m.1[m1] value, error: %v", err)
+ }
+
+ // Inc
+
+ cv.MustInc(10, "m2")
+
+ if val, err = cv.Val("m2"); val != 12 {
+ t.Errorf("expected m.1[m2] to be 12, got %v", val)
+ } else if err != nil {
+ t.Errorf("cannot retrieve m.1[m2] value, error: %v", err)
+ }
+
+ // Up
+
+ cv.Up("m1")
+
+ if val, err = cv.Val("m1"); val != 11 {
+ t.Errorf("expected m.1[m1] to be 11, got %v", val)
+ } else if err != nil {
+ t.Errorf("cannot retrieve m.1[m1] value, error: %v", err)
+ }
+}
+
+func TestGaugeVector(t *testing.T) {
+ g, err := NewPCPGaugeVector(map[string]float64{
+ "m1": 1.2,
+ "m2": 2.4,
+ }, "m.1")
+
+ if err != nil {
+ t.Errorf("cannot create GaugeVector, error: %v", err)
+ return
+ }
+
+ c, err := NewPCPClient("c")
+ if err != nil {
+ t.Errorf("cannot create client, error: %v", err)
+ }
+
+ c.MustRegister(g)
+
+ c.MustStart()
+ defer c.MustStop()
+
+ var val float64
+
+ // Set
+
+ g.MustSet(10, "m1")
+
+ if val, err = g.Val("m1"); val != 10 {
+ t.Errorf("expected m.1[m1] to be 10, got %v", val)
+ } else if err != nil {
+ t.Errorf("cannot retrieve m.1[m1] value, error: %v", err)
+ }
+
+ // Inc
+
+ g.MustInc(10, "m2")
+
+ if val, err = g.Val("m2"); val != 12.4 {
+ t.Errorf("expected m.1[m2] to be 12.4, got %v", val)
+ } else if err != nil {
+ t.Errorf("cannot retrieve m.1[m2] value, error: %v", err)
+ }
+
+ // Dec
+
+ g.MustDec(10, "m2")
+
+ if val, err = g.Val("m2"); toFixed(val, 5) != 2.4 {
+ t.Errorf("expected m.1[m2] to be 2.4, got %v", val)
+ } else if err != nil {
+ t.Errorf("cannot retrieve m.1[m2] value, error: %v", err)
+ }
+}
@@ -8,18 +8,13 @@ import (
"github.com/performancecopilot/speed"
)
-// TODO: replace the raw metric with a Counter once defined
-
-var metric speed.SingletonMetric
+var metric speed.Counter
func main() {
var err error
- metric, err = speed.NewPCPSingletonMetric(
+ metric, err = speed.NewPCPCounter(
0,
"http.requests",
- speed.Int32Type,
- speed.CounterSemantics,
- speed.OneUnit,
"Number of Requests",
)
if err != nil {
@@ -49,8 +44,6 @@ func main() {
}
func handleIncrement(w http.ResponseWriter, r *http.Request) {
- v := metric.Val().(int32)
- v++
- metric.MustSet(v)
+ metric.Up()
fmt.Fprintf(w, "incremented\n")
}
@@ -1,7 +1,5 @@
package main
-// TODO: update this example with PCPCounterMetric once that is implemented
-
import (
"flag"
"fmt"
@@ -15,12 +13,9 @@ var timelimit = flag.Int("time", 60, "number of seconds to run for")
func main() {
flag.Parse()
- metric, err := speed.NewPCPSingletonMetric(
+ metric, err := speed.NewPCPCounter(
0,
"counter",
- speed.Int32Type,
- speed.CounterSemantics,
- speed.OneUnit,
"A Simple Metric",
)
if err != nil {
@@ -42,9 +37,7 @@ func main() {
fmt.Println("The metric should be visible as mmv.singletoncounter.counter")
for i := 0; i < *timelimit; i++ {
- v := metric.Val().(int32)
- v++
- metric.MustSet(v)
+ metric.Up()
time.Sleep(time.Second)
}
}
Oops, something went wrong.

0 comments on commit 0907c1e

Please sign in to comment.