-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
919 additions
and
303 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
dist | ||
statsd | ||
statsd_linux_amd64 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM debian:wheezy | ||
|
||
ADD statsd_linux_amd64 /usr/bin/statsd | ||
|
||
EXPOSE 8125 | ||
|
||
ENTRYPOINT ["statsd"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,39 @@ | ||
VERSION=0.1.4 | ||
name := statsd | ||
version := $(shell cat main.go | grep VERSION | sed -e 's/\"//g' | head -n1 |cut -d' ' -f4) | ||
|
||
default: fmt run | ||
default: fmt build | ||
|
||
fmt: | ||
go fmt *.go | ||
|
||
debug: | ||
go run main.go -debug -flush=5 -percentiles=90,95,99 | ||
|
||
build: | ||
go build | ||
go build -o $(name) | ||
|
||
build-linux-amd64: | ||
GOOS=linux GOARCH=amd64 go build -o $(name)_linux_amd64 | ||
|
||
docker-build: | ||
GOOS=linux GOARCH=amd64 go build -o $(name)_linux_amd64 | ||
docker build -t jcoene/statsd-librato:latest . | ||
|
||
docker-release: docker-build | ||
docker push jcoene/statsd-librato:latest | ||
|
||
run: build | ||
./statsd -debug -flush=5 -percentiles=90,95,99 | ||
|
||
test: | ||
go test -cover | ||
|
||
release: | ||
mkdir -p dist | ||
|
||
mkdir -p statsd-${VERSION}.darwin-amd64/bin | ||
GOOS=darwin GOARCH=amd64 go build -o statsd-${VERSION}.darwin-amd64/bin/statsd | ||
tar zcvf dist/statsd-${VERSION}.darwin-amd64.tar.gz statsd-${VERSION}.darwin-amd64 | ||
rm -rf statsd-${VERSION}.darwin-amd64 | ||
mkdir -p statsd-$(version).darwin-amd64/bin | ||
GOOS=darwin GOARCH=amd64 go build -o statsd-$(version).darwin-amd64/bin/statsd | ||
tar zcvf dist/statsd-$(version).darwin-amd64.tar.gz statsd-$(version).darwin-amd64 | ||
rm -rf statsd-$(version).darwin-amd64 | ||
|
||
mkdir -p statsd-${VERSION}.linux-amd64/bin | ||
GOOS=linux GOARCH=amd64 go build -o statsd-${VERSION}.linux-amd64/bin/statsd | ||
tar zcvf dist/statsd-${VERSION}.linux-amd64.tar.gz statsd-${VERSION}.linux-amd64 | ||
rm -rf statsd-${VERSION}.linux-amd64 | ||
mkdir -p statsd-$(version).linux-amd64/bin | ||
GOOS=linux GOARCH=amd64 go build -o statsd-$(version).linux-amd64/bin/statsd | ||
tar zcvf dist/statsd-$(version).linux-amd64.tar.gz statsd-$(version).linux-amd64 | ||
rm -rf statsd-$(version).linux-amd64 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"math" | ||
"net/http" | ||
"sort" | ||
) | ||
|
||
type Measurement struct { | ||
Counters []*Counter `json:"counters"` | ||
Gauges []interface{} `json:"gauges"` | ||
Source string `json:"source,omitempty"` | ||
} | ||
|
||
func (m *Measurement) Count() int { | ||
return (len(m.Counters) + len(m.Gauges)) | ||
} | ||
|
||
type Counter struct { | ||
Name string `json:"name"` | ||
Source string `json:"source,omitempty"` | ||
Value float64 `json:"value"` | ||
} | ||
|
||
type Gauge struct { | ||
Name string `json:"name"` | ||
Source string `json:"source,omitempty"` | ||
Value float64 `json:"value"` | ||
} | ||
|
||
type ComplexGauge struct { | ||
Name string `json:"name"` | ||
Source string `json:"source,omitempty"` | ||
Count int `json:"count"` | ||
Sum float64 `json:"sum"` | ||
Min float64 `json:"min"` | ||
Max float64 `json:"max"` | ||
SumSquares float64 `json:"sum_squares"` | ||
} | ||
|
||
func submitLibrato() (err error) { | ||
m := buildMeasurement() | ||
|
||
if m.Count() == 0 { | ||
return | ||
} | ||
|
||
payload, err := json.MarshalIndent(m, "", " ") | ||
if err != nil { | ||
return | ||
} | ||
|
||
if *debug { | ||
log.Printf("sending payload:\n%s\n", string(payload)) | ||
} | ||
|
||
req, err := http.NewRequest("POST", "https://metrics-api.librato.com/v1/metrics", bytes.NewBuffer(payload)) | ||
if err != nil { | ||
return | ||
} | ||
|
||
req.Header.Add("Content-Type", "application/json") | ||
req.Header.Set("User-Agent", "statsd/1.0") | ||
req.SetBasicAuth(*libratoUser, *libratoToken) | ||
req.Close = true | ||
|
||
resp, err := http.DefaultClient.Do(req) | ||
if err != nil { | ||
return | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != 200 { | ||
raw, _ := ioutil.ReadAll(resp.Body) | ||
return fmt.Errorf("%s: %s", resp.Status, string(raw)) | ||
} | ||
|
||
log.Printf("%d measurements sent to librato\n", m.Count()) | ||
|
||
resetTimers() | ||
|
||
return | ||
} | ||
|
||
func buildMeasurement() (m *Measurement) { | ||
m = &Measurement{} | ||
if libratoSource != nil { | ||
m.Source = *libratoSource | ||
} | ||
|
||
m.Counters = make([]*Counter, len(counters)) | ||
m.Gauges = make([]interface{}, len(gauges)) | ||
|
||
n := 0 | ||
for k, v := range counters { | ||
c := &Counter{} | ||
c.Name, c.Source = parseSource(k) | ||
c.Value = v | ||
m.Counters[n] = c | ||
n++ | ||
} | ||
|
||
n = 0 | ||
for k, v := range gauges { | ||
g := &Gauge{} | ||
g.Name, g.Source = parseSource(k) | ||
g.Value = v | ||
m.Gauges[n] = g | ||
n++ | ||
} | ||
|
||
for k, t := range timers { | ||
for _, pct := range tiles { | ||
if g := buildComplexGauge(k, t, pct); g != nil { | ||
m.Gauges = append(m.Gauges, g) | ||
} | ||
} | ||
} | ||
|
||
return | ||
} | ||
|
||
func buildComplexGauge(k string, t []float64, pct float64) *ComplexGauge { | ||
threshold := ((100.0 - pct) / 100.0) * float64(len(t)) | ||
threshold = math.Floor(threshold + 0.5) | ||
|
||
count := len(t) - int(threshold) | ||
if count <= 0 { | ||
return nil | ||
} | ||
|
||
g := &ComplexGauge{} | ||
g.Name, g.Source = parseSource(k) | ||
if pct != 100.0 { | ||
if float64(int(pct)) != pct { | ||
rem := int(math.Ceil((pct - float64(int(pct))) * 10)) | ||
g.Name += fmt.Sprintf(".%d_%d", int(pct), rem) | ||
} else { | ||
g.Name += fmt.Sprintf(".%d", int(pct)) | ||
} | ||
} | ||
g.Count = count | ||
|
||
sort.Float64s(t) | ||
g.Min = t[0] | ||
g.Max = t[count-1] | ||
for i := 0; i < count; i++ { | ||
g.Sum += t[i] | ||
g.SumSquares += (t[i] * t[i]) | ||
} | ||
|
||
return g | ||
} |
Oops, something went wrong.