Browse Source

feat(metrics): Add metrics pkg

Brian Waldon 12 years ago
parent
commit
14c96306a0
3 changed files with 154 additions and 0 deletions
  1. 42 0
      metrics/metrics.go
  2. 25 0
      metrics/nil.go
  3. 87 0
      metrics/standard.go

+ 42 - 0
metrics/metrics.go

@@ -0,0 +1,42 @@
+// Package metrics provides both a means of generating metrics and the ability
+// to send metric data to a graphite endpoint.
+// The usage of this package without providing a graphite_addr when calling
+// NewBucket results in NOP metric objects. No data will be collected.
+package metrics
+
+import (
+	"io"
+
+	gometrics "github.com/rcrowley/go-metrics"
+)
+
+type Timer gometrics.Timer
+type Gauge gometrics.Gauge
+
+type Bucket interface {
+	// If a timer exists in this Bucket, return it. Otherwise, create
+	// a new timer with the given name and store it in this Bucket.
+	// The returned object will fulfull the Timer interface.
+	Timer(name string) Timer
+
+	// This acts similarly to Timer, but with objects that fufill the
+	// Gauge interface.
+	Gauge(name string) Gauge
+
+	// Write the current state of all Metrics in a human-readable format
+	// to the provide io.Writer.
+	Dump(io.Writer)
+
+	// Instruct the Bucket to periodically push all metric data to the
+	// provided graphite endpoint.
+	Publish(string) error
+}
+
+// Create a new Bucket object that periodically
+func NewBucket(name string) Bucket {
+	if name == "" {
+		return nilBucket{}
+	}
+
+	return newStandardBucket(name)
+}

+ 25 - 0
metrics/nil.go

@@ -0,0 +1,25 @@
+package metrics
+
+import (
+	"io"
+
+	gometrics "github.com/rcrowley/go-metrics"
+)
+
+type nilBucket struct{}
+
+func (nmb nilBucket) Dump(w io.Writer) {
+	return
+}
+
+func (nmb nilBucket) Timer(name string) Timer {
+	return gometrics.NilTimer{}
+}
+
+func (nmf nilBucket) Gauge(name string) Gauge {
+	return gometrics.NilGauge{}
+}
+
+func (nmf nilBucket) Publish(string) error {
+	return nil
+}

+ 87 - 0
metrics/standard.go

@@ -0,0 +1,87 @@
+package metrics
+
+import (
+	"io"
+	"net"
+	"sync"
+	"time"
+
+	gometrics "github.com/rcrowley/go-metrics"
+)
+
+const (
+	// RuntimeMemStatsSampleInterval is the interval in seconds at which the
+	// Go runtime's memory statistics will be gathered.
+	RuntimeMemStatsSampleInterval = time.Duration(2) * time.Second
+
+	// GraphitePublishInterval is the interval in seconds at which all
+	// gathered statistics will be published to a Graphite endpoint.
+	GraphitePublishInterval = time.Duration(2) * time.Second
+)
+
+
+type standardBucket struct {
+	sync.Mutex
+	name     string
+	registry gometrics.Registry
+	timers   map[string]Timer
+	gauges   map[string]Gauge
+}
+
+func newStandardBucket(name string) standardBucket {
+	registry := gometrics.NewRegistry()
+
+	gometrics.RegisterRuntimeMemStats(registry)
+	go gometrics.CaptureRuntimeMemStats(registry, RuntimeMemStatsSampleInterval)
+
+	return standardBucket{
+		name:     name,
+		registry: registry,
+		timers:   make(map[string]Timer),
+		gauges:   make(map[string]Gauge),
+	}
+}
+
+func (smb standardBucket) Dump(w io.Writer) {
+	gometrics.WriteOnce(smb.registry, w)
+	return
+}
+
+func (smb standardBucket) Timer(name string) Timer {
+	smb.Lock()
+	defer smb.Unlock()
+
+	timer, ok := smb.timers[name]
+	if !ok {
+		timer = gometrics.NewTimer()
+		smb.timers[name] = timer
+		smb.registry.Register(name, timer)
+	}
+
+	return timer
+}
+
+func (smb standardBucket) Gauge(name string) Gauge {
+	smb.Lock()
+	defer smb.Unlock()
+
+	gauge, ok := smb.gauges[name]
+	if !ok {
+		gauge = gometrics.NewGauge()
+		smb.gauges[name] = gauge
+		smb.registry.Register(name, gauge)
+	}
+
+	return gauge
+}
+
+func (smb standardBucket) Publish(graphite_addr string) error {
+	addr, err := net.ResolveTCPAddr("tcp", graphite_addr)
+	if err != nil {
+		return err
+	}
+
+	go gometrics.Graphite(smb.registry, GraphitePublishInterval, smb.name, addr)
+
+	return nil
+}