2013-04-03 20:33:32 +04:00
|
|
|
// Copyright (c) 2013, Prometheus Team
|
2013-02-12 05:36:06 +04:00
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
2012-12-19 14:48:12 +04:00
|
|
|
|
2013-04-03 20:33:32 +04:00
|
|
|
package prometheus
|
2012-12-19 14:48:12 +04:00
|
|
|
|
|
|
|
import (
|
2013-04-19 16:11:01 +04:00
|
|
|
"encoding/json"
|
2012-12-19 14:48:12 +04:00
|
|
|
"fmt"
|
|
|
|
"sync"
|
2013-06-27 20:46:16 +04:00
|
|
|
|
|
|
|
dto "github.com/prometheus/client_model/go"
|
|
|
|
|
|
|
|
"code.google.com/p/goprotobuf/proto"
|
2012-12-19 14:48:12 +04:00
|
|
|
)
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
// TODO(matt): Refactor to de-duplicate behaviors.
|
|
|
|
|
|
|
|
type Counter interface {
|
2013-04-19 15:22:59 +04:00
|
|
|
Metric
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
Decrement(labels map[string]string) float64
|
|
|
|
DecrementBy(labels map[string]string, value float64) float64
|
|
|
|
Increment(labels map[string]string) float64
|
|
|
|
IncrementBy(labels map[string]string, value float64) float64
|
|
|
|
Set(labels map[string]string, value float64) float64
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-02-12 05:36:06 +04:00
|
|
|
type counterVector struct {
|
2013-04-19 16:11:01 +04:00
|
|
|
Labels map[string]string `json:"labels"`
|
|
|
|
Value float64 `json:"value"`
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewCounter() Counter {
|
|
|
|
return &counter{
|
2013-06-27 20:46:16 +04:00
|
|
|
values: map[uint64]*counterVector{},
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type counter struct {
|
|
|
|
mutex sync.RWMutex
|
2013-06-27 20:46:16 +04:00
|
|
|
values map[uint64]*counterVector
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (metric *counter) Set(labels map[string]string, value float64) float64 {
|
2012-12-19 14:48:12 +04:00
|
|
|
metric.mutex.Lock()
|
|
|
|
defer metric.mutex.Unlock()
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
if labels == nil {
|
|
|
|
labels = map[string]string{}
|
|
|
|
}
|
|
|
|
|
2013-04-03 20:33:32 +04:00
|
|
|
signature := labelsToSignature(labels)
|
2013-01-19 17:48:30 +04:00
|
|
|
if original, ok := metric.values[signature]; ok {
|
2013-04-19 16:11:01 +04:00
|
|
|
original.Value = value
|
2013-01-19 17:48:30 +04:00
|
|
|
} else {
|
2013-02-12 05:36:06 +04:00
|
|
|
metric.values[signature] = &counterVector{
|
2013-04-19 16:11:01 +04:00
|
|
|
Labels: labels,
|
|
|
|
Value: value,
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2014-02-19 17:53:34 +04:00
|
|
|
func (metric *counter) Reset(labels map[string]string) {
|
|
|
|
metric.mutex.Lock()
|
|
|
|
defer metric.mutex.Unlock()
|
|
|
|
|
|
|
|
signature := labelsToSignature(labels)
|
|
|
|
delete(metric.values, signature)
|
|
|
|
}
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
func (metric *counter) ResetAll() {
|
|
|
|
metric.mutex.Lock()
|
|
|
|
defer metric.mutex.Unlock()
|
|
|
|
|
|
|
|
for key, value := range metric.values {
|
2013-04-19 16:11:01 +04:00
|
|
|
for label := range value.Labels {
|
|
|
|
delete(value.Labels, label)
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
delete(metric.values, key)
|
|
|
|
}
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-05-03 18:02:03 +04:00
|
|
|
func (metric *counter) String() string {
|
2013-01-19 17:48:30 +04:00
|
|
|
formatString := "[Counter %s]"
|
2012-12-19 14:48:12 +04:00
|
|
|
|
|
|
|
metric.mutex.RLock()
|
|
|
|
defer metric.mutex.RUnlock()
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
return fmt.Sprintf(formatString, metric.values)
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
func (metric *counter) IncrementBy(labels map[string]string, value float64) float64 {
|
2012-12-19 14:48:12 +04:00
|
|
|
metric.mutex.Lock()
|
|
|
|
defer metric.mutex.Unlock()
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
if labels == nil {
|
|
|
|
labels = map[string]string{}
|
|
|
|
}
|
|
|
|
|
2013-04-03 20:33:32 +04:00
|
|
|
signature := labelsToSignature(labels)
|
2013-01-19 17:48:30 +04:00
|
|
|
if original, ok := metric.values[signature]; ok {
|
2013-04-19 16:11:01 +04:00
|
|
|
original.Value += value
|
2013-01-19 17:48:30 +04:00
|
|
|
} else {
|
2013-02-12 05:36:06 +04:00
|
|
|
metric.values[signature] = &counterVector{
|
2013-04-19 16:11:01 +04:00
|
|
|
Labels: labels,
|
|
|
|
Value: value,
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
func (metric *counter) Increment(labels map[string]string) float64 {
|
|
|
|
return metric.IncrementBy(labels, 1)
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
func (metric *counter) DecrementBy(labels map[string]string, value float64) float64 {
|
2012-12-19 14:48:12 +04:00
|
|
|
metric.mutex.Lock()
|
|
|
|
defer metric.mutex.Unlock()
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
if labels == nil {
|
|
|
|
labels = map[string]string{}
|
|
|
|
}
|
|
|
|
|
2013-04-03 20:33:32 +04:00
|
|
|
signature := labelsToSignature(labels)
|
2013-01-19 17:48:30 +04:00
|
|
|
if original, ok := metric.values[signature]; ok {
|
2013-04-19 16:11:01 +04:00
|
|
|
original.Value -= value
|
2013-01-19 17:48:30 +04:00
|
|
|
} else {
|
2013-02-12 05:36:06 +04:00
|
|
|
metric.values[signature] = &counterVector{
|
2013-04-19 16:11:01 +04:00
|
|
|
Labels: labels,
|
|
|
|
Value: -1 * value,
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
func (metric *counter) Decrement(labels map[string]string) float64 {
|
|
|
|
return metric.DecrementBy(labels, 1)
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2013-05-03 18:02:03 +04:00
|
|
|
func (metric *counter) MarshalJSON() ([]byte, error) {
|
2012-12-19 14:48:12 +04:00
|
|
|
metric.mutex.RLock()
|
|
|
|
defer metric.mutex.RUnlock()
|
|
|
|
|
2013-04-19 16:11:01 +04:00
|
|
|
values := make([]*counterVector, 0, len(metric.values))
|
|
|
|
|
2013-01-19 17:48:30 +04:00
|
|
|
for _, value := range metric.values {
|
2013-04-19 16:11:01 +04:00
|
|
|
values = append(values, value)
|
2013-01-19 17:48:30 +04:00
|
|
|
}
|
|
|
|
|
2013-04-19 16:11:01 +04:00
|
|
|
return json.Marshal(map[string]interface{}{
|
2013-01-19 17:48:30 +04:00
|
|
|
valueKey: values,
|
|
|
|
typeKey: counterTypeValue,
|
2013-04-19 16:11:01 +04:00
|
|
|
})
|
2012-12-19 14:48:12 +04:00
|
|
|
}
|
2013-06-27 20:46:16 +04:00
|
|
|
|
|
|
|
func (metric *counter) dumpChildren(f *dto.MetricFamily) {
|
|
|
|
metric.mutex.RLock()
|
|
|
|
defer metric.mutex.RUnlock()
|
|
|
|
|
|
|
|
f.Type = dto.MetricType_COUNTER.Enum()
|
|
|
|
|
|
|
|
for _, child := range metric.values {
|
|
|
|
c := &dto.Counter{
|
|
|
|
Value: proto.Float64(child.Value),
|
|
|
|
}
|
|
|
|
|
|
|
|
m := &dto.Metric{
|
|
|
|
Counter: c,
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, value := range child.Labels {
|
|
|
|
p := &dto.LabelPair{
|
|
|
|
Name: proto.String(name),
|
|
|
|
Value: proto.String(value),
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Label = append(m.Label, p)
|
|
|
|
}
|
|
|
|
|
|
|
|
f.Metric = append(f.Metric, m)
|
|
|
|
}
|
|
|
|
}
|