Workflow Examples

This page provides practical examples of workflows for different use cases and integrations.

Triggers Examples

Filter by Monitor Name

This example shows how to create a workflow that only triggers for a specific monitor (by its name):

workflow: 
  id: specific-monitor-workflow
  description: Workflow triggered only by Workload Pods Crashed Monitor
  triggers:
    - type: alert
      filters:
        - key: alertname
          value: Workload Pods Crashed Monitor

Filter by Environment

Execute only on the Prod environment. The "env" attribute needs to be part of the monitor context attributes (either by using it in the group by section or by explicitly adding it as a context label):

workflow: 
  id: prod-only-workflow
  description: Workflow triggered only by production environment alerts
  triggers:
    - type: alert
      filters:
        - key: env
          value: prod

Filter by Multiple Conditions

This example shows how to combine multiple filters. In this case it will match events from the prod environment and also monitors that explicitly routed the workflow with the name "actual-name-of-workflow":

workflow: 
  id: multi-filter-workflow
  description: Workflow triggered by critical alerts in production
  triggers:
    - type: alert
      filters:
        - key: env
          value: prod
        - key: annotations.actual-name-of-workflow
          value: enabled

Filter by Regex

In this case we will use a regular expression to filter on events coming from the groundcover OR monitoring namespaces. Note that any regular expression can be used:

workflow: 
  id: regex-filter-workflow
  description: Workflow triggered by alerts from groundcover or monitoring namespaces
  triggers:
    - type: alert
      filters:
        - key: namespace
          value: r"(groundcover|monitoring)"

Consts Examples

The consts section is the best location to create pre-defined attributes and apply different transformations on the monitor's metadata for formatting the notification messaging.

Map Severities

Severities in your notified destination may not match the groundcover predefined severities. By using a dictionary, you can map any groundcover severity value to another, and extract it by using the actual monitor severity. Use the "keep.dictget" function to extract from a dictionary and apply a default in case the value is missing.

workflow:
  id: severity-mapping-example
  description: Example of mapping severities using consts
  triggers:
    - type: alert
  consts:
    severities: '{"S1": "P1","S2": "P2","S3": "P3","S4": "P4","critical": "P1","error": "P2","warning": "P3","info": "P4"}'
    severity: keep.dictget({{ consts.severities }}, {{ alert.annotations._gc_severity }}, "P3")

Best Practice for Accessing Monitor Labels

When accessing a context label via alert.labels, if this label is not transferred within the monitor - the workflow might crash. Best practice to pre-define labels is to declare them in the consts section with a default value, using "keep.dictget" so the value is gracefully pulled from the labels object.

workflow:
  id: labels-best-practice-example
  description: Example of safely accessing monitor labels
  triggers:
    - type: alert
  consts:
    region: keep.dictget({{ alert.labels }}, "cloud.region", "")

Note: Label names that are dotted, like "cloud.region" in this example, cannot be referenced in the monitor itself and can only be retrieved using this technique of pulling the value with "keep.dictget" from the alert.labels object.

Additional Useful Functions

  • keep.dict_pop({{alert.labels}}, "_gc_monitor_id", "_gc_monitor_name", "_gc_severity", "backend_id", "grafana_folder", "_gc_issue_header") - "Clean" a key-value dictionary from some irrelevant values (keys). In this case, the groundcover labels dictionary has some internal keys that you might not want to include in your notification content.

  • keep.join(["a", "b", "c"], ",") - Joins a list of elements into a string using a given delimiter. In this case the output is "a,b,c".

Action Examples

Conditional Statements

Use "if" condition to apply logic on different actions.

Create a separate block for a firing monitor (a resolved monitor can use different logic to change formatting of the notification):

workflow:
  id: conditional-actions-example
  description: Example of conditional actions based on alert status
  triggers:
    - type: alert
  actions:
    - if: '{{ alert.status }} == "firing"'
      name: slack-action-firing
      provider:
        config: '{{ providers.groundcover-alerts-dev }}'
        type: slack
        with:
          attachments:
          - color: '{{ consts.red_color }}'
            footer: '{{ consts.footer_url }}'
            footer_icon: '{{ consts.footer_icon }}'
            text: '{{ consts.slack_message }}'
            title: 'Firing: {{ alert.alertname }}'
            title_link: '{{ consts.title_link }}'
            ts: keep.utcnowtimestamp()
            type: plain_text
          message: ' '

"If" statements can include and/or logic for multiple conditions:

workflow:
  id: multi-condition-actions-example
  description: Example of multiple conditions in actions
  triggers:
    - type: alert
  actions:
    - if: '{{ alert.status }} == "firing" and {{ alert.labels.namespace }} == "namespace1"'
      name: slack-action-firing
      provider:
        config: '{{ providers.groundcover-alerts-dev }}'
        type: slack
        with:
          attachments:
          - color: '{{ consts.red_color }}'
            footer: '{{ consts.footer_url }}'
            footer_icon: '{{ consts.footer_icon }}'
            text: '{{ consts.slack_message }}'
            title: 'Firing: {{ alert.alertname }}'
            title_link: '{{ consts.title_link }}'
            ts: keep.utcnowtimestamp()
            type: plain_text
          message: ' '

Notification by Specific Hours

Use the function keep.is_business_hours combined with an "if" statement to trigger an action within specific hours only.

In this example the action block will execute on Sundays (6) between 20-23 (8pm to 11pm) or on Mondays (0) between 0-1am:

workflow:
  id: time-based-notification-example
  description: Example of time-based conditional actions
  triggers:
    - type: alert
  actions:
    - if: '({{ alert.status }} == "firing" and (keep.is_business_hours(timezone="America/New_York", business_days=[6], start_hour=20, end_hour=23) or keep.is_business_hours(timezone="America/New_York", business_days=[0], start_hour=0, end_hour=1)))'
      name: time-based-notification
      provider:
        type: slack
        config: '{{ providers.slack_webhook }}'
        with:
          message: "Time-sensitive alert: {{ alert.alertname }}"

Last updated