|
|
@@ -54,7 +54,7 @@ type Registry interface {
|
|
|
// of names to metrics.
|
|
|
type StandardRegistry struct {
|
|
|
metrics map[string]interface{}
|
|
|
- mutex sync.Mutex
|
|
|
+ mutex sync.RWMutex
|
|
|
}
|
|
|
|
|
|
// Create a new registry.
|
|
|
@@ -71,8 +71,8 @@ func (r *StandardRegistry) Each(f func(string, interface{})) {
|
|
|
|
|
|
// Get the metric by the given name or nil if none is registered.
|
|
|
func (r *StandardRegistry) Get(name string) interface{} {
|
|
|
- r.mutex.Lock()
|
|
|
- defer r.mutex.Unlock()
|
|
|
+ r.mutex.RLock()
|
|
|
+ defer r.mutex.RUnlock()
|
|
|
return r.metrics[name]
|
|
|
}
|
|
|
|
|
|
@@ -81,6 +81,15 @@ func (r *StandardRegistry) Get(name string) interface{} {
|
|
|
// The interface can be the metric to register if not found in registry,
|
|
|
// or a function returning the metric for lazy instantiation.
|
|
|
func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} {
|
|
|
+ // access the read lock first which should be re-entrant
|
|
|
+ r.mutex.RLock()
|
|
|
+ metric, ok := r.metrics[name]
|
|
|
+ r.mutex.RUnlock()
|
|
|
+ if ok {
|
|
|
+ return metric
|
|
|
+ }
|
|
|
+
|
|
|
+ // only take the write lock if we'll be modifying the metrics map
|
|
|
r.mutex.Lock()
|
|
|
defer r.mutex.Unlock()
|
|
|
if metric, ok := r.metrics[name]; ok {
|
|
|
@@ -103,8 +112,8 @@ func (r *StandardRegistry) Register(name string, i interface{}) error {
|
|
|
|
|
|
// Run all registered healthchecks.
|
|
|
func (r *StandardRegistry) RunHealthchecks() {
|
|
|
- r.mutex.Lock()
|
|
|
- defer r.mutex.Unlock()
|
|
|
+ r.mutex.RLock()
|
|
|
+ defer r.mutex.RUnlock()
|
|
|
for _, i := range r.metrics {
|
|
|
if h, ok := i.(Healthcheck); ok {
|
|
|
h.Check()
|