Skip to content

Commit e2b1c44

Browse files
committed
Add Datadob support
1 parent 3602d51 commit e2b1c44

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,11 @@ jplot --url http://:8080/debug/vars \
9797

9898
![](doc/memstats.png)
9999

100+
### Datadog
101+
102+
To graph metrics from Datadob, you have to pass a Datadog API and Application key to jplot as follow:
103+
104+
```
105+
jplot --url datadog://<api_key>/<app_key> metrics…
106+
```
100107

data/datadog.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package data
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
"github.com/elgs/gojq"
8+
"gopkg.in/zorkian/go-datadog-api.v2"
9+
)
10+
11+
type datadogSource struct {
12+
client *datadog.Client
13+
specs []Spec
14+
c chan res
15+
done chan struct{}
16+
17+
// state
18+
lastQueryTime int64
19+
}
20+
21+
// FromDatadog fetches data from Datadog service (http://datadog.com).
22+
func FromDatadog(apiKey, appKey string, specs []Spec, interval time.Duration, size int) *Points {
23+
client := datadog.NewClient(apiKey, appKey)
24+
s := &datadogSource{
25+
client: client,
26+
specs: specs,
27+
c: make(chan res),
28+
done: make(chan struct{}),
29+
lastQueryTime: time.Now().Unix(),
30+
}
31+
go s.run(interval)
32+
return &Points{
33+
Size: size,
34+
Source: s,
35+
}
36+
}
37+
38+
func (s *datadogSource) run(interval time.Duration) {
39+
t := time.NewTicker(interval)
40+
defer t.Stop()
41+
for {
42+
select {
43+
case <-t.C:
44+
s.fetch()
45+
case <-s.done:
46+
close(s.c)
47+
return
48+
}
49+
}
50+
}
51+
52+
func (s *datadogSource) fetch() {
53+
maxUpdateTimestamp := int64(s.lastQueryTime)
54+
dataPoints := make(map[string]datadog.DataPoint, len(s.specs))
55+
var err error
56+
for _, spec := range s.specs {
57+
for _, field := range spec.Fields {
58+
query := s.formatQuery(field)
59+
series, err := s.client.QueryMetrics(s.lastQueryTime, time.Now().Unix(), query)
60+
if err != nil {
61+
s.c <- res{err: err}
62+
return
63+
}
64+
if len(series) == 0 {
65+
s.c <- res{err: fmt.Errorf("no data for %s", field.Name)}
66+
return
67+
}
68+
endTs := int64(series[0].GetEnd() / 1000)
69+
if endTs > maxUpdateTimestamp {
70+
maxUpdateTimestamp = endTs
71+
}
72+
// assume the last data point is the latest
73+
dataPoints[field.ID] = series[0].Points[len(series[0].Points)-1]
74+
}
75+
}
76+
77+
jq := gojq.NewQuery(dataPoints)
78+
s.c <- res{jq: jq, err: err}
79+
}
80+
81+
func (s *datadogSource) formatQuery(field Field) string {
82+
querySuffix := ""
83+
if field.IsCounter {
84+
querySuffix = ".as_count()"
85+
}
86+
return fmt.Sprintf("%s%s", field.Name, querySuffix)
87+
}
88+
89+
func (s *datadogSource) Get() (*gojq.JQ, error) {
90+
res := <-s.c
91+
return res.jq, res.err
92+
}
93+
94+
func (s *datadogSource) Close() error {
95+
close(s.done)
96+
return nil
97+
}

data/http.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type res struct {
1818
err error
1919
}
2020

21-
// FromHTTP fetch data points from url every interval and keep size points.
21+
// FromHTTP fetches data points from url every interval and keep size points.
2222
func FromHTTP(url string, interval time.Duration, size int) *Points {
2323
h := httpSource{
2424
c: make(chan res),

main.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,15 @@ func main() {
3636
}
3737
var dp *data.Points
3838
if *url != "" {
39-
dp = data.FromHTTP(*url, *interval, *steps)
39+
if strings.HasPrefix(*url, "datadog://") {
40+
keys := strings.Split((*url)[10:], "/")
41+
if len(keys) != 2 {
42+
fatal("invalid datadog url, format is datadog://apiKey/appKey")
43+
}
44+
dp = data.FromDatadog(keys[0], keys[1], specs, *interval, *steps)
45+
} else {
46+
dp = data.FromHTTP(*url, *interval, *steps)
47+
}
4048
} else {
4149
dp = data.FromStdin(*steps)
4250
}

0 commit comments

Comments
 (0)