Bladeren bron

converting everything to map[string]interface{}

mihasya 12 jaren geleden
bovenliggende
commit
382b1f1161
2 gewijzigde bestanden met toevoegingen van 197 en 46 verwijderingen
  1. 100 0
      librato/client.go
  2. 97 46
      librato/librato.go

+ 100 - 0
librato/client.go

@@ -0,0 +1,100 @@
+package librato
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+)
+
+type LibratoClient struct {
+	Email, Token string
+}
+
+// property strings
+const (
+	// display attributes
+	Color             = "color"
+	DisplayMax        = "display_max"
+	DisplayMin        = "display_min"
+	DisplayUnitsLong  = "display_units_long"
+	DisplayUnitsShort = "display_units_short"
+	DisplayStacked    = "display_stacked"
+	DisplayTransform  = "display_transform"
+	// special gauge display attributes
+	SummarizeFunction = "summarize_function"
+	Aggregate         = "aggregate"
+
+	// metric keys
+	Name        = "name"
+	Period      = "period"
+	Description = "description"
+	DisplayName = "display_name"
+	Attributes  = "attributes"
+
+	// measurement keys
+	MeasureTime = "measure_time"
+	Source      = "source"
+	Value       = "value"
+
+	// special gauge keys
+	Count      = "count"
+	Sum        = "sum"
+	Max        = "max"
+	Min        = "min"
+	SumSquares = "sum_squares"
+
+	// batch keys
+	Counters = "counters"
+	Gauges   = "gauges"
+
+	MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics"
+)
+
+type Measurement map[string]interface{}
+type Metric map[string]interface{}
+
+type Batch struct {
+	Gauges      []Measurement `json:"gauges,omitempty"`
+	Counters    []Measurement `json:"counters,omitempty"`
+	MeasureTime int64         `json:"measure_time"`
+	Source      string        `json:"source"`
+}
+
+func (self *LibratoClient) PostMetrics(batch Batch) (err error) {
+	var (
+		js   []byte
+		req  *http.Request
+		resp *http.Response
+	)
+
+	if len(batch.Counters) == 0 && len(batch.Gauges) == 0 {
+		return nil
+	}
+
+	if js, err = json.Marshal(batch); err != nil {
+		return
+	}
+
+	if req, err = http.NewRequest("POST", MetricsPostUrl, bytes.NewBuffer(js)); err != nil {
+		return
+	}
+
+	req.Header.Set("Content-Type", "application/json")
+	req.SetBasicAuth(self.Email, self.Token)
+
+	if resp, err = http.DefaultClient.Do(req); err != nil {
+		return
+	}
+
+	if resp.StatusCode != http.StatusOK {
+		var body []byte
+		var err error
+		if body, err = ioutil.ReadAll(resp.Body); err != nil {
+			body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err))
+		}
+		err = fmt.Errorf("Unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body))
+	}
+	return
+}

+ 97 - 46
librato/librato.go

@@ -1,9 +1,13 @@
 package librato
 
+// TODO: use map[string]interface{} and constants for keys for everything to
+// avoid the omitempty/0 problem; remove dependency on samuel/go-librato
+
+// TODO WIP status: test that the resulting JSON is actually correct..
+
 import (
 	"fmt"
 	"github.com/rcrowley/go-metrics"
-	"github.com/samuel/go-librato/librato"
 	"log"
 	"math"
 	"time"
@@ -24,14 +28,14 @@ func Librato(r metrics.Registry, d time.Duration, e string, t string, s string,
 
 func (self *LibratoReporter) Run() {
 	ticker := time.Tick(self.Interval)
-	metricsApi := &librato.Metrics{self.Email, self.Token}
+	metricsApi := &LibratoClient{self.Email, self.Token}
 	for now := range ticker {
-		var metrics *librato.MetricsFormat
+		var metrics Batch
 		var err error
 		if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
 			log.Printf("ERROR constructing librato request body %s", err)
 		}
-		if err := metricsApi.SendMetrics(metrics); err != nil {
+		if err := metricsApi.PostMetrics(metrics); err != nil {
 			log.Printf("ERROR sending metrics to librato %s", err)
 		}
 	}
@@ -60,81 +64,128 @@ func sumSquaresTimer(m metrics.Timer) float64 {
 	return sumSquares
 }
 
-func (self *LibratoReporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot *librato.MetricsFormat, err error) {
-	snapshot = &librato.MetricsFormat{}
+func (self *LibratoReporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
+	snapshot = Batch{
+		MeasureTime: now.Unix(),
+		Source:      self.Source,
+	}
 	snapshot.MeasureTime = now.Unix()
-	snapshot.Source = self.Source
-	snapshot.Gauges = make([]interface{}, 0)
-	snapshot.Counters = make([]librato.Metric, 0)
+	snapshot.Gauges = make([]Measurement, 0)
+	snapshot.Counters = make([]Measurement, 0)
 	histogramGaugeCount := 1 + len(self.Percentiles)
 	r.Each(func(name string, metric interface{}) {
+		measurement := Measurement{}
+		measurement[Period] = self.Interval.Seconds()
 		switch m := metric.(type) {
 		case metrics.Counter:
-			libratoName := fmt.Sprintf("%s.%s", name, "count")
-			snapshot.Counters = append(snapshot.Counters, librato.Metric{Name: libratoName, Value: float64(m.Count())})
+			measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
+			measurement[Value] = float64(m.Count())
+			snapshot.Counters = append(snapshot.Counters, measurement)
 		case metrics.Gauge:
-			snapshot.Gauges = append(snapshot.Gauges, librato.Metric{Name: name, Value: float64(m.Value())})
+			measurement[Name] = name
+			measurement[Value] = float64(m.Value())
+			snapshot.Gauges = append(snapshot.Gauges, measurement)
 		case metrics.Histogram:
 			if m.Count() > 0 {
-				libratoName := fmt.Sprintf("%s.%s", name, "hist")
-				gauges := make([]interface{}, histogramGaugeCount, histogramGaugeCount)
-				gauges[0] = librato.Gauge{
-					Name:       libratoName,
-					Count:      uint64(m.Count()),
-					Sum:        m.Mean() * float64(m.Count()),
-					Max:        float64(m.Max()),
-					Min:        float64(m.Min()),
-					SumSquares: sumSquares(m),
-				}
+				gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
+				measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
+				measurement[Count] = uint64(m.Count())
+				measurement[Sum] = m.Mean() * float64(m.Count())
+				measurement[Max] = float64(m.Max())
+				measurement[Min] = float64(m.Min())
+				measurement[SumSquares] = sumSquares(m)
+				gauges[0] = measurement
 				for i, p := range self.Percentiles {
-					gauges[i+1] = librato.Metric{Name: fmt.Sprintf("%s.%.2f", libratoName, p), Value: m.Percentile(p)}
+					pMeasurement := Measurement{}
+					pMeasurement[Name] = fmt.Sprintf("%s.%.2f", measurement[Name], p)
+					pMeasurement[Value] = m.Percentile(p)
+					pMeasurement[Period] = measurement[Period]
+					gauges[i+1] = pMeasurement
 				}
 				snapshot.Gauges = append(snapshot.Gauges, gauges...)
 			}
 		case metrics.Meter:
-			snapshot.Counters = append(snapshot.Counters, librato.Metric{Name: name, Value: float64(m.Count())})
+			measurement[Name] = name
+			measurement[Value] = float64(m.Count())
+			snapshot.Counters = append(snapshot.Counters, measurement)
 			snapshot.Gauges = append(snapshot.Gauges,
-				librato.Metric{
-					Name:  fmt.Sprintf("%s.%s", name, "1min"),
-					Value: m.Rate1(),
+				Measurement{
+					Name:   fmt.Sprintf("%s.%s", name, "1min"),
+					Value:  m.Rate1(),
+					Period: int64(self.Interval.Seconds()),
 				},
-				librato.Metric{
-					Name:  fmt.Sprintf("%s.%s", name, "5min"),
-					Value: m.Rate5(),
+				Measurement{
+					Name:   fmt.Sprintf("%s.%s", name, "5min"),
+					Value:  m.Rate5(),
+					Period: int64(self.Interval.Seconds()),
 				},
-				librato.Metric{
-					Name:  fmt.Sprintf("%s.%s", name, "15min"),
-					Value: m.Rate15(),
+				Measurement{
+					Name:   fmt.Sprintf("%s.%s", name, "15min"),
+					Value:  m.Rate15(),
+					Period: int64(self.Interval.Seconds()),
 				},
 			)
 		case metrics.Timer:
 			if m.Count() > 0 {
-				libratoName := fmt.Sprintf("%s.%s", name, "timer")
-				gauges := make([]interface{}, histogramGaugeCount, histogramGaugeCount)
-				gauges[0] = librato.Gauge{
+				libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
+				gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
+				gauges[0] = Measurement{
 					Name:       libratoName,
 					Count:      uint64(m.Count()),
 					Sum:        m.Mean() * float64(m.Count()),
 					Max:        float64(m.Max()),
 					Min:        float64(m.Min()),
 					SumSquares: sumSquaresTimer(m),
+					Period:     int64(self.Interval.Seconds()),
+					Attributes: map[string]interface{}{
+						DisplayTransform:  "x/1000000",
+						DisplayUnitsLong:  "milliseconds",
+						DisplayUnitsShort: "ms",
+					},
 				}
 				for i, p := range self.Percentiles {
-					gauges[i+1] = librato.Metric{Name: fmt.Sprintf("%s.%2.0f", libratoName, p*100), Value: m.Percentile(p)}
+					gauges[i+1] = Measurement{
+						Name:   fmt.Sprintf("%s.timer.%2.0f", name, p*100),
+						Value:  m.Percentile(p),
+						Period: int64(self.Interval.Seconds()),
+						Attributes: map[string]interface{}{
+							DisplayTransform:  "x/1000000",
+							DisplayUnitsLong:  "milliseconds",
+							DisplayUnitsShort: "ms",
+						},
+					}
 				}
 				snapshot.Gauges = append(snapshot.Gauges, gauges...)
 				snapshot.Gauges = append(snapshot.Gauges,
-					librato.Metric{
-						Name:  fmt.Sprintf("%s.%s", name, "1min"),
-						Value: m.Rate1(),
+					Measurement{
+						Name:   fmt.Sprintf("%s.%s", name, "rate.1min"),
+						Value:  m.Rate1(),
+						Period: int64(self.Interval.Seconds()),
+						Attributes: map[string]interface{}{
+							DisplayUnitsLong:  "occurences",
+							DisplayUnitsShort: "occ",
+							DisplayMin:        "0",
+						},
 					},
-					librato.Metric{
-						Name:  fmt.Sprintf("%s.%s", name, "5min"),
-						Value: m.Rate5(),
+					Measurement{
+						Name:   fmt.Sprintf("%s.%s", name, "rate.5min"),
+						Value:  m.Rate5(),
+						Period: int64(self.Interval.Seconds()),
+						Attributes: map[string]interface{}{
+							DisplayUnitsLong:  "occurences",
+							DisplayUnitsShort: "occ",
+							DisplayMin:        "0",
+						},
 					},
-					librato.Metric{
-						Name:  fmt.Sprintf("%s.%s", name, "15min"),
-						Value: m.Rate15(),
+					Measurement{
+						Name:   fmt.Sprintf("%s.%s", name, "rate.15min"),
+						Value:  m.Rate15(),
+						Period: int64(self.Interval.Seconds()),
+						Attributes: map[string]interface{}{
+							DisplayUnitsLong:  "occurences",
+							DisplayUnitsShort: "occ",
+							DisplayMin:        "0",
+						},
 					},
 				)
 			}