diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e225959f..962ba302 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,4 +13,17 @@ jobs: with: node-version: '20.11.1' - - run: make fmt-check + - name: Run format check + run: make fmt-check + continue-on-error: true + id: fmt-check + + - name: Run formatter and show diff if check failed + if: steps.fmt-check.outcome == 'failure' + run: | + make fmt + git diff + + - name: Exit with error if format check failed + if: steps.fmt-check.outcome == 'failure' + run: exit 1 diff --git a/Makefile b/Makefile index dfed4bd6..208904cc 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ fmt: .PHONY: fmt-check fmt-check: - npx prettier --check "**/*.md" + npx prettier --check --log-level=debug "**/*.md" .PHONY: sync: diff --git a/canary-checker/docs/windows.md b/canary-checker/docs/windows.md index 97ff8f57..bfeabc13 100644 --- a/canary-checker/docs/windows.md +++ b/canary-checker/docs/windows.md @@ -20,7 +20,7 @@ To run Canary Checker on windows please ensure the following ## 2. Downloading required files -You only need the powershell script below(assuming internet connectivity), place it in the folder you wish to install Canary Checker in. +You only need the powershell script below(assuming internet connectivity). Place it in the folder you wish to install Canary Checker in. ```powershell [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 diff --git a/common/src/components/Fields.jsx b/common/src/components/Fields.jsx index 2d9da03a..b871b632 100644 --- a/common/src/components/Fields.jsx +++ b/common/src/components/Fields.jsx @@ -28,8 +28,8 @@ const schemes = { "notificationconnection": "[Connection](/reference/connections)", "notificationproperties": "[map[string]string](/reference/notifications#properties)", } -export default function Fields({ common = [], rows = [], oneOf, anyOf, connection }) { +export default function Fields({ common = [], rows = [], oneOf, anyOf, connection, withTemplates }) { const { siteConfig, siteMetadata } = useDocusaurusContext(); const oss = siteConfig.customFields.oss; @@ -292,55 +292,85 @@ export default function Fields({ common = [], rows = [], oneOf, anyOf, connectio return ( <> -
Field | Description | Scheme | + {withTemplates &&Template Env | }|
---|---|---|---|---|
- {row.field}{row.required ? "*" : ""}
+
+ {row.field}
+ {row.required ? '*' : ''}
+
|
-
- {row.anyOf &&
- {row.anyOf.join(' | ')}
- }
- {!row.anyOf && row.scheme &&
+ |
+
+ {row.anyOf && {row.anyOf.join(' | ')} }
+ {!row.anyOf && row.scheme && (
|
+ {withTemplates && (
+
+ {row.templateEnv &&
+ row.templateEnv.map((v) => (
+
+
+ |
+ )}
-You must specify
+{anyOf[0]}
and/or{anyOf[1]}
+- } - { - oneOf && oneOf.length == 2 && -+ You must specify
{anyOf[0]}
and/or{' '} +{anyOf[1]}
+
-You must specify
+ )} + {oneOf && oneOf.length == 2 && ( +{oneOf[0]}
or{oneOf[1]}
but not both+- } - { - oneOf && oneOf.length == 3 && -+ You must specify
{oneOf[0]}
or{oneOf[1]}
{' '} + but not both +-You must specify one of
+ )} + {oneOf && oneOf.length == 3 && ( +{oneOf[0]}
,{oneOf[1]}
or{oneOf[2]}
+- } + )} > ) } diff --git a/mission-control/docs/notifications/concepts/index.md b/mission-control/docs/notifications/concepts/index.md new file mode 100644 index 00000000..2b847611 --- /dev/null +++ b/mission-control/docs/notifications/concepts/index.md @@ -0,0 +1,8 @@ +--- +title: Concepts +sidebar_position: 2 +--- + +import DocCardList from '@theme/DocCardList'; + ++ You must specify one of
{oneOf[0]}
,{' '} +{oneOf[1]}
or{oneOf[2]}
+diff --git a/mission-control/docs/notifications/concepts/rate-limiting.mdx b/mission-control/docs/notifications/concepts/rate-limiting.mdx new file mode 100644 index 00000000..7c3bfda6 --- /dev/null +++ b/mission-control/docs/notifications/concepts/rate-limiting.mdx @@ -0,0 +1,40 @@ +--- +title: Rate Limiting +--- + +To prevent overwhelming users with excessive notifications, Mission Control implements a rate limiting mechanism. + +We use a sliding window rate limiter that restricts the total number of notifications sent within a specified time period. + +:::info +The rate limit is applied individually to each notification. +::: + +:::caution Rate Limited Notifications +When a notification exceeds the rate limit, it is dropped and not delivered to the user. +::: + +## Default Configuration + +The following table outlines the default rate limiting parameters: + +| Property | Value | +|----------------------------------|----------| +| Maximum number of notifications allowed per window | 50 | +| Time period for the sliding window | 4 hours | + +## Customizing Rate Limiting Parameters + +You can override the default settings by adjusting the following properties: + +- `notifications.max.count`: Sets the maximum number of notifications allowed within the window +- `notifications.max.window`: Defines the duration of the sliding window (in hours) + +### Example Configuration + +To allow a maximum of 100 notifications in a 6 hour window: + +``` +notifications.max.count=100 +notifications.max.window=6h +``` diff --git a/mission-control/docs/notifications/concepts/repeat-interval.mdx b/mission-control/docs/notifications/concepts/repeat-interval.mdx new file mode 100644 index 00000000..225eb453 --- /dev/null +++ b/mission-control/docs/notifications/concepts/repeat-interval.mdx @@ -0,0 +1,61 @@ +--- +title: Repeat Interval +--- + +The repeat interval determines the duration between subsequent notifications after an initial successful delivery. + +```yaml title="deployment-failed.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: config-updates + namespace: default +spec: + events: + - config.healthy + - config.unhealthy + - config.warning + - config.unknown + filter: config.type == "Kubernetes::Deployment" + to: + email: alerts@acme.com + repeatInterval: 2h +``` + +The above notification sends at max 1 email notification in a moving 2 hour window. + +## Repeat Group + +By default, the repeat interval applies to any notification sent for the given notification. + +In the example above, if a notification is sent for a `config.healthy` event and then a new notification is to be sent +for a `config.unhealthy` event, then the notification is dropped due to the repeat interval. + +With grouping, you can apply the repeat interval per source event & per resource ID. + +- `source_event` +- `resource_id` + +```yaml title="deployment-updates.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: config-updates + namespace: default +spec: + events: + - config.healthy + - config.unhealthy + - config.warning + - config.unknown + filter: config.type == "Kubernetes::Deployment" + to: + email: alerts@acme.com + repeatInterval: 2h + // highlight-start + repeatGroup: + - source_event + // highlight-end +``` + +With this change, you'll now receive at max 4 notifications for each source event. \ No newline at end of file diff --git a/mission-control/docs/notifications/events/components.md b/mission-control/docs/notifications/events/components.md deleted file mode 100644 index f7113008..00000000 --- a/mission-control/docs/notifications/events/components.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Components -description: Events that fire on topology/component changes ---- - -Component status updates emit the following events - -- `component.healthy` -- `component.unhealthy` -- `component.warning` -- `component.unknown` - -The default notification template used is: -_ **Title:** `Component {{.component.name}} is {{.component.health}}` -_ **Body:** - -``` -### Labels: -{{range $k, $v := .component.labels}}**{{$k}}**: {{$v}} -{{end}} -[Reference]({{.permalink}}) -``` - -Sample notification: - -```yaml title="notification.yaml" -apiVersion: mission-control.flanksource.com/v1 -kind: Notification -metadata: - name: web-api-component-alert - namespace: default -spec: - events: - - component.unhealthy - filter: component.type == 'WebAPI' - title: WebAPI {{.component.name}} failing - body: | - ## Component Failed - Status: {{.component.status}} | {{.component.status_reason}} - Last updated: {{.component.updated_at}} - to: - email: alerts@acme.com -``` - -The notification title and body can be changed using the variables below: - -## Variables - -| Field | Description | Schema | Optional | -| ----------- | ----------------------------- | ------------------------- | -------- | -| `component` | The component object | [`Component`](#component) | | -| `agent` | Agent details (if applicable) | [`Agent`](#agent) | `true` | -| `permalink` | A link to the health check | `string` | | - -### Component - -| Field | Description | Schema | Optional | -| ----------------- | -------------------------------------------- | ------------------- | -------- | -| `id` | The id of the component | `uuid` | | -| `description` | The description of the component | `string` | | -| `external_id` | The external id of the component | `string` | | -| `hidden` | Whether the component is hidden | `bool` | | -| `labels` | The labels of the component | `map[string]string` | `true` | -| `name` | The name of the component | `string` | | -| `namespace` | The namespace of the component | `string` | | -| `parent_id` | The id of the parent component | `uuid` | `true` | -| `properties` | The properties of the component | `map[string]string` | `true` | -| `silenced` | Whether the component is silenced | `bool` | | -| `status_reason` | The status reason of the component | `string` | | -| `status` | The status of the component | `string` | | -| `summary` | The summary of the component | `map[string]string` | `true` | -| `text` | The text of the component | `string` | | -| `topology_type` | The type of the topology | `string` | | -| `type` | The type of the component | `string` | | -| `cost_per_minute` | The cost per minute of the component | `float64` | | -| `cost_total_1d` | The cost total 1d of the component | `float64` | | -| `cost_total_7d` | The cost total 7d of the component | `float64` | | -| `cost_total_30d` | The cost total 30d of the component | `float64` | | -| `created_by` | Id of the person that created this component | `uuid` | | -| `created_at` | Created timestamp | `time.Time` | | -| `updated_at` | Updated timestamp | `time.Time` | | -| `deleted_at` | Deleted timestamp | `time.Time` | `true` | - -### Agent - -| Field | Description | Schema | Optional | -| ------------- | ------------------------------ | -------- | -------- | -| `id` | The id of the agent | `uuid` | | -| `name` | The name of the agent | `string` | | -| `description` | Short description of the agent | `string` | | diff --git a/mission-control/docs/notifications/events/components.mdx b/mission-control/docs/notifications/events/components.mdx new file mode 100644 index 00000000..bb0f6aea --- /dev/null +++ b/mission-control/docs/notifications/events/components.mdx @@ -0,0 +1,62 @@ +--- +title: Components +description: Events that fire on topology/component changes +--- + +import { ComponentHealthEnv, AgentEnv, ComponentEnv } from "../../reference/notifications/_env_vars.mdx" + +Components updates emit the following events when its health changes + +- `component.healthy` +- `component.unhealthy` +- `component.warning` +- `component.unknown` + +```yaml title="unhelthy-component-notification.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: web-api-component-alert + namespace: default +spec: + events: + - component.unhealthy + filter: component.type == 'WebAPI' + title: WebAPI {{.component.name}} failing + body: | + ## Component Failed + Status: {{.component.status}} | {{.component.status_reason}} + Last updated: {{.component.updated_at}} + to: + email: alerts@acme.com +``` + +![](./slack-notification-component.png) + +## Default Templates + +The default notification template used is: + +### Title + +``` +{{ if ne channel "slack"}}Component {{.component.name}} is {{.component.health}}{{end}} +``` + +### Template + +```txt file=../../../modules/mission-control/notification/templates/component.health + +``` + +## Template Variables + +The notification title and body can be changed using the variables below: + + +### Component + + + +### Agent + \ No newline at end of file diff --git a/mission-control/docs/notifications/events/configs.md b/mission-control/docs/notifications/events/configs.md deleted file mode 100644 index 9e4e073d..00000000 --- a/mission-control/docs/notifications/events/configs.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Configs -description: Events that fire on config changes and health ---- - -Configs emit events when their health changes or when they are created, modified, or removed. - -**Health events** - -- `config.healthy` -- `config.unhealthy` -- `config.warning` -- `config.unknown` - -The default notification template for health events is: - -- **Title:** `{{.config.type}} {{.config.name}} is {{.config.health}}` -- **Body:** - - ``` - ### Labels: - {{range $k, $v := .config.labels}}**{{$k}}**: {{$v}} - {{end}} - [Reference]({{.permalink}}) - ``` - -**State events** - -- `config.created` -- `config.updated` -- `config.deleted` - -The default notification template for state events is: - -- **Title:** `{{.config.type}} {{.config.name}} was [created/updated/deleted]` -- **Body:** - - ``` - ### Labels: - {{range $k, $v := .config.labels}}**{{$k}}**: {{$v}} - {{end}} - [Reference]({{.permalink}}) - ``` - -Sample notification: - -```yaml title="notification.yaml" -apiVersion: mission-control.flanksource.com/v1 -kind: Notification -metadata: - name: ec2-instance-create-alert - namespace: default -spec: - events: - - config.created - filter: config.type == 'AWS::EC2::Instance' - title: New EC2 instance {{.config.name}} created - body: | - Region: {{.config.tags['region']}} - Zone: {{.config.tags['zone']}} - Account: {{.config.tags['account']}} - to: - email: alerts@acme.com -``` - -## Variables - -| Field | Description | Schema | nullable | -| ----------- | ----------------------------- | ------------------- | -------- | -| `config` | The config object | [`Config`](#config) | | -| `agent` | Agent details (if applicable) | [`Agent`](#agent) | `true` | -| `permalink` | A link to the config item | `string` | | - -### Config - -| Field | Description | Schema | nullable | -| --------------- | -------------------------------- | --------------- | -------- | -| `id` | ID of the config item | `uuid` | | -| `agent_id` | ID of the agent | `uuid` | `true` | -| `config_class` | Class of the config item | `string` | | -| `config` | Configuration | `string` | `true` | -| `created_at` | Creation timestamp | `time.Time` | | -| `delete_reason` | Reason for deletion | `string` | `true` | -| `deleted_at` | Deletion timestamp | `time.Time` | `true` | -| `description` | Description | `string` | `true` | -| `external_id` | External IDs | `[]string` | `true` | -| `health` | Health | `Health` | `true` | -| `labels` | Labels | `JSONStringMap` | `true` | -| `name` | Name | `string` | `true` | -| `properties` | Properties | `Properties` | `true` | -| `ready` | Whether the config item is ready | `bool` | | -| `scraper_id` | ID of the scraper | `string` | `true` | -| `source` | Source | `string` | `true` | -| `status` | Status | `string` | `true` | -| `tags` | Tags | `JSONStringMap` | | -| `type` | Type | `string` | | -| `updated_at` | Update timestamp | `time.Time` | `true` | - -### Agent - -| Field | Description | Schema | Optional | -| ------------- | ------------------------------ | -------- | -------- | -| `id` | The id of the agent | `uuid` | | -| `name` | The name of the agent | `string` | | -| `description` | Short description of the agent | `string` | | - -## Notification Defaults diff --git a/mission-control/docs/notifications/events/configs.mdx b/mission-control/docs/notifications/events/configs.mdx new file mode 100644 index 00000000..4ae37ead --- /dev/null +++ b/mission-control/docs/notifications/events/configs.mdx @@ -0,0 +1,101 @@ +--- +title: Configs +description: Events that fire on config changes and health +--- + +import { + CheckHealthEnv, ConfigEventsTemplateVars, ComponentHealthEnv, + AgentEnv, ConfigItemEnv, ComponentEnv, CanaryEnv, CheckEnv, CheckStatus, + Uptime, Latency +} from "../../reference/notifications/_env_vars.mdx" + +Configs emit events when their health changes or when they are created, modified, or removed. + +## Health events + +- `config.healthy` +- `config.unhealthy` +- `config.warning` +- `config.unknown` + +```yaml title="ec2-health-notification.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: ec2-instance-health-alerts + namespace: default +spec: + events: + - config.unhealthy + - config.warning + filter: config.type == 'AWS::EC2::Instance' + to: + email: alerts@acme.com +``` + +![](./slack-notification-catalog-unhealthy.png) + + +### Default Template + +The default notification template for health events is: + +#### Title + +``` +{{ if ne channel "slack"}}{{.config.type}} {{.config.name}} is {{.config.health}}{{end}} +``` + +#### Template + +```txt file=../../../modules/mission-control/notification/templates/config.health + +``` + +## State events + +- `config.created` +- `config.updated` +- `config.deleted` + +```yaml title="ec2-instance-updates.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: ec2-instance-changes + namespace: default +spec: + events: + - config.created + - config.updated + - config.deleted + filter: config.type == 'AWS::EC2::Instance' + to: + email: alerts@acme.com +``` + +![](./slack-notification-catalog-updated.png) + +### Default Template + +#### Title + +``` +{{ if ne channel "slack"}}{{.config.type}} {{.config.name}} was {{.new_state}}{{end}} +``` + +#### Template + +```txt file=../../../modules/mission-control/notification/templates/config.db.update + +``` + +## Template Variables + + + +### Config Item + + +### Agent + diff --git a/mission-control/docs/notifications/events/health-checks.md b/mission-control/docs/notifications/events/health-checks.md deleted file mode 100644 index 6e45d000..00000000 --- a/mission-control/docs/notifications/events/health-checks.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -description: Events that fire when health checks pass or fail -title: Health Checks ---- - -Health checks emit 2 events - -- **`check.passed`**: - - - **Title:** `Check {{.check.name}} has passed` - - **Body:** - ``` - Canary: {{.canary.name}} - {{if .agent}}Agent: {{.agent.name}}{{end}} - {{if .status.message}}Message: {{.status.message}} {{end}} - ### Labels: - {{range $k, $v := .check.labels}}**{{$k}}**: {{$v}} - {{end}} - [Reference]({{.permalink}}) - ``` - -- **`check.failed`**: - - **Title:** `Check {{.check.name}} has failed` - - **Body:** - ``` - Canary: {{.canary.name}} - {{if .agent}}Agent: {{.agent.name}}{{end}} - Error: {{.status.error}} - ### Labels: - {{range $k, $v := .check.labels}}**{{$k}}**: {{$v}} - {{end}} - [Reference]({{.permalink}}) - ``` - -Sample notification: - -```yaml title="notification.yaml" -apiVersion: mission-control.flanksource.com/v1 -kind: Notification -metadata: - name: api-http-fail-alert - namespace: default -spec: - events: - - check.failed - filter: check.type == 'http' - title: API HTTP Check {{.check.name}} failing - body: | - ## Check Failed - Error: {{.status.error}} - Failed at {{.status.created_at}} - to: - email: alerts@acme.com -``` - -## Variables - -| Field | Description | Schema | Optional | -| ----------- | ----------------------------- | ------------------------------ | -------- | -| `canary` | The parent canary object | [`Canary`](#canary) | | -| `check` | The check | [`Check`](#check) | | -| `agent` | Agent details (if applicable) | [`Agent`](#check) | `true` | -| `status` | Check status details | [`CheckStatus`](#check-status) | | -| `permalink` | A link to the health check | `string` | | - -### Canary - -| Field | Description | Schema | Optional | -| ------------ | ---------------------------- | ------------------- | -------- | -| `id` | The id of the canary | `uuid` | | -| `name` | The name of the canary | `string` | | -| `namespace` | The namespace of the canary | `string` | | -| `agent_id` | The agent id of the canary | `string` | | -| `labels` | The labels of the canary | `map[string]string` | `true` | -| `source` | The source of the canary | `string` | | -| `created_at` | The created at of the canary | `string` | | -| `updated_at` | The updated at of the canary | `string` | | -| `deleted_at` | The deleted at of the canary | `string` | `true` | - -### Check - -| Field | Description | Schema | Optional | -| ---------------------- | -------------------------------------- | --------------------- | -------- | -| `id` | The id of the check | `uuid` | | -| `type` | The type of the check | `string` | | -| `name` | The name of the check | `string` | | -| `labels` | The labels of the check | `map[string]string` | `true` | -| `description` | The description of the check | `string` | | -| `status` | Check status details | `string` | | -| `severity` | The severity of the check | `string` | `true` | -| `uptime` | The past 1 hour uptime summary | [`Uptime`](#uptime) | `true` | -| `latency` | The past 1 hour latency summary | [`Latency`](#latency) | `true` | -| `transformed` | Whether the check has been transformed | `bool` | | -| `last_runtime` | The last runtime of the check | `time.Time` | `true` | -| `next_runtime` | The next runtime of the check | `time.Time` | `true` | -| `last_transition_time` | The last transition time of the check | `time.Time` | `true` | -| `created_at` | The created at of the check | `time.Time` | | -| `updated_at` | The updated at of the check | `time.Time` | | -| `deleted_at` | The deleted at of the check | `time.Time` | `true` | - -#### Uptime - -| Field | Description | Schema | Optional | -| ----------- | ------------------------------------ | ----------- | -------- | -| `passed` | The number of checks that passed | `int` | | -| `failed` | The number of checks that failed | `int` | | -| `p100` | The percentage of checks that passed | `float64` | | -| `last_pass` | The last time a check passed | `time.Time` | `true` | -| `last_fail` | The last time a check failed | `time.Time` | `true` | - -#### Latency - -| Field | Description | Schema | Optional | -| ----------- | ------------------------ | --------- | -------- | -| `p99` | The latency of the check | `float64` | `true` | -| `p97` | The latency of the check | `float64` | `true` | -| `p95` | The latency of the check | `float64` | `true` | -| `rolling1h` | The latency of the check | `float64` | | - -### Agent - -| Field | Description | Schema | Optional | -| ------------- | ------------------------------ | -------- | -------- | -| `id` | The id of the agent | `uuid` | | -| `name` | The name of the agent | `string` | | -| `description` | Short description of the agent | `string` | | - -### Check Status - -| Field | Description | Schema | Optional | -| ------------ | ----------------------------------------------- | ----------- | -------- | -| `check_id` | The id of the check associated with this status | `uuid` | | -| `status` | The status of the check | `bool` | | -| `invalid` | Whether the check errored out | `bool` | | -| `time` | The time of the check | `string` | | -| `duration` | The duration of the check | `int` | | -| `message` | The success message of the check | `string` | | -| `error` | The error of the check in case of failure | `string` | | -| `created_at` | The created at of the check | `time.Time` | | - -## Notification Template Defaults diff --git a/mission-control/docs/notifications/events/health-checks.mdx b/mission-control/docs/notifications/events/health-checks.mdx new file mode 100644 index 00000000..6bedab70 --- /dev/null +++ b/mission-control/docs/notifications/events/health-checks.mdx @@ -0,0 +1,88 @@ +--- +description: Events that fire when health checks pass or fail +title: Health Checks +--- + +import { + CheckHealthEnv, ConfigEventsTemplateVars, ComponentHealthEnv, + AgentEnv, ConfigItemEnv, ComponentEnv, CanaryEnv, CheckEnv, CheckStatus, + Uptime, Latency +} from "../../reference/notifications/_env_vars.mdx" + +Health checks emit 2 events + +- `check.passed` +- `check.failed` + +```yaml title="notification.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: api-http-fail-alert + namespace: default +spec: + events: + - check.failed + filter: check.type == 'http' + title: API HTTP Check {{.check.name}} failing + body: | + ## Check Failed + Error: {{.status.error}} + Failed at {{.status.created_at}} + to: + email: alerts@acme.com +``` + +![](./slack-notification-unhealthy-check.png) + +## Default Templates + +### check.passed + +#### Title + +``` +{{ if ne channel "slack"}}Check {{.check.name}} has passed{{end}} +``` + +#### Template + +```txt file=../../../modules/mission-control/notification/templates/check.passed + +``` + +### check.failed + +#### Title + +``` +{{ if ne channel "slack"}}Check {{.check.name}} has failed{{end}} +``` + +#### Template + +```txt file=../../../modules/mission-control/notification/templates/check.failed + +``` + +## Template Variables + + + +### Agent + + +### Canary + + +### Check + + +### CheckStatus + + +### Uptime + + +### Latency + \ No newline at end of file diff --git a/mission-control/docs/notifications/events/slack-notification-catalog-unhealthy.png b/mission-control/docs/notifications/events/slack-notification-catalog-unhealthy.png new file mode 100644 index 00000000..584105d4 Binary files /dev/null and b/mission-control/docs/notifications/events/slack-notification-catalog-unhealthy.png differ diff --git a/mission-control/docs/notifications/events/slack-notification-catalog-updated.png b/mission-control/docs/notifications/events/slack-notification-catalog-updated.png new file mode 100644 index 00000000..c89a5d22 Binary files /dev/null and b/mission-control/docs/notifications/events/slack-notification-catalog-updated.png differ diff --git a/mission-control/docs/notifications/events/slack-notification-component.png b/mission-control/docs/notifications/events/slack-notification-component.png new file mode 100644 index 00000000..84caa1a4 Binary files /dev/null and b/mission-control/docs/notifications/events/slack-notification-component.png differ diff --git a/mission-control/docs/notifications/events/slack-notification-unhealthy-check.png b/mission-control/docs/notifications/events/slack-notification-unhealthy-check.png new file mode 100644 index 00000000..3b96c5bc Binary files /dev/null and b/mission-control/docs/notifications/events/slack-notification-unhealthy-check.png differ diff --git a/mission-control/docs/notifications/examples/kube-unhealthy-deployment.md b/mission-control/docs/notifications/examples/kube-unhealthy-deployment.md new file mode 100644 index 00000000..c958ed50 --- /dev/null +++ b/mission-control/docs/notifications/examples/kube-unhealthy-deployment.md @@ -0,0 +1,17 @@ +--- +title: Kubernetes Deployment Health +--- + +```yaml title="kubernetes-deployment-health.yaml" +apiVersion: mission-control.flanksource.com/v1 +kind: Notification +metadata: + name: deployment-health-alerts +spec: + events: + - config.unhealthy + - config.warning + filter: config.type == 'Kubernetes::Deployment' + to: + connection: connection://mission-control/slack +``` diff --git a/mission-control/docs/notifications/index.mdx b/mission-control/docs/notifications/index.mdx index 9ef5da84..55a32e67 100644 --- a/mission-control/docs/notifications/index.mdx +++ b/mission-control/docs/notifications/index.mdx @@ -31,16 +31,20 @@ This notification will send an email to `alerts@acme.com` whenever a health chec + ## Templating You can use Go Templates to customize the content of notification titles and bodies. This allows you to include dynamic information from the event that triggered the notification. -For example, the following notification definition uses a Go Template to include the name and health status of the check in the notification title: +**For example, the following notification definition** uses a Go Template to include the name and health status of the check in the notification title: ```yaml title="notification-template" apiVersion: mission-control.flanksource.com/v1 kind: Notification spec: + events: + - check.failed + - check.passed title: Check {{.check.name}} is {{.check.health}} ``` @@ -48,10 +52,9 @@ In this example `{{.check.name}}` and `{{.check.health}}` are placeholders that :::tip Markdown -All notification templates in Mission Control are defined in markdown, and depending on the support of the notification channel in use it will either be converted to HTML or plain text. +All notification templates in Mission Control are defined in markdown, and depending on the support of the notification channel it will either be converted to HTML or plain text. ::: - ## Filtering Events Mission Control allows you to fine-tune your notification delivery by filtering events using CEL . This enables you to specify precise conditions that dictate when a notification should be triggered. For instance, you can configure notifications to be sent only for specific event types, specific resources, or when certain conditions are met. diff --git a/mission-control/docs/reference/notifications/_env_vars.mdx b/mission-control/docs/reference/notifications/_env_vars.mdx new file mode 100644 index 00000000..75beb426 --- /dev/null +++ b/mission-control/docs/reference/notifications/_env_vars.mdx @@ -0,0 +1,593 @@ +export function CheckHealthEnv() { + return+} + +export function ComponentHealthEnv() { + return +} + +export function ConfigEventsTemplateVars() { + return +} + +export function AgentEnv() { + return +} + +export function ConfigItemEnv() { + return +} + +export function CanaryEnv() { + return +} + +export function ComponentEnv() { + return +} + +export function CheckEnv() { + return +} + +export function Uptime() { + return ( + + ) +} + +export function Latency() { + return ( + + ) +} + + +### Check Status + +| Field | Description | Schema | Optional | +| ------------ | ----------------------------------------------- | ----------- | -------- | +| `check_id` | The id of the check associated with this status | `uuid` | | +| `status` | The status of the check | `bool` | | +| `invalid` | Whether the check errored out | `bool` | | +| `time` | The time of the check | `string` | | +| `duration` | The duration of the check | `int` | | +| `message` | The success message of the check | `string` | | +| `error` | The error of the check in case of failure | `string` | | +| `created_at` | The created at of the check | ``time.Time`` | | + + +export function CheckStatus() { + return ( + + ) +} diff --git a/mission-control/docs/reference/notifications/_notification.mdx b/mission-control/docs/reference/notifications/_notification.mdx index 076463d4..27838470 100644 --- a/mission-control/docs/reference/notifications/_notification.mdx +++ b/mission-control/docs/reference/notifications/_notification.mdx @@ -1,10 +1,11 @@ - -> Only one recipient can be specified +:::info Single Recipient +Only one recipient can be specified +::: diff --git a/mission-control/docs/reference/notifications/template_functions.mdx b/mission-control/docs/reference/notifications/template_functions.mdx new file mode 100644 index 00000000..203ef2bd --- /dev/null +++ b/mission-control/docs/reference/notifications/template_functions.mdx @@ -0,0 +1,219 @@ +--- +title: Template Functions +--- + +Special template functions are made available on notifications to complex block formation easier. + +## labelsFormat +Formats the given set of labels into a markdown string + +Syntax: + +```js +labelsFormat(map[string]any): string +``` + +Example: + +```js +labelsFormat(map[string]any{ + "namespace": "default", + "cluster": "staging", +}) +``` + +```md +### Labels + +**namespace**: default +**cluster**: staging +``` + +## Slack + +These slack helper functions will return a json string suitable for use in slack blocks/messages. + +### slackHealthEmoji +Returns a slack emoji based on the supplied health + +Syntax: + +```js +slackHealthEmoji(health): string +``` + +**Returns:** + +- `:large_green_circle:` for `healthy` health status +- `:red_circle:` for `unhealthy` health status +- `:large_orange_circle:` for `warning` health status +- `:white_circle:` for any other health status + +### slackSectionLabels + +Formats the given set of labels into fields of a slack section block + +Syntax: + +```js +slackSectionLabels(map[string]any): SlackSection +``` + +Example: + +```js +slackSectionLabels(map[string]any{ + "namespace": "default", + "cluster": "staging", +}) +``` + +```json +{ + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Labels*" + }, + "fields": [ + { + "type": "mrkdwn", + "text": "*namespace*: default", + "verbatim": true + }, + { + "type": "mrkdwn", + "text": "*cluster*: staging", + "verbatim": true + } + ] +} +``` + +### slackSectionTextFieldPlain + +Creates a plain text field for a Slack section block + +Syntax: + +```js +slackSectionTextFieldPlain(text: string): string +``` + +Example: + +```js +slackSectionTextFieldPlain("alert-manager") +``` + +```json +{ + "type": "plain_text", + "text": "alert-manager" +} +``` + +### slackSectionTextFieldMD +Creates a markdown text field for a Slack section block + +Syntax: + +```js +slackSectionTextFieldMD(text: string): string +``` + +Example: + +```js +slackSectionTextFieldPlain("alert-manager") +``` + +```json +{ + "type": "mrkdwn", + "text": "alert-manager" +} +``` + +### slackSectionTextMD +Creates a Slack section block with markdown text + +Syntax: + +```js +slackSectionTextMD(text: string): string +``` + +Example: + +```js +slackSectionTextMD("alert-manager") +``` + +```json +{ + "type": "section", + "text": { + "type": "mrkdwn", + "text": "alert-manager" + } +} +``` + +### slackSectionTextPlain +Creates a Slack section block with plain text + +Syntax: + +```js +slackSectionTextPlain(text: string): string +``` + +Example: + +```js +slackSectionTextMD("alert-manager") +``` + +```json +{ + "type": "section", + "text": { + "type": "plain_text", + "text": "alert-manager" + } +} +``` + +### SlackURLAction +Creates a Slack action block with a URL button + +Syntax: + +```js +slackURLAction(name: string, url: string): string +``` + +Example: + +```js +slackURLAction("Grafana", "https://grafana.com") +``` + +```json +{ + "type": "actions", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Grafana", + "emoji": true + }, + "url": "https://grafana.com", + "action_id": "Grafana" + } + ] +} +``` \ No newline at end of file diff --git a/mission-control/docs/reference/notifications/template_vars/checks.mdx b/mission-control/docs/reference/notifications/template_vars/checks.mdx new file mode 100644 index 00000000..a9fcceb8 --- /dev/null +++ b/mission-control/docs/reference/notifications/template_vars/checks.mdx @@ -0,0 +1,27 @@ +--- +title: Check Events +--- + +import { CheckHealthEnv, AgentEnv, CanaryEnv, CheckEnv, CheckStatus, Uptime, Latency } from "../_env_vars.mdx" + +List of template variables available on check events. + + + +### Agent + + +### Canary + + +### Check + + +### CheckStatus + + +### Uptime + + +### Latency + \ No newline at end of file diff --git a/mission-control/docs/reference/notifications/template_vars/components.mdx b/mission-control/docs/reference/notifications/template_vars/components.mdx new file mode 100644 index 00000000..b59e9dff --- /dev/null +++ b/mission-control/docs/reference/notifications/template_vars/components.mdx @@ -0,0 +1,17 @@ +--- +title: Component Events +--- + +import { + CheckHealthEnv, ConfigEventsTemplateVars, ComponentHealthEnv, + AgentEnv, ConfigItemEnv, ComponentEnv, CanaryEnv, CheckEnv, CheckStatus, + Uptime, Latency +} from "../_env_vars.mdx" + + + +### Agent + + +### Component + \ No newline at end of file diff --git a/mission-control/docs/reference/notifications/template_vars/config.mdx b/mission-control/docs/reference/notifications/template_vars/config.mdx new file mode 100644 index 00000000..b5d1f588 --- /dev/null +++ b/mission-control/docs/reference/notifications/template_vars/config.mdx @@ -0,0 +1,13 @@ +--- +title: Config Events +--- + +import { ConfigEventsTemplateVars, AgentEnv, ConfigItemEnv } from "../_env_vars.mdx" + + + +### Agent + + +### Config Item + diff --git a/mission-control/docs/reference/notifications/template_vars/index.md b/mission-control/docs/reference/notifications/template_vars/index.md new file mode 100644 index 00000000..573e287f --- /dev/null +++ b/mission-control/docs/reference/notifications/template_vars/index.md @@ -0,0 +1,3 @@ +--- +title: Template Variables +---