Skip to content

Webhook Custom Body Templates


With template syntax, you can customize the Body content of Webhook notifications:

  • Dynamic rendering: use {{ field_name }} to insert alert fields directly (for example, {{ host }} or {{ df_status }});

  • Data processing: format data with {{ variable | function() }} (for example, converting a timestamp to a date, or a value to a percentage);

  • Conditional branching: use {% if ... %} to achieve differentiated Body output under different statuses;

  • JSON output: use to_json_dumps to output JSON objects, arrays, numbers, booleans, and more;

  • Real-time queries: embed DQL("query statement") to retrieve related data (such as host IP and system information).

Basic Template Variables

The basic syntax of template variables is {{ field_name }}, which can be used to render dynamic information about events. The following table lists common template variables in Webhook custom Bodies and their purposes:

Template Variable Type Description
date, timestamp Integer Time when the event was generated, Unix timestamp in seconds
df_status String(Enum) Event status. Possible values: Critical (critical), Error (error), Warning (warning), OK (ok), No Data (nodata)
df_event_id String Unique event ID
df_event_link String Link to the event details page
df_title String Event title
df_message String Event content
df_dimension_tags String Event dimension tags, used to identify the detected object, for example {"host":"web-001"}
df_dimension_tags_obj Dict Event dimension object, for reading dimension fields as an object
df_monitor_id String Alert policy ID
df_monitor_name String Alert policy name
df_monitor_checker_id String Monitor ID
df_monitor_checker_name String Monitor name
df_monitor_checker_value String Detection value, that is, the value detected by the monitor
Result Integer, Float, String, Dict, List Raw value detected. Like df_monitor_checker_value, it is generated at detection time, but retains its original type
Result_with_unit String Detection value with unit
df_related_data Dict Related data
df_fault_id String ID of the current fault, equal to the df_event_id of the first fault event
df_fault_status String(Enum) Status of the current fault. Possible values: OK (ok), Fault (fault)
df_fault_start_time Integer Time when the current fault occurred, Unix timestamp in seconds
df_fault_duration Integer Duration of the current fault, in seconds
df_site_name String Name of the current Guance node
df_workspace_name String Name of the workspace it belongs to
df_workspace_uuid String ID of the workspace it belongs to
df_label List List of monitor labels
df_alert_policy_names List List of matched alert policy names
df_sent_target_types List List of alert notification target types to which this event has been sent
df_event Dict Complete event data
Fields in df_dimension_tags String Fields in df_dimension_tags are extracted to the top level, such as host and region

Note:

  • df_monitor_checker_value is forcibly converted to the String type for compatibility;

  • If you need to retain the original type of the detection value, it is recommended to use Result;

  • Available variables may vary by monitor type, event source, and notification scenario.

Template Variable Example

Suppose the monitor's by clause is configured with region and host, and the Webhook custom Body template is as follows:

{
  "title": "Monitor {{ df_monitor_checker_name }} detected a fault in {{ df_dimension_tags }}",
  "region": "{{ region }}",
  "host": "{{ host }}",
  "status": "{{ df_status }}",
  "value": "{{ Result }}",
  "monitor": "{{ df_monitor_checker_name }}",
  "policy": "{{ df_monitor_name }}"
}

After an error event is generated, the rendered Body output is as follows:

{
  "title": "Monitor Monitor 001 detected a fault in {\"region\":\"hangzhou\",\"host\":\"web-001\"}",
  "region": "hangzhou",
  "host": "web-001",
  "status": "error",
  "value": "90.12345",
  "monitor": "Monitor 001",
  "policy": "Team 001"
}

JSON Body Output

The final Webhook custom Body usually needs to output valid JSON. It is recommended to define a JSON object first and then process it with the to_json_dumps function, to avoid JSON syntax errors such as string escaping, nested objects and arrays, and missing commas.

Example:

{% set json_data = {
  "event_id": df_event_id,
  "title": df_title,
  "status": df_status,
  "status_text": df_status | to_status_human,
  "event_link": df_event_link,
  "monitor": {
    "id": df_monitor_id,
    "name": df_monitor_name,
    "checker_id": df_monitor_checker_id,
    "checker_name": df_monitor_checker_name
  },
  "dimension": {
    "raw": df_dimension_tags,
    "object": df_dimension_tags_obj,
    "pretty": df_dimension_tags | to_pretty_tags
  },
  "value": {
    "raw": Result,
    "with_unit": Result_with_unit,
    "type": Result | type_name
  }
} %}
{{ json_data | to_json_dumps }}

The output is as follows:

{
  "event_id": "event-xxxxx",
  "title": "CPU usage too high",
  "status": "error",
  "status_text": "Error",
  "event_link": "https://console.guance.com/keyevents/monitor/events/event-xxxxx",
  "monitor": {
    "id": "altpl_xxxxx",
    "name": "Team 001",
    "checker_id": "rul_xxxxx",
    "checker_name": "Monitor 001"
  },
  "dimension": {
    "raw": "{\"region\":\"hangzhou\",\"host\":\"web-001\"}",
    "object": {
      "region": "hangzhou",
      "host": "web-001"
    },
    "pretty": "region:hangzhou, host:web-001"
  },
  "value": {
    "raw": 90.12345,
    "with_unit": "90.12345%",
    "type": "float"
  }
}

Rendering JSON Field by Field

You can also render JSON field by field. In this case, pay attention to field types:

{
  "event_id": "{{ df_event_id }}",
  "status": "{{ df_status }}",
  "status_text": "{{ df_status | to_status_human }}",
  "checker_name": "{{ df_monitor_checker_name }}",
  "dimension": {{ df_dimension_tags_obj | to_json_dumps }},
  "value": {{ Result | to_json_dumps }},
  "related_data": {{ df_related_data | to_json_dumps }}
}

Notes:

  • String fields can be placed in double quotes, for example "{{ df_status }}";

  • For objects, arrays, numbers, and booleans, it is recommended to use to_json_dumps;

  • It is not recommended to write objects or arrays as "{{ df_related_data }}"; otherwise, the receiver will get a string instead of a JSON object.

Variables for Special Scenarios

RUM Metric Detection

In RUM metric detection, in addition to the common template variables above, the following template variables are also supported:

Template Variable Type Description
app_id String App ID
app_name String App name
app_type String App type

Handling Fields with Special Characters

If the dimensions field in the detection configuration contains special characters (such as - or @), for example host-name or @level, it cannot be used directly as a normal variable name, which causes template rendering to fail.

Incorrect syntax:

{{ host-name }}
{{ @level }}

The solution is to reference them in the following format:

{{ df_event["host-name"] }}
{{ df_event["@level"] }}
{{ df_dimension_tags_obj["host-name"] }}
{{ df_dimension_tags_obj["@level"] }}

Template Functions

In addition to directly displaying field values from events, you can also use template functions to further process field values for better output.

The basic syntax is as follows:

{{ <template_variable> | <template_function> }}
{{ <template_variable> | <template_function>(arguments) }}

Here is a concrete example:

Event generation time: {{ date | to_datetime }}

If you need to perform arithmetic on a template variable before applying a template function, do not forget to add parentheses, for example:

CPU usage: {{ (Result * 100) | to_round(2) }}

The available template functions are as follows:

Template Function Arguments Description
to_datetime tz="Asia/Shanghai" Converts a Unix timestamp in seconds or an ISO8601 date string to a datetime string
to_date_range_human lang="zh" Converts a duration in seconds to a human-readable form, such as 1 day 2 hours 3 minutes 1 second
to_status_human lang="zh" Converts df_status to a human-readable status
to_fixed ndigits=0 Outputs a number with a fixed number of decimal places
to_round ndigits=0 Rounds a number to the specified number of decimal places
to_percent ndigits=0 Converts a decimal to a percentage
to_pretty_tags separators=(':', ', ') Converts dict or JSON string tags into readable tag text
limit_lines lines=3, chars=None Limits the number of output lines and can also limit the number of characters per line
limit_chars / limit_text chars=50 Limits the number of output characters; limit_text is an alias for limit_chars
type_name None Outputs the name of the data type
to_int None Converts to an integer
to_float None Converts to a float
to_str None Converts to a string
to_json_dumps indent=None Converts dict, list, and other data into a JSON-serialized string
is_error None Determines whether an object is an error; often used to check whether an embedded DQL executed normally
length None Returns the length of a string, list, dict, or other object
replace old, new, count=-1 Replaces string content; count=-1 means replace all
abs None Returns the absolute value of a number

Template Function Example

{% set body = {
  "object": df_dimension_tags | to_pretty_tags,
  "time": date | to_datetime,
  "status": df_status | to_status_human,
  "value": Result | to_fixed(2),
  "percent": Result | to_percent(1),
  "duration": df_fault_duration | to_date_range_human,
  "message": df_message | limit_lines(3, 80)
} %}
{{ body | to_json_dumps }}

Template Branches

You can use conditional branches to achieve differentiated Body output for different statuses.

The basic syntax is as follows:

{% if condition %}
  ...
{% elif condition %}
  ...
{% else %}
  ...
{% endif %}

Template Branch Example

{% set level = "info" %}
{% if df_status == "critical" %}
  {% set level = "critical" %}
{% elif df_status == "error" %}
  {% set level = "error" %}
{% elif df_status == "warning" %}
  {% set level = "warning" %}
{% elif df_status == "nodata" %}
  {% set level = "nodata" %}
{% endif %}

{% set body = {
  "level": level,
  "status": df_status,
  "status_text": df_status | to_status_human,
  "title": df_title,
  "event_link": df_event_link
} %}
{{ body | to_json_dumps }}

Embedded DQL Query Function

When template variables alone cannot meet the rendering requirements, you can use the embedded DQL query function to supplement data. The embedded DQL executes the DQL within the current workspace and the time range of the current detection, and usually uses the first record of the query result as a template variable.

The call format is as follows:

{% set dql_data = DQL("DQL statement", argument 1, argument 2) %}

Embedded DQL Query Example

{% set host_info = DQL("O::HOST:(host_ip, os) { region = ?, host = ? }", region, host) %}

{% set body = {
  "host": host,
  "region": region,
  "host_ip": host_info.host_ip,
  "os": host_info.os,
  "status": df_status,
  "event_link": df_event_link
} %}
{{ body | to_json_dumps }}

Embedded DQL Query Function Details

  • The embedded DQL query should be placed at the beginning of the template;

  • The parameter placeholder ? in the DQL statement is automatically escaped when replaced with specific values;

  • When passing template variables to DQL, write the variable name directly in the arguments, such as host; do not write {{ host }};

  • The variable name of the query result must not conflict with existing template variables or template functions;

  • If functions are used to process fields in DQL, it is recommended to use AS to specify a field alias for easy access in the template;

  • If a field name in the DQL query result contains special characters, read it in the form {{ host_info["host-name"] }};

  • You can use is_error to determine whether the DQL executed normally.

Complete Body Example

The following example is suitable for sending alert events to an external event center:

{% set is_recovery = df_status == "ok" %}
{% set priority = "P0" if df_status == "critical" else ("P1" if df_status in ["error", "nodata"] else ("P2" if df_status == "warning" else "INFO")) %}

{% set body = {
  "source": "guance",
  "event_id": df_event_id,
  "event_link": df_event_link,
  "title": df_title,
  "status": df_status,
  "status_text": df_status | to_status_human,
  "priority": priority,
  "is_recovery": is_recovery,
  "monitor": {
    "policy_id": df_monitor_id,
    "policy_name": df_monitor_name,
    "checker_id": df_monitor_checker_id,
    "checker_name": df_monitor_checker_name
  },
  "object": {
    "tags": df_dimension_tags_obj,
    "text": df_dimension_tags | to_pretty_tags
  },
  "value": {
    "raw": Result,
    "with_unit": Result_with_unit,
    "fixed_2": Result | to_fixed(2)
  },
  "fault": {
    "fault_id": df_fault_id,
    "fault_status": df_fault_status,
    "start_time": df_fault_start_time | to_datetime,
    "duration_seconds": df_fault_duration,
    "duration_text": df_fault_duration | to_date_range_human
  },
  "notify": {
    "alert_policy_names": df_alert_policy_names,
    "sent_target_types": df_sent_target_types
  }
} %}
{{ body | to_json_dumps }}

Notes

  • The final rendered result of a Webhook custom Body must be valid JSON;

  • If a field value may contain double quotes, line breaks, or special characters, it is recommended to use to_json_dumps for output;

  • Do not forcibly wrap objects, arrays, numbers, or booleans in strings;

  • When debugging a template, it is recommended to first verify the rendering result with a few fields, and then gradually add complex fields and conditional branches;

  • The Webhook custom Body template is responsible only for rendering the request Body; configurations such as the request URL and request headers are still maintained in the Webhook notification target.

Feedback

Is this page helpful?