mirror of https://github.com/grafana/grafana
feat(instrumentation): lots of refactoring to support tag based backend, #4696
parent
2a9b51d836
commit
e2c794ff31
@ -0,0 +1,53 @@ |
|||||||
|
package metrics |
||||||
|
|
||||||
|
import "github.com/grafana/grafana/pkg/log" |
||||||
|
|
||||||
|
type MetricMeta struct { |
||||||
|
tags map[string]string |
||||||
|
name string |
||||||
|
} |
||||||
|
|
||||||
|
func NewMetricMeta(name string, tagStrings []string) *MetricMeta { |
||||||
|
if len(tagStrings)%2 != 0 { |
||||||
|
log.Fatal(3, "Metrics: tags array is missing value for key, %v", tagStrings) |
||||||
|
} |
||||||
|
|
||||||
|
tags := make(map[string]string) |
||||||
|
for i := 0; i < len(tagStrings); i += 2 { |
||||||
|
tags[tagStrings[i]] = tagStrings[i+1] |
||||||
|
} |
||||||
|
|
||||||
|
return &MetricMeta{ |
||||||
|
tags: tags, |
||||||
|
name: name, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (m *MetricMeta) Name() string { |
||||||
|
return m.name |
||||||
|
} |
||||||
|
|
||||||
|
func (m *MetricMeta) Tags() map[string]string { |
||||||
|
return m.tags |
||||||
|
} |
||||||
|
|
||||||
|
func (m *MetricMeta) StringifyTags() string { |
||||||
|
if len(m.tags) == 0 { |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
str := "" |
||||||
|
for key, value := range m.tags { |
||||||
|
str += "." + key + "_" + value |
||||||
|
} |
||||||
|
|
||||||
|
return str |
||||||
|
} |
||||||
|
|
||||||
|
type Metric interface { |
||||||
|
Name() string |
||||||
|
Tags() map[string]string |
||||||
|
StringifyTags() string |
||||||
|
Snapshot() Metric |
||||||
|
Clear() |
||||||
|
} |
@ -1,102 +1,38 @@ |
|||||||
package metrics |
package metrics |
||||||
|
|
||||||
import ( |
import "sync" |
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
"sync" |
|
||||||
) |
|
||||||
|
|
||||||
// DuplicateMetric is the error returned by Registry.Register when a metric
|
|
||||||
// already exists. If you mean to Register that metric you must first
|
|
||||||
// Unregister the existing metric.
|
|
||||||
type DuplicateMetric string |
|
||||||
|
|
||||||
func (err DuplicateMetric) Error() string { |
|
||||||
return fmt.Sprintf("duplicate metric: %s", string(err)) |
|
||||||
} |
|
||||||
|
|
||||||
type Registry interface { |
type Registry interface { |
||||||
// Call the given function for each registered metric.
|
GetSnapshots() []Metric |
||||||
Each(func(string, interface{})) |
Register(metric Metric) |
||||||
|
|
||||||
// Get the metric by the given name or nil if none is registered.
|
|
||||||
Get(string) interface{} |
|
||||||
|
|
||||||
// Gets an existing metric or registers the given one.
|
|
||||||
// The interface can be the metric to register if not found in registry,
|
|
||||||
// or a function returning the metric for lazy instantiation.
|
|
||||||
GetOrRegister(string, interface{}) interface{} |
|
||||||
|
|
||||||
// Register the given metric under the given name.
|
|
||||||
Register(string, interface{}) error |
|
||||||
} |
} |
||||||
|
|
||||||
// The standard implementation of a Registry is a mutex-protected map
|
// The standard implementation of a Registry is a mutex-protected map
|
||||||
// of names to metrics.
|
// of names to metrics.
|
||||||
type StandardRegistry struct { |
type StandardRegistry struct { |
||||||
metrics map[string]interface{} |
metrics []Metric |
||||||
mutex sync.Mutex |
mutex sync.Mutex |
||||||
} |
} |
||||||
|
|
||||||
// Create a new registry.
|
// Create a new registry.
|
||||||
func NewRegistry() Registry { |
func NewRegistry() Registry { |
||||||
return &StandardRegistry{metrics: make(map[string]interface{})} |
return &StandardRegistry{ |
||||||
} |
metrics: make([]Metric, 0), |
||||||
|
|
||||||
// Call the given function for each registered metric.
|
|
||||||
func (r *StandardRegistry) Each(f func(string, interface{})) { |
|
||||||
for name, i := range r.registered() { |
|
||||||
f(name, i) |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
// Get the metric by the given name or nil if none is registered.
|
func (r *StandardRegistry) Register(metric Metric) { |
||||||
func (r *StandardRegistry) Get(name string) interface{} { |
|
||||||
r.mutex.Lock() |
r.mutex.Lock() |
||||||
defer r.mutex.Unlock() |
defer r.mutex.Unlock() |
||||||
return r.metrics[name] |
r.metrics = append(r.metrics, metric) |
||||||
} |
} |
||||||
|
|
||||||
// Gets an existing metric or creates and registers a new one. Threadsafe
|
// Call the given function for each registered metric.
|
||||||
// alternative to calling Get and Register on failure.
|
func (r *StandardRegistry) GetSnapshots() []Metric { |
||||||
// The interface can be the metric to register if not found in registry,
|
metrics := make([]Metric, len(r.metrics)) |
||||||
// or a function returning the metric for lazy instantiation.
|
for i, metric := range r.metrics { |
||||||
func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { |
metrics[i] = metric.Snapshot() |
||||||
r.mutex.Lock() |
metric.Clear() |
||||||
defer r.mutex.Unlock() |
|
||||||
if metric, ok := r.metrics[name]; ok { |
|
||||||
return metric |
|
||||||
} |
|
||||||
if v := reflect.ValueOf(i); v.Kind() == reflect.Func { |
|
||||||
i = v.Call(nil)[0].Interface() |
|
||||||
} |
|
||||||
r.register(name, i) |
|
||||||
return i |
|
||||||
} |
|
||||||
|
|
||||||
// Register the given metric under the given name. Returns a DuplicateMetric
|
|
||||||
// if a metric by the given name is already registered.
|
|
||||||
func (r *StandardRegistry) Register(name string, i interface{}) error { |
|
||||||
r.mutex.Lock() |
|
||||||
defer r.mutex.Unlock() |
|
||||||
return r.register(name, i) |
|
||||||
} |
|
||||||
|
|
||||||
func (r *StandardRegistry) register(name string, i interface{}) error { |
|
||||||
if _, ok := r.metrics[name]; ok { |
|
||||||
return DuplicateMetric(name) |
|
||||||
} |
|
||||||
|
|
||||||
r.metrics[name] = i |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (r *StandardRegistry) registered() map[string]interface{} { |
|
||||||
metrics := make(map[string]interface{}, len(r.metrics)) |
|
||||||
r.mutex.Lock() |
|
||||||
defer r.mutex.Unlock() |
|
||||||
for name, i := range r.metrics { |
|
||||||
metrics[name] = i |
|
||||||
} |
} |
||||||
return metrics |
return metrics |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue