-
Notifications
You must be signed in to change notification settings - Fork 97
ACLP Alerting go SDK #824
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
base: main
Are you sure you want to change the base?
ACLP Alerting go SDK #824
Changes from all commits
3001996
625296b
926f2a0
d72eefa
18272f3
423915d
e933ea7
e5b6ef1
e836182
5e17334
a066c29
51b93c7
da18794
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,64 @@ | ||
| package linodego | ||
|
|
||
| import ( | ||
| "context" | ||
| ) | ||
|
|
||
| // AlertChannelEnvelope represents a single alert channel entry returned inside alert definition | ||
| type AlertChannelEnvelope struct { | ||
| ID int `json:"id"` | ||
| Label string `json:"label"` | ||
| Type string `json:"type"` | ||
| URL string `json:"url"` | ||
| } | ||
|
|
||
| // AlertChannel represents a Monitor Channel object. | ||
| type AlertChannel struct { | ||
| ID int `json:"id"` | ||
| Label string `json:"label"` | ||
| ChannelType string `json:"channel_type"` | ||
| Content ChannelContent `json:"content"` | ||
| Created string `json:"created"` | ||
| CreatedBy string `json:"created_by"` | ||
| Updated string `json:"updated"` | ||
| UpdatedBy string `json:"updated_by"` | ||
| } | ||
|
|
||
| // AlertChannelCreateOptions are the options used to create a new Monitor Channel. | ||
| type AlertChannelCreateOptions struct { | ||
| Label string `json:"label"` | ||
| Type string `json:"type"` | ||
| Details AlertChannelDetailOptions `json:"details"` | ||
| } | ||
|
|
||
| // AlertChannelDetailOptions are the options used to create the details of a new Monitor Channel. | ||
| type AlertChannelDetailOptions struct { | ||
| To string `json:"to,omitempty"` | ||
| } | ||
|
|
||
| // AlertingChannelCreateOptions are the options used to create a new Monitor Channel. | ||
| // | ||
| // Deprecated: AlertChannelCreateOptions should be used in all new implementations. | ||
| type AlertingChannelCreateOptions = AlertChannelCreateOptions | ||
|
|
||
| type EmailChannelContent struct { | ||
| EmailAddresses []string `json:"email_addresses"` | ||
| } | ||
|
|
||
| // ChannelContent represents the content block for an AlertChannel, which varies by channel type. | ||
| type ChannelContent struct { | ||
| Email *EmailChannelContent `json:"email,omitempty"` | ||
| // Other channel types like 'webhook', 'slack' could be added here as optional fields. | ||
| } | ||
|
|
||
| // ListAlertChannels gets a paginated list of Alert Channels. | ||
| func (c *Client) ListAlertChannels(ctx context.Context, opts *ListOptions) ([]AlertChannel, error) { | ||
| endpoint := formatAPIPath("monitor/alert-channels") | ||
| return getPaginatedResults[AlertChannel](ctx, c, endpoint, opts) | ||
| } | ||
|
|
||
| // GetAlertChannel gets an Alert Channel by ID. | ||
| func (c *Client) GetAlertChannel(ctx context.Context, channelID int) (*AlertChannel, error) { | ||
| e := formatAPIPath("monitor/alert-channels/%d", channelID) | ||
| return doGETRequest[AlertChannel](ctx, c, e) | ||
| } | ||
|
Comment on lines
+61
to
+64
Contributor
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. Just curious, is getting a single alert channel available now? Didn't see it in the api doc though |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,4 @@ require ( | |
|
|
||
| go 1.24.0 | ||
|
|
||
| toolchain go1.25.1 | ||
|
|
||
|
Comment on lines
-23
to
-24
Contributor
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. Can you revert the change to go mod? should not be necessary here |
||
| retract v1.0.0 // Accidental branch push | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,230 @@ | ||
| package linodego | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "time" | ||
|
|
||
| "github.com/linode/linodego/internal/parseabletime" | ||
| ) | ||
|
|
||
| // AlertDefinition represents an ACLP Alert Definition object | ||
| type AlertDefinition struct { | ||
| ID int `json:"id"` | ||
| Label string `json:"label"` | ||
| Severity int `json:"severity"` | ||
| Type string `json:"type"` | ||
| ServiceType string `json:"service_type"` | ||
| Status string `json:"status"` | ||
| HasMoreResources bool `json:"has_more_resources"` | ||
| Rule *Rule `json:"rule"` | ||
|
Contributor
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. I don't think this field |
||
| RuleCriteria *RuleCriteria `json:"rule_criteria"` | ||
| TriggerConditions *TriggerConditions `json:"trigger_conditions"` | ||
| AlertChannels []AlertChannelEnvelope `json:"alert_channels"` | ||
| Created *time.Time `json:"-"` | ||
| Updated *time.Time `json:"-"` | ||
| UpdatedBy string `json:"updated_by"` | ||
| CreatedBy string `json:"created_by"` | ||
| EntityIDs []string `json:"entity_ids"` | ||
|
Contributor
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. Judging from the api doc, the entity_ids seems could be any type: You should build them as |
||
| Description string `json:"description"` | ||
| Class string `json:"class"` | ||
| } | ||
|
|
||
| // Backwards-compatible alias | ||
|
|
||
| // MonitorAlertDefinition represents an ACLP Alert Definition object | ||
| // | ||
| // Deprecated: AlertDefinition should be used in all new implementations. | ||
| type MonitorAlertDefinition = AlertDefinition | ||
|
|
||
| // TriggerConditions represents the trigger conditions for an alert. | ||
| type TriggerConditions struct { | ||
| CriteriaCondition string `json:"criteria_condition,omitempty"` | ||
| EvaluationPeriodSeconds int `json:"evaluation_period_seconds,omitempty"` | ||
| PollingIntervalSeconds int `json:"polling_interval_seconds,omitempty"` | ||
| TriggerOccurrences int `json:"trigger_occurrences,omitempty"` | ||
| } | ||
|
|
||
| // RuleCriteria represents the rule criteria for an alert. | ||
| type RuleCriteria struct { | ||
| Rules []Rule `json:"rules,omitempty"` | ||
| } | ||
|
|
||
| // Rule represents a single rule for an alert. | ||
| type Rule struct { | ||
|
Contributor
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. The Rule object is not the same as it is in the create options. i.e. |
||
| AggregateFunction string `json:"aggregate_function,omitempty"` | ||
| DimensionFilters []DimensionFilter `json:"dimension_filters,omitempty"` | ||
| Label string `json:"label,omitempty"` | ||
| Metric string `json:"metric,omitempty"` | ||
| Operator string `json:"operator,omitempty"` | ||
| Threshold *float64 `json:"threshold,omitempty"` | ||
| Unit *string `json:"unit,omitempty"` | ||
|
Comment on lines
+60
to
+61
Contributor
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. Just curious why is is necessary to use pointer for these two fields? |
||
| } | ||
|
|
||
| // DimensionFilter represents a single dimension filter used inside a Rule. | ||
| type DimensionFilter struct { | ||
| DimensionLabel string `json:"dimension_label"` | ||
| Label string `json:"label"` | ||
|
Contributor
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. I find |
||
| Operator string `json:"operator"` | ||
| Value any `json:"value"` | ||
| } | ||
|
|
||
| // AlertType represents the type of alert: "user" or "system" | ||
| type AlertType string | ||
|
|
||
| const ( | ||
| AlertTypeUser AlertType = "user" | ||
| AlertTypeSystem AlertType = "system" | ||
| ) | ||
|
|
||
| // Severity represents the severity level of an alert. | ||
| // 0 = Severe, 1 = Medium, 2 = Low, 3 = Info | ||
| type Severity int | ||
|
|
||
| const ( | ||
| SeveritySevere Severity = 0 | ||
| SeverityMedium Severity = 1 | ||
| SeverityLow Severity = 2 | ||
| SeverityInfo Severity = 3 | ||
| ) | ||
|
|
||
| // CriteriaCondition represents supported criteria conditions | ||
| type CriteriaCondition string | ||
|
|
||
| const ( | ||
| CriteriaConditionAll CriteriaCondition = "ALL" | ||
| ) | ||
|
|
||
| // AlertDefinitionCreateOptions are the options used to create a new alert definition. | ||
| type AlertDefinitionCreateOptions struct { | ||
| ServiceType string `json:"service_type"` // mandatory | ||
|
Contributor
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. You don't need to include this field here since it's a path param. |
||
| Label string `json:"label"` // mandatory | ||
| Severity int `json:"severity"` // mandatory | ||
| ChannelIDs []int `json:"channel_ids"` // mandatory | ||
| RuleCriteria *RuleCriteria `json:"rule_criteria,omitempty"` // optional | ||
| TriggerConditions *TriggerConditions `json:"trigger_conditions,omitempty"` // optional | ||
| EntityIDs []string `json:"entity_ids,omitempty"` // optional | ||
| Description string `json:"description,omitempty"` // optional | ||
| } | ||
|
|
||
| // AlertDefinitionUpdateOptions are the options used to update an alert definition. | ||
| type AlertDefinitionUpdateOptions struct { | ||
| ServiceType string `json:"service_type"` // mandatory, must not be empty | ||
| AlertID int `json:"alert_id"` // mandatory, must not be zero | ||
|
Comment on lines
+112
to
+113
Contributor
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. These two path param can be removed from options as well |
||
| Label string `json:"label,omitempty"` // optional | ||
| Severity int `json:"severity,omitempty"` // optional, should be int to match AlertDefinition | ||
| Description string `json:"description,omitempty"` // optional | ||
| RuleCriteria *RuleCriteria `json:"rule_criteria,omitempty"` // optional | ||
| TriggerConditions *TriggerConditions `json:"trigger_conditions,omitempty"` // optional | ||
| EntityIDs []string `json:"entity_ids,omitempty"` // optional | ||
| ChannelIDs []int `json:"channel_ids,omitempty"` // optional | ||
| } | ||
|
|
||
| // UnmarshalJSON implements the json.Unmarshaler interface | ||
| func (i *AlertDefinition) UnmarshalJSON(b []byte) error { | ||
| type Mask AlertDefinition | ||
|
|
||
| p := struct { | ||
| *Mask | ||
|
|
||
| Created *parseabletime.ParseableTime `json:"created"` | ||
| Updated *parseabletime.ParseableTime `json:"updated"` | ||
| }{ | ||
| Mask: (*Mask)(i), | ||
| } | ||
|
|
||
| if err := json.Unmarshal(b, &p); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| i.Created = (*time.Time)(p.Created) | ||
| i.Updated = (*time.Time)(p.Updated) | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // ListMonitorAlertDefinitions gets a paginated list of ACLP Monitor Alert Definitions. | ||
| func (c *Client) ListMonitorAlertDefinitions( | ||
| ctx context.Context, | ||
| serviceType string, | ||
| opts *ListOptions, | ||
| ) ([]AlertDefinition, error) { | ||
| var endpoint string | ||
| if serviceType != "" { | ||
| endpoint = formatAPIPath("monitor/services/%s/alert-definitions", serviceType) | ||
| } else { | ||
| endpoint = formatAPIPath("monitor/alert-definitions") | ||
| } | ||
|
Comment on lines
+153
to
+157
Contributor
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. You probably need to separate these two endpoints into two functions in linodego. Because go can't take optional parameters. |
||
|
|
||
| return getPaginatedResults[AlertDefinition](ctx, c, endpoint, opts) | ||
| } | ||
|
|
||
| // GetMonitorAlertDefinition gets an ACLP Monitor Alert Definition. | ||
| func (c *Client) GetMonitorAlertDefinition( | ||
| ctx context.Context, | ||
| serviceType string, | ||
| alertID int, | ||
| ) (*MonitorAlertDefinition, error) { | ||
| e := formatAPIPath("monitor/services/%s/alert-definitions/%d", serviceType, alertID) | ||
| return doGETRequest[AlertDefinition](ctx, c, e) | ||
| } | ||
|
|
||
| // CreateMonitorAlertDefinition creates an ACLP Monitor Alert Definition. | ||
| func (c *Client) CreateMonitorAlertDefinition( | ||
| ctx context.Context, | ||
| serviceType string, | ||
| opts AlertDefinitionCreateOptions, | ||
| ) (*MonitorAlertDefinition, error) { | ||
| e := formatAPIPath("monitor/services/%s/alert-definitions", serviceType) | ||
| return doPOSTRequest[AlertDefinition](ctx, c, e, opts) | ||
| } | ||
|
|
||
| // CreateMonitorAlertDefinitionWithIdempotency creates an ACLP Monitor Alert Definition | ||
| // and optionally sends an Idempotency-Key header to make the request idempotent. | ||
| func (c *Client) CreateMonitorAlertDefinitionWithIdempotency( | ||
| ctx context.Context, | ||
| serviceType string, | ||
| opts AlertDefinitionCreateOptions, | ||
| idempotencyKey string, | ||
| ) (*MonitorAlertDefinition, error) { | ||
| e := formatAPIPath("monitor/services/%s/alert-definitions", serviceType) | ||
|
|
||
| var result AlertDefinition | ||
|
|
||
| req := c.R(ctx).SetResult(&result) | ||
|
|
||
| if idempotencyKey != "" { | ||
| req.SetHeader("Idempotency-Key", idempotencyKey) | ||
| } | ||
|
|
||
| body, err := json.Marshal(opts) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| req.SetBody(string(body)) | ||
|
|
||
| r, err := coupleAPIErrors(req.Post(e)) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return r.Result().(*AlertDefinition), nil | ||
| } | ||
|
|
||
| // UpdateMonitorAlertDefinition updates an ACLP Monitor Alert Definition. | ||
| func (c *Client) UpdateMonitorAlertDefinition( | ||
| ctx context.Context, | ||
| serviceType string, | ||
| alertID int, | ||
| opts AlertDefinitionUpdateOptions, | ||
| ) (*AlertDefinition, error) { | ||
| e := formatAPIPath("monitor/services/%s/alert-definitions/%d", serviceType, alertID) | ||
| return doPUTRequest[AlertDefinition](ctx, c, e, opts) | ||
| } | ||
|
|
||
| // DeleteMonitorAlertDefinition deletes an ACLP Monitor Alert Definition. | ||
| func (c *Client) DeleteMonitorAlertDefinition(ctx context.Context, serviceType string, alertID int) error { | ||
| e := formatAPIPath("monitor/services/%s/alert-definitions/%d", serviceType, alertID) | ||
| return doDELETERequest(ctx, c, e) | ||
| } | ||
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.
It seems only GET endpoints are supported currently. Can you remove the CreateOptions?