-
Notifications
You must be signed in to change notification settings - Fork 8
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
Grafana alerts #111
Grafana alerts #111
Changes from all commits
7f70951
c797c87
d527a85
6ac3c0b
4a1ac6d
da94332
a3852d9
aeb3c67
e0849fb
ea410da
8336761
669958e
d3013d3
3858a03
cca4ca7
102cdd9
4cac51d
baf34b6
cdd3f27
7df1557
f00203b
0d166a2
244d569
83d4cad
b717e77
b934091
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Grafana Alert | ||
|
||
To create a Grafana alert: | ||
|
||
```go | ||
data := grafana_alerts.GrafanaAlertQuery{ | ||
DatasourceUid: "__expr__", | ||
Model: json.RawMessage(`{"conditions":[{"evaluator":{"params":[0,0],"type":"gt"},"operator":{"type":"and"},"query":{"params":[]},"reducer":{"params":[],"type":"avg"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1 == 1","hide":false,"intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}`), | ||
RefId: "A", | ||
RelativeTimeRange: grafana_alerts.RelativeTimeRangeObj{ | ||
From: 0, | ||
To: 0, | ||
}, | ||
} | ||
|
||
createGrafanaAlert := grafana_alerts.GrafanaAlertRule{ | ||
Annotations: map[string]string{"key_test": "value_test"}, | ||
Condition: "A", | ||
Data: []*grafana_alerts.GrafanaAlertQuery{&data}, | ||
FolderUID: os.Getenv(envGrafanaFolderUid), | ||
NoDataState: grafana_alerts.NoDataOk, | ||
ExecErrState: grafana_alerts.ErrOK, | ||
OrgID: 1, | ||
RuleGroup: "rule_group_1", | ||
Title: "test_alert", | ||
For: int64(3), | ||
} | ||
|
||
client, err := grafana_alerts.New(apiToken, server.URL) | ||
grafanaAlert, err := client.CreateGrafanaAlertRule(createGrafanaAlert) | ||
``` | ||
|
||
| function | func name | | ||
|---------------------|------------------------------------------------------------------------------------------------------------| | ||
| create alert | `func (c *GrafanaAlertClient) CreateGrafanaAlertRule(payload GrafanaAlertRule) (*GrafanaAlertRule, error)` | | ||
| update alert | `func (c *GrafanaAlertClient) UpdateGrafanaAlertRule(payload GrafanaAlertRule) error` | | ||
| delete alert by uid | `func (c *GrafanaAlertClient) DeleteGrafanaAlertRule(uid string) error` | | ||
| get alert by uid | `func (c *GrafanaAlertClient) GetGrafanaAlertRule(uid string) (*GrafanaAlertRule, error)` | | ||
| list alerts | `func (c *GrafanaAlertClient) ListGrafanaAlertRules() ([]GrafanaAlertRule, error)` | |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package grafana_alerts | ||
|
||
import ( | ||
"fmt" | ||
"github.com/logzio/logzio_terraform_client/client" | ||
"time" | ||
) | ||
|
||
type ExecErrState string | ||
type NoDataState string | ||
|
||
const ( | ||
grafanaAlertServiceEndpoint = "%s/v1/grafana/api/v1/provisioning/alert-rules" | ||
|
||
grafanaAlertResourceName = "grafana alert rule" | ||
|
||
operationCreateGrafanaAlert = "CreateGrafanaAlert" | ||
operationGetGrafanaAlert = "GetGrafanaAlert" | ||
operationUpdateGrafanaAlert = "UpdateGrafanaAlert" | ||
operationDeleteGrafanaAlert = "DeleteGrafanaAlert" | ||
operationListGrafanaAlerts = "ListGrafanaAlerts" | ||
|
||
ErrOK ExecErrState = "OK" | ||
ErrError ExecErrState = "Error" | ||
ErrAlerting ExecErrState = "Alerting" | ||
NoDataOk NoDataState = "OK" | ||
NoData NoDataState = "NoData" | ||
NoDataAlerting NoDataState = "Alerting" | ||
) | ||
|
||
type GrafanaAlertClient struct { | ||
*client.Client | ||
} | ||
|
||
type GrafanaAlertRule struct { | ||
Annotations map[string]string `json:"annotations,omitempty"` | ||
Condition string `json:"condition"` // Required | ||
Data []*GrafanaAlertQuery `json:"data"` // Required | ||
ExecErrState ExecErrState `json:"execErrState"` // Required | ||
FolderUID string `json:"folderUID"` // Required | ||
For int64 `json:"for"` // Required, representing nanoseconds | ||
Id int64 `json:"id,omitempty"` | ||
Labels map[string]string `json:"labels,omitempty"` | ||
NoDataState NoDataState `json:"noDataState"` // Required | ||
OrgID int64 `json:"orgID"` // Required | ||
Provenance string `json:"provenance,omitempty"` | ||
RuleGroup string `json:"ruleGroup"` // Required | ||
Title string `json:"title"` // Required | ||
Uid string `json:"uid,omitempty"` | ||
Updated time.Time `json:"updated"` | ||
IsPaused bool `json:"isPaused"` | ||
} | ||
|
||
type GrafanaAlertQuery struct { | ||
DatasourceUid string `json:"datasourceUid"` | ||
Model interface{} `json:"model"` | ||
QueryType string `json:"queryType"` | ||
RefId string `json:"refId"` | ||
RelativeTimeRange RelativeTimeRangeObj `json:"relativeTimeRange"` | ||
} | ||
|
||
type RelativeTimeRangeObj struct { | ||
From time.Duration `json:"from"` | ||
To time.Duration `json:"to"` | ||
} | ||
|
||
func New(apiToken string, baseUrl string) (*GrafanaAlertClient, error) { | ||
if len(apiToken) == 0 { | ||
return nil, fmt.Errorf("API token not defined") | ||
} | ||
if len(baseUrl) == 0 { | ||
return nil, fmt.Errorf("Base URL not defined") | ||
} | ||
|
||
grafanaAlertClient := &GrafanaAlertClient{ | ||
Client: client.New(apiToken, baseUrl), | ||
} | ||
|
||
return grafanaAlertClient, nil | ||
} | ||
|
||
func validateGrafanaAlertRuleCreateUpdate(payload GrafanaAlertRule, isUpdate bool) error { | ||
if len(payload.Condition) == 0 { | ||
return fmt.Errorf("Field condition must be set!") | ||
} | ||
|
||
if payload.Data == nil || len(payload.Data) == 0 { | ||
return fmt.Errorf("Field data must be set!") | ||
} | ||
|
||
if len(payload.ExecErrState) == 0 { | ||
return fmt.Errorf("Field execErrState must be set!") | ||
} | ||
|
||
if len(payload.FolderUID) == 0 { | ||
return fmt.Errorf("Field folderUID must be set!") | ||
} | ||
|
||
if payload.For == 0 { | ||
return fmt.Errorf("Field for must be set!") | ||
} | ||
|
||
if len(payload.NoDataState) == 0 { | ||
return fmt.Errorf("Field noDataState must be set!") | ||
} | ||
|
||
if len(payload.RuleGroup) == 0 { | ||
return fmt.Errorf("Field ruleGroup must be set!") | ||
} | ||
|
||
if len(payload.Title) == 0 { | ||
return fmt.Errorf("Field title must be set!") | ||
} | ||
|
||
if isUpdate { | ||
if len(payload.Uid) == 0 { | ||
return fmt.Errorf("Field uid must be set when updating a Grafana alert rule!") | ||
} | ||
|
||
} else { | ||
if payload.OrgID == 0 { | ||
return fmt.Errorf("Field orgID must be set!") | ||
} | ||
} | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package grafana_alerts | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
logzio_client "github.com/logzio/logzio_terraform_client" | ||
"net/http" | ||
) | ||
|
||
const ( | ||
createGrafanaAlertServiceUrl = grafanaAlertServiceEndpoint | ||
createGrafanaAlertServiceMethod = http.MethodPost | ||
createGrafanaAlertMethodCreated = http.StatusCreated | ||
createGrafanaAlertStatusNotFound = http.StatusNotFound | ||
) | ||
|
||
func (c *GrafanaAlertClient) CreateGrafanaAlertRule(payload GrafanaAlertRule) (*GrafanaAlertRule, error) { | ||
err := validateGrafanaAlertRuleCreateUpdate(payload, false) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
createGrafanaAlertRuleJson, err := json.Marshal(payload) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
res, err := logzio_client.CallLogzioApi(logzio_client.LogzioApiCallDetails{ | ||
ApiToken: c.ApiToken, | ||
HttpMethod: createGrafanaAlertServiceMethod, | ||
Url: fmt.Sprintf(createGrafanaAlertServiceUrl, c.BaseUrl), | ||
Body: createGrafanaAlertRuleJson, | ||
SuccessCodes: []int{createGrafanaAlertMethodCreated}, | ||
NotFoundCode: createGrafanaAlertStatusNotFound, | ||
ResourceId: nil, | ||
ApiAction: operationCreateGrafanaAlert, | ||
ResourceName: grafanaAlertResourceName, | ||
}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var retVal GrafanaAlertRule | ||
err = json.Unmarshal(res, &retVal) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &retVal, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package grafana_alerts | ||
|
||
import ( | ||
"fmt" | ||
logzio_client "github.com/logzio/logzio_terraform_client" | ||
"net/http" | ||
) | ||
|
||
const ( | ||
deleteGrafanaAlertServiceUrl = grafanaAlertServiceEndpoint + "/%s" | ||
deleteGrafanaAlertServiceMethod = http.MethodDelete | ||
deleteGrafanaAlertServiceSuccess = http.StatusNoContent | ||
// NOTE: the grafana api returns 204 even when you try to delete with a uid that doesn't exist, | ||
// so the following line is just for compatibility with the CallLogzioApi object | ||
deleteGrafanaAlertNotFound = http.StatusNotFound | ||
) | ||
|
||
func (c *GrafanaAlertClient) DeleteGrafanaAlertRule(uid string) error { | ||
if uid == "" { | ||
return fmt.Errorf("uid is empty") | ||
} | ||
_, err := logzio_client.CallLogzioApi(logzio_client.LogzioApiCallDetails{ | ||
ApiToken: c.ApiToken, | ||
HttpMethod: deleteGrafanaAlertServiceMethod, | ||
Url: fmt.Sprintf(deleteGrafanaAlertServiceUrl, c.BaseUrl, uid), | ||
Body: nil, | ||
SuccessCodes: []int{deleteGrafanaAlertServiceSuccess}, | ||
NotFoundCode: deleteGrafanaAlertNotFound, | ||
ResourceId: uid, | ||
ApiAction: operationDeleteGrafanaAlert, | ||
ResourceName: grafanaAlertResourceName, | ||
}) | ||
|
||
return err | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package grafana_alerts | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
logzio_client "github.com/logzio/logzio_terraform_client" | ||
"net/http" | ||
) | ||
|
||
const ( | ||
getGrafanaAlertServiceUrl = grafanaAlertServiceEndpoint + "/%s" | ||
getGrafanaAlertServiceMethod = http.MethodGet | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Value duplication in |
||
getGrafanaAlertServiceSuccess = http.StatusOK | ||
getGrafanaAlertServiceNotFound = http.StatusNotFound | ||
) | ||
|
||
func (c *GrafanaAlertClient) GetGrafanaAlertRule(uid string) (*GrafanaAlertRule, error) { | ||
res, err := logzio_client.CallLogzioApi(logzio_client.LogzioApiCallDetails{ | ||
ApiToken: c.ApiToken, | ||
HttpMethod: getGrafanaAlertServiceMethod, | ||
Url: fmt.Sprintf(getGrafanaAlertServiceUrl, c.BaseUrl, uid), | ||
Body: nil, | ||
SuccessCodes: []int{getGrafanaAlertServiceSuccess}, | ||
NotFoundCode: getGrafanaAlertServiceNotFound, | ||
ResourceId: uid, | ||
ApiAction: operationGetGrafanaAlert, | ||
ResourceName: grafanaAlertResourceName, | ||
}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var grafanaAlertRule GrafanaAlertRule | ||
err = json.Unmarshal(res, &grafanaAlertRule) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &grafanaAlertRule, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package grafana_alerts | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
logzio_client "github.com/logzio/logzio_terraform_client" | ||
"net/http" | ||
) | ||
|
||
const ( | ||
listGrafanaAlertServiceUrl = grafanaAlertServiceEndpoint | ||
listGrafanaAlertServiceMethod = http.MethodGet | ||
listGrafanaAlertServiceSuccess = http.StatusOK | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Value duplication in |
||
listGrafanaAlertStatusNotFound = http.StatusNotFound | ||
) | ||
|
||
func (c *GrafanaAlertClient) ListGrafanaAlertRules() ([]GrafanaAlertRule, error) { | ||
res, err := logzio_client.CallLogzioApi(logzio_client.LogzioApiCallDetails{ | ||
ApiToken: c.ApiToken, | ||
HttpMethod: listGrafanaAlertServiceMethod, | ||
Url: fmt.Sprintf(listGrafanaAlertServiceUrl, c.BaseUrl), | ||
Body: nil, | ||
SuccessCodes: []int{listGrafanaAlertServiceSuccess}, | ||
NotFoundCode: listGrafanaAlertStatusNotFound, | ||
ResourceId: nil, | ||
ApiAction: operationListGrafanaAlerts, | ||
ResourceName: grafanaAlertResourceName, | ||
}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var alertRules []GrafanaAlertRule | ||
err = json.Unmarshal(res, &alertRules) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return alertRules, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Value duplication in
delete
get
list
crate
update
may be worth unifying those. Not critical for your consideration :)