Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

add custom metric types #23

Merged
merged 23 commits into from Aug 11, 2016
Commits
Jump to file or symbol
Failed to load files and symbols.
+158 −1
Split
Viewing a subset of changes. View all
View
@@ -492,6 +492,11 @@ func (c *PCPClient) writeMetrics() {
c.writeSingletonMetric(metric.PCPSingletonMetric)
wg.Done()
}(metric)
+ case *PCPCounterVector:
+ go func(metric *PCPCounterVector) {
+ c.writeInstanceMetric(metric.PCPInstanceMetric)
+ wg.Done()
+ }(metric)
}
}
View
@@ -997,3 +997,51 @@ func TestTimer(t *testing.T) {
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()
+
+ // Set
+
+ err = cv.Set(10, "m1")
+ if err != nil {
+ t.Errorf("cannot set an instance, error: %v", err)
+ }
+
+ 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")
+ }
+
+ // Inc
+
+ err = cv.Inc(10, "m2")
+ if err != nil {
+ t.Errorf("cannot inc an instance, error: %v", err)
+ }
+
+ 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")
+ }
+}
View
@@ -606,6 +606,8 @@ func (g *PCPGauge) MustDec(val float64) {
// End signals the end of monitoring and adding the elapsed time to the accumulated time
// and returning it
type Timer interface {
+ Metric
+
Start() error
Stop() (float64, error)
}
@@ -790,3 +792,102 @@ func (m *PCPInstanceMetric) MustSetInstance(instance string, val interface{}) {
panic(err)
}
}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// CounterVector defines a Counter on multiple instances
+type CounterVector interface {
+ Metric
+
+ Val(string) int64
+
+ Set(int64, string) error
+
+ Inc(int64, string) error
+
+ Up(string)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PCPCounterVector implements a PCP counter vector
+type PCPCounterVector struct {
+ *PCPInstanceMetric
+}
+
+// NewPCPCounterVector creates a new instance of a PCPCounterVector
+func NewPCPCounterVector(values map[string]int64, name string, desc ...string) (*PCPCounterVector, error) {
+ instances, i := make([]string, len(values)), 0
+ vals := make(map[string]interface{})
+ for k, v := range values {
+ instances[i] = k
+ i++
+ vals[k] = v
+ }
+
+ indomname := name + ".indom"
+ indom, err := NewPCPInstanceDomain(indomname, instances)
+ if err != nil {
+ return nil, fmt.Errorf("cannot create indom, error: %v", err)
+ }
+
+ im, err := NewPCPInstanceMetric(vals, name, indom, Int64Type, CounterSemantics, OneUnit, desc...)
+ if err != nil {
+ return nil, err
+ }
+
+ return &PCPCounterVector{im}, nil
+}
+
+// Val returns the value of a particular instance of PCPCounterVector
+func (c *PCPCounterVector) Val(instance string) (int64, error) {
+ val, err := c.PCPInstanceMetric.ValInstance(instance)
+ if err != nil {
+ return 0, err
+ }
+ return val.(int64), nil
+}
+
+// Set sets the value of a particular instance of PCPCounterVector
+func (c *PCPCounterVector) Set(val int64, instance string) error {
+ v, err := c.Val(instance)
+ if err != nil {
+ return err
+ }
+
+ if val < v {
+ return fmt.Errorf("cannot set instance %s to a lesser value %v", instance, val)
+ }
+
+ return c.PCPInstanceMetric.SetInstance(instance, val)
+}
+
+// Inc increments the value of a particular instance of PCPCounterVector
+func (c *PCPCounterVector) Inc(inc int64, instance string) error {
+ if inc < 0 {
+ return errors.New("increment cannot be negative")
+ }
+
+ if inc == 0 {
+ return nil
+ }
+
+ v, err := c.Val(instance)
+ if err != nil {
+ return err
+ }
+
+ return c.Set(v+inc, instance)
+}
+
+// Up increments the value of a particular instance ny 1
+func (c *PCPCounterVector) Up(instance string) error {
+ v, err := c.Val(instance)
+ if err != nil {
+ return err
+ }
+
+ return c.Set(v+1, instance)
+}
+
+///////////////////////////////////////////////////////////////////////////////
View
@@ -213,7 +213,10 @@ func (r *PCPRegistry) AddMetric(m Metric) error {
// if it is an indom metric
if pcpm.Indom() != nil && !r.HasInstanceDomain(pcpm.Indom().Name()) {
- return errors.New("the metric's instance domain is not defined for current registry")
+ err := r.AddInstanceDomain(pcpm.Indom())
+ if err != nil {
+ return err
+ }
}
r.metricslock.Lock()