|
|
@@ -281,50 +281,6 @@ type PCPMetric interface { |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
-// Counter defines a metric that holds a single value that can only be incremented
|
|
|
-type Counter interface {
|
|
|
- Metric
|
|
|
-
|
|
|
- Val() int64
|
|
|
- Set(int64) error
|
|
|
-
|
|
|
- Inc(int64) error
|
|
|
- MustInc(int64)
|
|
|
-
|
|
|
- Up() // same as MustInc(1)
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-// Gauge defines a metric that holds a single double value that can be incremented or decremented
|
|
|
-type Gauge interface {
|
|
|
- Metric
|
|
|
-
|
|
|
- Val() float64
|
|
|
-
|
|
|
- Set(float64) error
|
|
|
- MustSet(float64)
|
|
|
-
|
|
|
- Inc(float64) error
|
|
|
- Dec(float64) error
|
|
|
-
|
|
|
- MustInc(float64)
|
|
|
- MustDec(float64)
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-// Timer defines a metric that accumulates time periods
|
|
|
-// Start signals the beginning of monitoring
|
|
|
-// End signals the end of monitoring and adding the elapsed time to the accumulated time
|
|
|
-// and returning it
|
|
|
-type Timer interface {
|
|
|
- Start() error
|
|
|
- Stop() (float64, error)
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
// PCPMetricItemBitLength is the maximum bit size of a PCP Metric id
|
|
|
//
|
|
|
// see: https://github.com/performancecopilot/pcp/blob/master/src/include/pcp/impl.h#L102-L121
|
|
|
@@ -497,115 +453,19 @@ func (m *PCPSingletonMetric) String() string { |
|
|
return fmt.Sprintf("Val: %v\n%v", m.val, m.Description())
|
|
|
}
|
|
|
|
|
|
-// TODO: implement PCPCounterMetric, PCPGaugeMetric ...
|
|
|
-
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
-type instanceValue struct {
|
|
|
- val interface{}
|
|
|
- update updateClosure
|
|
|
-}
|
|
|
-
|
|
|
-func newinstanceValue(val interface{}) *instanceValue {
|
|
|
- return &instanceValue{val, nil}
|
|
|
-}
|
|
|
-
|
|
|
-// PCPInstanceMetric represents a PCPMetric that can have multiple values
|
|
|
-// over multiple instances in an instance domain
|
|
|
-type PCPInstanceMetric struct {
|
|
|
- sync.RWMutex
|
|
|
- *PCPMetricDesc
|
|
|
- indom *PCPInstanceDomain
|
|
|
- vals map[string]*instanceValue
|
|
|
-}
|
|
|
-
|
|
|
-// NewPCPInstanceMetric creates a new instance of PCPSingletonMetric
|
|
|
-// it takes 2 extra optional strings as short and long description parameters,
|
|
|
-// which on not being present are set blank
|
|
|
-func NewPCPInstanceMetric(vals Instances, name string, indom *PCPInstanceDomain, t MetricType, s MetricSemantics, u MetricUnit, desc ...string) (*PCPInstanceMetric, error) {
|
|
|
- if len(vals) != indom.InstanceCount() {
|
|
|
- return nil, errors.New("values for all instances in the instance domain only should be passed")
|
|
|
- }
|
|
|
-
|
|
|
- d, err := newPCPMetricDesc(name, t, s, u, desc...)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- mvals := make(map[string]*instanceValue)
|
|
|
-
|
|
|
- for name := range indom.instances {
|
|
|
- val, present := vals[name]
|
|
|
- if !present {
|
|
|
- return nil, fmt.Errorf("Instance %v not initialized", name)
|
|
|
- }
|
|
|
-
|
|
|
- if !t.IsCompatible(val) {
|
|
|
- return nil, fmt.Errorf("value %v is incompatible with type %v for Instance %v", val, t, name)
|
|
|
- }
|
|
|
-
|
|
|
- val = t.resolve(val)
|
|
|
- mvals[name] = newinstanceValue(val)
|
|
|
- }
|
|
|
-
|
|
|
- return &PCPInstanceMetric{
|
|
|
- sync.RWMutex{},
|
|
|
- d,
|
|
|
- indom,
|
|
|
- mvals,
|
|
|
- }, nil
|
|
|
-}
|
|
|
-
|
|
|
-// Indom returns the instance domain for the metric
|
|
|
-func (m *PCPInstanceMetric) Indom() *PCPInstanceDomain { return m.indom }
|
|
|
-
|
|
|
-// ValInstance returns the value for a particular instance of the metric
|
|
|
-func (m *PCPInstanceMetric) ValInstance(instance string) (interface{}, error) {
|
|
|
- if !m.indom.HasInstance(instance) {
|
|
|
- return nil, fmt.Errorf("%v is not an instance of this metric", instance)
|
|
|
- }
|
|
|
-
|
|
|
- m.RLock()
|
|
|
- defer m.RUnlock()
|
|
|
-
|
|
|
- ans := m.vals[instance].val
|
|
|
- return ans, nil
|
|
|
-}
|
|
|
-
|
|
|
-// SetInstance sets the value for a particular instance of the metric
|
|
|
-func (m *PCPInstanceMetric) SetInstance(instance string, val interface{}) error {
|
|
|
- if !m.t.IsCompatible(val) {
|
|
|
- return errors.New("the value is incompatible with this metrics MetricType")
|
|
|
- }
|
|
|
-
|
|
|
- if !m.indom.HasInstance(instance) {
|
|
|
- return fmt.Errorf("%v is not an instance of this metric", instance)
|
|
|
- }
|
|
|
-
|
|
|
- val = m.t.resolveFloat(m.t.resolveInt(val))
|
|
|
-
|
|
|
- if m.vals[instance].val != val {
|
|
|
- m.Lock()
|
|
|
- defer m.Unlock()
|
|
|
-
|
|
|
- if m.vals[instance].update != nil {
|
|
|
- err := m.vals[instance].update(val)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
+// Counter defines a metric that holds a single value that can only be incremented
|
|
|
+type Counter interface {
|
|
|
+ Metric
|
|
|
|
|
|
- m.vals[instance].val = val
|
|
|
- }
|
|
|
+ Val() int64
|
|
|
+ Set(int64) error
|
|
|
|
|
|
- return nil
|
|
|
-}
|
|
|
+ Inc(int64) error
|
|
|
+ MustInc(int64)
|
|
|
|
|
|
-// MustSetInstance is a SetInstance that panics
|
|
|
-func (m *PCPInstanceMetric) MustSetInstance(instance string, val interface{}) {
|
|
|
- if err := m.SetInstance(instance, val); err != nil {
|
|
|
- panic(err)
|
|
|
- }
|
|
|
+ Up() // same as MustInc(1)
|
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
@@ -668,6 +528,24 @@ func (c *PCPCounter) Up() { c.MustInc(1) } |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
+// Gauge defines a metric that holds a single double value that can be incremented or decremented
|
|
|
+type Gauge interface {
|
|
|
+ Metric
|
|
|
+
|
|
|
+ Val() float64
|
|
|
+
|
|
|
+ Set(float64) error
|
|
|
+ MustSet(float64)
|
|
|
+
|
|
|
+ Inc(float64) error
|
|
|
+ Dec(float64) error
|
|
|
+
|
|
|
+ MustInc(float64)
|
|
|
+ MustDec(float64)
|
|
|
+}
|
|
|
+
|
|
|
+///////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
// PCPGauge defines a PCP compatible Gauge metric
|
|
|
type PCPGauge struct {
|
|
|
*PCPSingletonMetric
|
|
|
@@ -723,6 +601,17 @@ func (g *PCPGauge) MustDec(val float64) { |
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
+// Timer defines a metric that accumulates time periods
|
|
|
+// Start signals the beginning of monitoring
|
|
|
+// End signals the end of monitoring and adding the elapsed time to the accumulated time
|
|
|
+// and returning it
|
|
|
+type Timer interface {
|
|
|
+ Start() error
|
|
|
+ Stop() (float64, error)
|
|
|
+}
|
|
|
+
|
|
|
+///////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
// PCPTimer implements a PCP compatible Timer
|
|
|
// It also functionally implements a metric with elapsed type from PCP
|
|
|
type PCPTimer struct {
|
|
|
@@ -771,9 +660,9 @@ func (t *PCPTimer) Stop() (float64, error) { |
|
|
case NanosecondUnit:
|
|
|
inc = float64(d.Nanoseconds())
|
|
|
case MicrosecondUnit:
|
|
|
- inc = float64(d.Nanoseconds()) * 1e3
|
|
|
+ inc = float64(d.Nanoseconds()) * 1e-3
|
|
|
case MillisecondUnit:
|
|
|
- inc = float64(d.Nanoseconds()) * 1e6
|
|
|
+ inc = float64(d.Nanoseconds()) * 1e-6
|
|
|
case SecondUnit:
|
|
|
inc = d.Seconds()
|
|
|
case MinuteUnit:
|
|
|
@@ -792,3 +681,112 @@ func (t *PCPTimer) Stop() (float64, error) { |
|
|
}
|
|
|
return v + inc, nil
|
|
|
}
|
|
|
+
|
|
|
+///////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+type instanceValue struct {
|
|
|
+ val interface{}
|
|
|
+ update updateClosure
|
|
|
+}
|
|
|
+
|
|
|
+func newinstanceValue(val interface{}) *instanceValue {
|
|
|
+ return &instanceValue{val, nil}
|
|
|
+}
|
|
|
+
|
|
|
+// PCPInstanceMetric represents a PCPMetric that can have multiple values
|
|
|
+// over multiple instances in an instance domain
|
|
|
+type PCPInstanceMetric struct {
|
|
|
+ sync.RWMutex
|
|
|
+ *PCPMetricDesc
|
|
|
+ indom *PCPInstanceDomain
|
|
|
+ vals map[string]*instanceValue
|
|
|
+}
|
|
|
+
|
|
|
+// NewPCPInstanceMetric creates a new instance of PCPSingletonMetric
|
|
|
+// it takes 2 extra optional strings as short and long description parameters,
|
|
|
+// which on not being present are set blank
|
|
|
+func NewPCPInstanceMetric(vals Instances, name string, indom *PCPInstanceDomain, t MetricType, s MetricSemantics, u MetricUnit, desc ...string) (*PCPInstanceMetric, error) {
|
|
|
+ if len(vals) != indom.InstanceCount() {
|
|
|
+ return nil, errors.New("values for all instances in the instance domain only should be passed")
|
|
|
+ }
|
|
|
+
|
|
|
+ d, err := newPCPMetricDesc(name, t, s, u, desc...)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ mvals := make(map[string]*instanceValue)
|
|
|
+
|
|
|
+ for name := range indom.instances {
|
|
|
+ val, present := vals[name]
|
|
|
+ if !present {
|
|
|
+ return nil, fmt.Errorf("Instance %v not initialized", name)
|
|
|
+ }
|
|
|
+
|
|
|
+ if !t.IsCompatible(val) {
|
|
|
+ return nil, fmt.Errorf("value %v is incompatible with type %v for Instance %v", val, t, name)
|
|
|
+ }
|
|
|
+
|
|
|
+ val = t.resolve(val)
|
|
|
+ mvals[name] = newinstanceValue(val)
|
|
|
+ }
|
|
|
+
|
|
|
+ return &PCPInstanceMetric{
|
|
|
+ sync.RWMutex{},
|
|
|
+ d,
|
|
|
+ indom,
|
|
|
+ mvals,
|
|
|
+ }, nil
|
|
|
+}
|
|
|
+
|
|
|
+// Indom returns the instance domain for the metric
|
|
|
+func (m *PCPInstanceMetric) Indom() *PCPInstanceDomain { return m.indom }
|
|
|
+
|
|
|
+// ValInstance returns the value for a particular instance of the metric
|
|
|
+func (m *PCPInstanceMetric) ValInstance(instance string) (interface{}, error) {
|
|
|
+ if !m.indom.HasInstance(instance) {
|
|
|
+ return nil, fmt.Errorf("%v is not an instance of this metric", instance)
|
|
|
+ }
|
|
|
+
|
|
|
+ m.RLock()
|
|
|
+ defer m.RUnlock()
|
|
|
+
|
|
|
+ ans := m.vals[instance].val
|
|
|
+ return ans, nil
|
|
|
+}
|
|
|
+
|
|
|
+// SetInstance sets the value for a particular instance of the metric
|
|
|
+func (m *PCPInstanceMetric) SetInstance(instance string, val interface{}) error {
|
|
|
+ if !m.t.IsCompatible(val) {
|
|
|
+ return errors.New("the value is incompatible with this metrics MetricType")
|
|
|
+ }
|
|
|
+
|
|
|
+ if !m.indom.HasInstance(instance) {
|
|
|
+ return fmt.Errorf("%v is not an instance of this metric", instance)
|
|
|
+ }
|
|
|
+
|
|
|
+ val = m.t.resolveFloat(m.t.resolveInt(val))
|
|
|
+
|
|
|
+ if m.vals[instance].val != val {
|
|
|
+ m.Lock()
|
|
|
+ defer m.Unlock()
|
|
|
+
|
|
|
+ if m.vals[instance].update != nil {
|
|
|
+ err := m.vals[instance].update(val)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ m.vals[instance].val = val
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// MustSetInstance is a SetInstance that panics
|
|
|
+func (m *PCPInstanceMetric) MustSetInstance(instance string, val interface{}) {
|
|
|
+ if err := m.SetInstance(instance, val); err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+}
|