Skip to content

Commit

Permalink
docs: update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdh committed Nov 3, 2022
1 parent dd6b493 commit 6f7cd8b
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 19 deletions.
14 changes: 7 additions & 7 deletions docs/docs/concepts/plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Siren decouples `provider` and `receiver` as a plugin. The purpose is to ease th

## Provider

Provider responsibility is to accept incoming rules configuration from Siren and send alerts to the designated Siren Hook API. Provider plugin needs to fulfill some interfaces. More detail about interfaces can be found in [contribution](../contribute/provider.md) page. Supported providers are:
Provider responsibility is to accept incoming rules configuration from Siren and send alerts to the designated Siren's Hook API. Provider plugin needs to fulfill some interfaces. More detail about interfaces can be found in [contribution](../contribute/provider.md) page. Supported providers are:

- [Cortexmetrics](https://cortexmetrics.io/)

Expand All @@ -16,21 +16,21 @@ Siren provider plugin could have an `AppConfig`:

```go
type ProviderPlugin interface {
// AlertTransformer
TransformToAlerts(ctx context.Context, providerID uint64, body map[string]interface{}) ([]*alert.Alert, int, error)

// ConfigSyncer
SyncRuntimeConfig(ctx context.Context, namespaceURN string, prov provider.Provider) error

// RuleUploader
UpsertRule(ctx context.Context, namespaceURN string, prov provider.Provider, rl *rule.Rule, templateToUpdate *template.Template) error
}
```
**AlertTransformer** interface is being used by alert service to transform incoming alert body in Siren's Hook API to list of *alert.Alert

ConfigSyncer interface is being used by namespace service to synchronize runtime-provider configs for a specific namespace. In cortex, it is being used to sync alertmanager config.

RuleUploader interface is being used to upsert rules to the provider. It support templatization of rules.
**ConfigSyncer** interface is being used by namespace service to synchronize runtime-provider configs for a specific namespace. In cortex, it is being used to sync alertmanager config.

//TODO
### Hook API
Beside implementing a plugin interface, you will need to create a
**RuleUploader** interface is being used to upsert rules to the provider. It support templatization of rules.

## Receiver

Expand Down
19 changes: 10 additions & 9 deletions docs/docs/contribute/provider.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# Add a New Provider Plugin

Provider plugin is being used to update rule configurations to the provider and setup some runtime provider configuration config if any.
Provider plugin is being used to update rule configurations to the provider, setup some runtime provider configuration config if any, and transform incoming alert data in Siren's Hook API to list of *alert.Alert model.

## Defining Configs
## Requirements

If there is a need to have a generic config for the provider that is being loaded during start-up, you could add a new `AppConfig` and assign the config to `plugins/providers/config.go` to expose it to the app-level config. Siren will recognize and read the config when starting up.
1. You need to find a way for the provider to send alert to Siren's hook API `{version}/alerts/{provider_type}/{provider_id}`. You need to implement a `TransformToAlerts` method to parse and transform the body of incoming request received by Siren's hook API to the list of Siren's *alert.Alert model.

2. You need to implement `UpsertRules` method to push all rules changes to the provider everytime a rule is upserted.

3. If provider supports setting the configuration dynamically and if for each provider's namespace there is a possibility to have different config (e.g. for multitenancy purpose like CortexMetrics), you could implement `SyncRuntimeConfig` function to push all configurations changes to the provider everytime a new namespace is created or an existing namespace is updated.

## Implementable Methods

There are only 2 methods that are possible to be implemented for provider plugin.
1. `SyncRuntimeConfig`
- Only implement this if there is a specific runtime plugin need to be set for every unique namespaces. This is usually helpful for multi-tenant use cases like Cortexmetrics.
2. `UpsertRules`
- You will need to implement this methods to synchronized alerting rules between Siren and Providers.
## Defining Configs

If there is a need to have a generic config for the provider that is being loaded during start-up, you could add a new `AppConfig` and assign the config to `plugins/providers/config.go` to expose it to the app-level config. Siren will recognize and read the config when starting up.

## Integrate New Plugin with Siren

Expand Down
28 changes: 27 additions & 1 deletion docs/docs/contribute/receiver.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
# Add a New Receiver Plugin

More details about the concept of receiver plugin can be found [here](../concepts/plugin.md#receiver). In this part, we will show how to add a new receiver plugin to send notifications to a local `file`.
More details about the concept of receiver plugin can be found [here](../concepts/plugin.md#receiver).

## Requirements

1. You need to figure out whether there is a need to do pre-processing of receiver configuration before storing to the database or enqueueing to the queue. For some receivers, there is a need to do encryption or validation in pre-processing step, in this case you could implement `PreHookDBTransformConfigs` to transform and validate configurations before storing it to the DB and `PreHookQueueTransformConfigs` to transform and validate configurations before storing it to the queue.

2. If there is a need to transform back receiver's configurations (e.g. decrypting config), you need to implement `PostHookDBTransformConfigs` or `PostHookQueueTransformConfigs` to transform the config back for processing.

3. You need to implement `Send` method to send notification message to the external notification vendor.

## Defining Configs

- If there is a need to have a generic config for the receiver that is being loaded during start-up, you could add a new `AppConfig` and assign the config to `plugins/receivers/config.go` to expose it to the app-level config. Siren will recognize and read the config when starting up.
- It is also possible for a receiver to have different config in the receiver and subscription. For example, slack has a dedicated config called `channel_name` in subscription to send notification only to a specific channel. In this case you need to define separate configurations: `ReceiverConfig` and `SubscriptionConfig`.
- You need to implement `NotificationConfig` which is a placeholder to combine `ReceiverConfig` and `SubscriptionConfig` (if any). Therefore `NotificationConfig` should just embed `ReceiverConfig` and `SubscriptionConfig` (if needed). You might also want to add more function to validate and transform the config to `map[string]interface{}`.


## Integrate New Plugin with Siren

1. Define and add your new type of plugin inside `core/providers/type.go`.
2. Initialize your plugin receiver service and notification service and add to the `ConfigResolver` and `Notifier` registries map in `cli/deps`.
3. To make sure notification handler and dlq handler process your new type, don't forget to add your new receiver type in notification message & dlq handler config or make it default to support all receiver types.


# Sample: Add a new `file` receiver

In this part, we will show how to add a new receiver plugin to send notifications to a local `file`.

## Defining Configs

Expand Down
3 changes: 2 additions & 1 deletion plugins/providers/cortex/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func NewPluginService(logger log.Logger, appConfig AppConfig, opts ...ServiceOpt
return s
}

// TransformToAlerts is a function to transform alert body in hook API to []*alert.Alert
func (s *PluginService) TransformToAlerts(ctx context.Context, providerID uint64, body map[string]interface{}) ([]*alert.Alert, int, error) {
var groupAlert = &GroupAlert{}
if err := mapstructure.Decode(body, groupAlert); err != nil {
Expand Down Expand Up @@ -118,7 +119,7 @@ func (s *PluginService) TransformToAlerts(ctx context.Context, providerID uint64
return alerts, firingLen, nil
}

// SyncRuntimeConfig synchronize runtime configuration of provider
// SyncRuntimeConfig synchronizes runtime configuration of provider
func (s *PluginService) SyncRuntimeConfig(ctx context.Context, namespaceURN string, prov provider.Provider) error {
if s.appConfig.WebhookBaseAPI == "" {
return errors.New("Cortex webhook base api string in config cannot be empty")
Expand Down
2 changes: 1 addition & 1 deletion test/e2e_test/cortex_alerting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (s *CortexAlertingTestSuite) TestSendingNotification() {
body, err := io.ReadAll(r.Body)
s.Assert().NoError(err)

expectedBody := `{"environment":"integration","generatorUrl":"","groupKey":"{}:{severity=\"WARNING\"}","metricName":"test_alert","metricValue":"1","numAlertsFiring":1,"resource":"test_alert","routing_method":"subscribers","service":"some-service","severity":"WARNING","status":"firing","team":"odpf","template":"alert_test"}`
expectedBody := `{"environment":"integration","generatorUrl":"","groupKey":"{}:{severity=\"WARNING\"}","id":"cortex-39255dc96d0f642c","metricName":"test_alert","metricValue":"1","numAlertsFiring":1,"resource":"test_alert","routing_method":"subscribers","service":"some-service","severity":"WARNING","status":"firing","team":"odpf","template":"alert_test"}`
s.Assert().Equal(expectedBody, string(body))
close(waitChan)
}))
Expand Down

0 comments on commit 6f7cd8b

Please sign in to comment.