Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Datadog support #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,11 @@ jplot --url http://:8080/debug/vars \

![](doc/memstats.png)

### Datadog

To graph metrics from Datadob, you have to pass a Datadog API and Application key to jplot as follow:

```
jplot --url datadog://<api_key>/<app_key> metrics…
```

97 changes: 97 additions & 0 deletions data/datadog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package data

import (
"fmt"
"time"

"github.com/elgs/gojq"
"gopkg.in/zorkian/go-datadog-api.v2"
)

type datadogSource struct {
client *datadog.Client
specs []Spec
c chan res
done chan struct{}

// state
lastQueryTime int64
}

// FromDatadog fetches data from Datadog service (http://datadog.com).
func FromDatadog(apiKey, appKey string, specs []Spec, interval time.Duration, size int) *Points {
client := datadog.NewClient(apiKey, appKey)
s := &datadogSource{
client: client,
specs: specs,
c: make(chan res),
done: make(chan struct{}),
lastQueryTime: time.Now().Unix(),
}
go s.run(interval)
return &Points{
Size: size,
Source: s,
}
}

func (s *datadogSource) run(interval time.Duration) {
t := time.NewTicker(interval)
defer t.Stop()
for {
select {
case <-t.C:
s.fetch()
case <-s.done:
close(s.c)
return
}
}
}

func (s *datadogSource) fetch() {
maxUpdateTimestamp := int64(s.lastQueryTime)
dataPoints := make(map[string]datadog.DataPoint, len(s.specs))
var err error
for _, spec := range s.specs {
for _, field := range spec.Fields {
query := s.formatQuery(field)
series, err := s.client.QueryMetrics(s.lastQueryTime, time.Now().Unix(), query)
if err != nil {
s.c <- res{err: err}
return
}
if len(series) == 0 {
s.c <- res{err: fmt.Errorf("no data for %s", field.Name)}
return
}
endTs := int64(series[0].GetEnd() / 1000)
if endTs > maxUpdateTimestamp {
maxUpdateTimestamp = endTs
}
// assume the last data point is the latest
dataPoints[field.ID] = series[0].Points[len(series[0].Points)-1]
}
}

jq := gojq.NewQuery(dataPoints)
s.c <- res{jq: jq, err: err}
}

func (s *datadogSource) formatQuery(field Field) string {
querySuffix := ""
if field.IsCounter {
querySuffix = ".as_count()"
}
return fmt.Sprintf("%s%s", field.Name, querySuffix)
}

func (s *datadogSource) Get() (*gojq.JQ, error) {
res := <-s.c
return res.jq, res.err
}

func (s *datadogSource) Close() error {
close(s.done)
return nil
}
2 changes: 1 addition & 1 deletion data/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type res struct {
err error
}

// FromHTTP fetch data points from url every interval and keep size points.
// FromHTTP fetches data points from url every interval and keep size points.
func FromHTTP(url string, interval time.Duration, size int) *Points {
h := httpSource{
c: make(chan res),
Expand Down
10 changes: 9 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ func main() {
}
var dp *data.Points
if *url != "" {
dp = data.FromHTTP(*url, *interval, *steps)
if strings.HasPrefix(*url, "datadog://") {
keys := strings.Split((*url)[10:], "/")
if len(keys) != 2 {
fatal("invalid datadog url, format is datadog://apiKey/appKey")
}
dp = data.FromDatadog(keys[0], keys[1], specs, *interval, *steps)
} else {
dp = data.FromHTTP(*url, *interval, *steps)
}
} else {
dp = data.FromStdin(*steps)
}
Expand Down