2016-09-05 20:37:35 +00:00
|
|
|
package mondash
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
const defaultHost = "https://mondash.org"
|
|
|
|
|
|
|
|
// Status type represents a collection of available status strings
|
|
|
|
type Status string
|
|
|
|
|
|
|
|
// Collection of available status strings
|
|
|
|
const (
|
2016-09-06 16:51:00 +00:00
|
|
|
StatusOK Status = "OK"
|
|
|
|
StatusWarning = "Warning"
|
|
|
|
StatusCritical = "Critical"
|
|
|
|
StatusUnknown = "Unknown"
|
2016-09-05 20:37:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Client represents an accessor to the MonDash API
|
|
|
|
type Client struct {
|
|
|
|
host string
|
|
|
|
context context.Context
|
|
|
|
board, token string
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates a new Client pre-filled with board-ID and token
|
|
|
|
func New(boardID, token string) *Client {
|
|
|
|
return &Client{
|
|
|
|
board: boardID,
|
|
|
|
context: context.Background(),
|
|
|
|
host: defaultHost,
|
|
|
|
token: token,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) do(method, path string, body io.Reader) error {
|
|
|
|
req, err := http.NewRequest(method, c.host+path, body)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-09-06 16:34:14 +00:00
|
|
|
req.Header.Set("Authorization", c.token)
|
|
|
|
|
2016-09-05 20:37:35 +00:00
|
|
|
req = req.WithContext(c.context)
|
|
|
|
res, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
|
|
|
|
if res.StatusCode != 200 {
|
|
|
|
return fmt.Errorf("Received unexpected status code %d", res.StatusCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithHost creates a copy of the Client with replaced hostname for own instances
|
|
|
|
func (c *Client) WithHost(host string) *Client {
|
|
|
|
c2 := new(Client)
|
|
|
|
*c2 = *c
|
|
|
|
c2.host = host
|
|
|
|
return c2
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithContext craetes a copy of the Client using the passed context instead of context.Background()
|
|
|
|
func (c *Client) WithContext(ctx context.Context) *Client {
|
|
|
|
if ctx == nil {
|
|
|
|
panic("nil context")
|
|
|
|
}
|
|
|
|
c2 := new(Client)
|
|
|
|
*c2 = *c
|
|
|
|
c2.context = ctx
|
|
|
|
return c2
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteDashboard will delete all your monitoring results available on your dashboard and release the dashboard URL to the public
|
|
|
|
func (c *Client) DeleteDashboard() error {
|
|
|
|
return c.do("DELETE", "/"+c.board, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// PostMetricInput contains parameters for the API request
|
|
|
|
type PostMetricInput struct {
|
|
|
|
// The unique name for your metric Example: `beer_available`.
|
|
|
|
MetricID string `json:"-"`
|
|
|
|
|
|
|
|
// The title of the metric to display on the dashboard
|
|
|
|
Title string `json:"title"`
|
|
|
|
|
|
|
|
// A descriptive text for the current state of the metric
|
|
|
|
Description string `json:"description"`
|
|
|
|
|
|
|
|
// One of: OK, Warning, Critical, Unknown
|
|
|
|
Status Status `json:"status"`
|
|
|
|
|
2016-09-06 16:44:27 +00:00
|
|
|
// The metric value to store with the status
|
|
|
|
Value float64 `json:"value"`
|
|
|
|
|
2016-09-05 20:37:35 +00:00
|
|
|
// Time in seconds when to remove the metric if there is no update (Valid: `0 < x < 604800`)
|
|
|
|
// Default: `604800`
|
|
|
|
Expires int64 `json:"expires,omitempty"`
|
|
|
|
|
|
|
|
// Time in seconds when to switch to `Unkown` state of there is no update (Valid: `0 < x < 604800`)
|
|
|
|
// Default: 3600
|
|
|
|
Freshness int64 `json:"freshness,omitempty"`
|
|
|
|
|
|
|
|
// If set to true the status passed in the update will be used instead of the median absolute deviation
|
|
|
|
// Default: false
|
|
|
|
IgnoreMAD bool `json:"ignore_mad,omitempty"`
|
|
|
|
|
|
|
|
// If set to true the median absolute deviation is hidden on the dashboard for this metric
|
|
|
|
// Default: false
|
|
|
|
HideMAD bool `json:"hide_mad,omitempty"`
|
2018-01-20 18:01:26 +00:00
|
|
|
|
|
|
|
// If set to true the value of the metric is not shown on the dashboard
|
|
|
|
// Default: false
|
|
|
|
HideValue bool `json:"hide_value,omitempty"`
|
2016-09-05 20:37:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *PostMetricInput) validate() error {
|
|
|
|
if p.MetricID == "" {
|
|
|
|
return errors.New("Field 'MetricID' is required.")
|
|
|
|
}
|
|
|
|
if p.Title == "" {
|
|
|
|
return errors.New("Field 'Title' is required.")
|
|
|
|
}
|
|
|
|
if p.Description == "" {
|
|
|
|
return errors.New("Field 'Description' is required.")
|
|
|
|
}
|
|
|
|
if p.Status == "" {
|
|
|
|
return errors.New("Field 'Status' is required.")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// PostMetric submits a new monitoring result
|
|
|
|
func (c *Client) PostMetric(input *PostMetricInput) error {
|
|
|
|
if err := input.validate(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
buf := bytes.NewBuffer([]byte{})
|
|
|
|
if err := json.NewEncoder(buf).Encode(input); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.do("PUT", "/"+c.board+"/"+input.MetricID, buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteMetricInput contains parameters for the API request
|
|
|
|
type DeleteMetricInput struct {
|
|
|
|
// The unique name for your metric Example: `beer_available`.
|
|
|
|
MetricID string
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteMetric deletes a metric from your dashboard
|
|
|
|
func (c *Client) DeleteMetric(input *DeleteMetricInput) error {
|
|
|
|
return c.do("DELETE", "/"+c.board+"/"+input.MetricID, nil)
|
|
|
|
}
|