Skip to content

Commit

Permalink
add delete metrics api
Browse files Browse the repository at this point in the history
  • Loading branch information
kiamran authored Dec 17, 2019
1 parent a524c66 commit 7d972f8
Showing 1 changed file with 113 additions and 23 deletions.
136 changes: 113 additions & 23 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"
)

//TODO vnekhai: add docs to exported methods
var (
httpTimeout = promauto.NewGauge(prometheus.GaugeOpts{
Name: "anodot_server_http_timeout_seconds",
Expand Down Expand Up @@ -45,23 +46,15 @@ type Anodot20Metric struct {
Tags map[string]string `json:"tags"`
}

type Submitter interface {
SubmitMetrics(metrics []Anodot20Metric) (*AnodotResponse, error)
AnodotURL() *url.URL
}

// Anodot 2.0 Metrics submitter.
// See more details at https://support.anodot.com/hc/en-us/articles/360020259354-Posting-2-0-Metrics-
type Anodot20Submitter struct {
ServerURL *url.URL
Token string

client *http.Client
type AnodotResponse interface {
HasErrors() bool
ErrorMessage() string
RawResponse() *http.Response
}

// Anodot server response.
// See more at: https://app.swaggerhub.com/apis/Anodot/metrics_protocol_2.0/1.0.0#/ErrorResponse
type AnodotResponse struct {
type CreateResponse struct {
Errors []struct {
Description string
Error int64
Expand All @@ -70,16 +63,68 @@ type AnodotResponse struct {
HttpResponse *http.Response `json:"-"`
}

func (r *AnodotResponse) HasErrors() bool {
func (r *CreateResponse) HasErrors() bool {
return len(r.Errors) > 0
}

func (r *AnodotResponse) ErrorMessage() string {
func (r *CreateResponse) ErrorMessage() string {
return fmt.Sprintf("%+v\n", r.Errors)
}

func (r *CreateResponse) RawResponse() *http.Response {
return r.HttpResponse
}

type DeleteResponse struct {
ID string `json:"id"`
Validation struct {
Passed bool `json:"passed"`
Failures []struct {
ID int `json:"id"`
Message string `json:"message"`
} `json:"failures"`
} `json:"validation"`
HttpResponse *http.Response `json:"-"`
}

type DeleteExpression struct {
Type string `json:"type"`
Key string `json:"key"`
Value string `json:"value"`
}

func (a *DeleteResponse) HasErrors() bool {
return !a.Validation.Passed
}

func (a *DeleteResponse) ErrorMessage() string {
return fmt.Sprintf("%+v\n", a.Validation.Failures)
}

func (a *DeleteResponse) RawResponse() *http.Response {
return a.HttpResponse
}

type Submitter interface {
SubmitMetrics(metrics []Anodot20Metric) (*AnodotResponse, error)
AnodotURL() *url.URL
}

func (s *Anodot20Client) AnodotURL() *url.URL {
return s.ServerURL
}

// Anodot 2.0 Metrics client.
// See more details at https://support.anodot.com/hc/en-us/articles/360020259354-Posting-2-0-Metrics-
type Anodot20Client struct {
ServerURL *url.URL
Token string

client *http.Client
}

//Constructs new Anodot 2.0 submitter which should be used to send metrics to Anodot.
func NewAnodot20Submitter(anodotURL string, apiToken string, httpClient *http.Client) (*Anodot20Submitter, error) {
func NewAnodot20Client(anodotURL string, apiToken string, httpClient *http.Client) (*Anodot20Client, error) {
parsedUrl, err := url.Parse(anodotURL)
if err != nil {
return nil, fmt.Errorf("failed to parse Anodot server url: %w", err)
Expand All @@ -89,7 +134,7 @@ func NewAnodot20Submitter(anodotURL string, apiToken string, httpClient *http.Cl
return nil, fmt.Errorf("anodot api token should not be blank")
}

submitter := Anodot20Submitter{Token: apiToken, ServerURL: parsedUrl, client: httpClient}
submitter := Anodot20Client{Token: apiToken, ServerURL: parsedUrl, client: httpClient}
if httpClient == nil {
client := http.Client{Timeout: 30 * time.Second}

Expand All @@ -105,7 +150,7 @@ func NewAnodot20Submitter(anodotURL string, apiToken string, httpClient *http.Cl
return &submitter, nil
}

func (s *Anodot20Submitter) SubmitMetrics(metrics []Anodot20Metric) (*AnodotResponse, error) {
func (s *Anodot20Client) SubmitMetrics(metrics []Anodot20Metric) (AnodotResponse, error) {
s.ServerURL.Path = "/api/v1/metrics"

q := s.ServerURL.Query()
Expand All @@ -123,7 +168,7 @@ func (s *Anodot20Submitter) SubmitMetrics(metrics []Anodot20Metric) (*AnodotResp
r.Header.Add("Content-Type", "application/json")

resp, err := s.client.Do(r)
anodotResponse := &AnodotResponse{HttpResponse: resp}
anodotResponse := &CreateResponse{HttpResponse: resp}
if err != nil {
return anodotResponse, err
}
Expand Down Expand Up @@ -151,8 +196,53 @@ func (s *Anodot20Submitter) SubmitMetrics(metrics []Anodot20Metric) (*AnodotResp
}
}

func (s *Anodot20Submitter) AnodotURL() *url.URL {
return s.ServerURL
func (s *Anodot20Client) DeleteMetrics(expressions ...DeleteExpression) (AnodotResponse, error) {
s.ServerURL.Path = "/api/v1/metrics"

q := s.ServerURL.Query()
q.Set("token", s.Token)

s.ServerURL.RawQuery = q.Encode()

deleteStruct := struct {
Expression []DeleteExpression `json:"expression"`
}{}
deleteStruct.Expression = expressions

b, e := json.Marshal(deleteStruct)
if e != nil {
return nil, fmt.Errorf("failed to parse delete expression:" + e.Error())
}

r, _ := http.NewRequest(http.MethodDelete, s.ServerURL.String(), bytes.NewBuffer(b))
r.Header.Add("Content-Type", "application/json")

resp, err := s.client.Do(r)
anodotResponse := &DeleteResponse{HttpResponse: resp}
if err != nil {
return anodotResponse, err
}

statusCode := resp.StatusCode
if statusCode < 200 && statusCode >= 300 {
return anodotResponse, fmt.Errorf("http error: %d", statusCode)
}

bodyBytes, _ := ioutil.ReadAll(resp.Body)
err = json.Unmarshal(bodyBytes, anodotResponse)
if err != nil {
return anodotResponse, fmt.Errorf("failed to parse Anodot sever response: %w ", err)
}

if resp.Body == nil {
return anodotResponse, fmt.Errorf("empty response body")
}

if anodotResponse.HasErrors() {
return anodotResponse, errors.New(anodotResponse.ErrorMessage())
} else {
return anodotResponse, nil
}
}

type debugHTTPTransport struct {
Expand All @@ -161,9 +251,9 @@ type debugHTTPTransport struct {

func (d *debugHTTPTransport) RoundTrip(h *http.Request) (*http.Response, error) {
dump, _ := httputil.DumpRequestOut(h, true)
fmt.Printf("****REQUEST****\n%q\n", string(dump))
fmt.Printf("----------------------------------REQUEST----------------------------------\n%s\n", string(dump))
resp, err := d.r.RoundTrip(h)
dump, _ = httputil.DumpResponse(resp, true)
fmt.Printf("****RESPONSE****\n%q\n****************\n\n", string(dump))
fmt.Printf("----------------------------------RESPONSE----------------------------------\n%s\n----------------------------------\n\n", string(dump))
return resp, err
}

0 comments on commit 7d972f8

Please sign in to comment.