Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vfoucault committed Jan 30, 2019
0 parents commit 7b78928
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 0 deletions.
28 changes: 28 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true


[[constraint]]
branch = "master"
name = "github.com/mbndr/logo"

[[constraint]]
name = "gopkg.in/yaml.v2"
version = "2.2.2"

[prune]
go-tests = true
unused-packages = true
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
grafana-annotation: Post graphite annotation to grafana

# Install

go get -d "github.com/contentsquare/grafana-annotation"

# Configure

Will work with a configuration file (default to `~/.grafana-anotation-poster.yml`)

## Configuration file

```yaml
grafanaUri: https://some-grafana-host.tld
bearerToken: BearerTokenFromGrafana
```
## Create a Bearer Token
[Read the Docs](http://docs.grafana.org/http_api/auth/)
# Build
```
go build
```


140 changes: 140 additions & 0 deletions annotation-poster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package main

import (
"bytes"
"encoding/json"
"flag"
"fmt"
"github.com/mbndr/logo"
"gopkg.in/yaml.v2"
"io/ioutil"
"net/http"
"os"
"time"
)

const (
apiPath string = "api/annotations/graphite"
)

var (
flagConfig FlagsConfig
config Config
log = logo.NewSimpleLogger(os.Stderr, logo.INFO, "grafana-annotation ", true)
)

type arrayFlags []string

func (i *arrayFlags) String() string {
return "my string representation"
}

func (i *arrayFlags) Set(value string) error {
*i = append(*i, value)
return nil
}

type FlagsConfig struct {
FilePath string
Type string
What string
Data string
Tags arrayFlags
}

func (c *FlagsConfig) Setup() {
hostname, _ := os.Hostname()
flag.StringVar(&c.FilePath, "config-file", "~/.grafana-anotation-poster.yml", "Configuration File")
flag.Var(&c.Tags, "tag", "Tags. may be repeated multiple times")
flag.StringVar(&c.What, "what", hostname, "The What item to post.")
flag.StringVar(&c.Data, "data", "", "Additional data.")
flag.Parse()
}

type Config struct {
GrafanaUri string `yaml:"grafanaUri"`
BearerToken string `yaml:"bearerToken"`
}

func (c *Config) loadConfig(filePath string) {

yamlFile, err := ioutil.ReadFile(filePath)
if err != nil {
log.Fatalf("Unable to open configuration file.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, c)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}

return
}

type GraphiteAnnotation struct {
What string `json:"what"`
Tags []string `json:"tags"`
When int64 `json:"when"`
Data string `json:"data"`
}

func (a *GraphiteAnnotation) toJson() []byte {
payload, _ := json.Marshal(a)
return payload
}

type jsonAnnotationResponse struct {
Id int `json:id`
Message string `json:message`
}

func (a *GraphiteAnnotation) post(url string, token string) {

completeUrl := fmt.Sprintf("%v/%v", url, apiPath)
payload := a.toJson()
log.Debug(string(payload))
log.Debug(completeUrl)
req, err := http.NewRequest("POST", completeUrl, bytes.NewBuffer(payload))
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token))
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("unable to post to url %v. err=%v", completeUrl, err.Error())
}
defer resp.Body.Close()

log.Info("response Status:", resp.Status)
log.Info("response Headers:", resp.Header)
body, _ := ioutil.ReadAll(resp.Body)
var response jsonAnnotationResponse
err = json.Unmarshal(body, &response)
if err != nil {
log.Fatalf("Unable to parse response. response is %v. err=%v", string(body), err.Error())
}
if response.Id == 0 {
// no id in response
log.Fatalf("error sending annotation. Message is %v", response.Message)
} else {
log.Info("response Body:", string(body))
}
}

func NewGraphiteAnnotation(what string, tags arrayFlags, data string) GraphiteAnnotation {
now := time.Now()
when := now.Unix()
log.Debugf("new anotation with %v %v %v %v", what, when, tags, data)
return GraphiteAnnotation{What: what, When: when, Tags: tags, Data: data}
}

func main() {
flagConfig.Setup()
config.loadConfig(flagConfig.FilePath)

if _, err := os.Stat(flagConfig.FilePath); os.IsNotExist(err) {
log.Fatalf("Config file not found. %v", flagConfig.FilePath)
}
annotation := NewGraphiteAnnotation(flagConfig.What, flagConfig.Tags, flagConfig.Data)
annotation.post(config.GrafanaUri, config.BearerToken)

}

0 comments on commit 7b78928

Please sign in to comment.