Deliver Dynatrace problem notifications to ServiceNow ITOM quickly, with field mappings you can fine-tune. The
ServiceNow Connector supports problem detection and alerting and notification use cases.
For this purpose, you can use the ready-made workflow template called Send problem as ITOM event to ServiceNow. This is a good starting point for fine-tuning the custom notifications and for the heavy lifting of adapting the Davis problem data structure to the technical representation of the Dynatrace event management push connector in ServiceNow IT Operations Management (ITOM).
This section gives you an overview of the Send problem as ITOM event to ServiceNow workflow template, including the simple workflow, its problem trigger, and the mappings for each input field of the Send ITOM Event action.
To find and create this simple workflow from the template, follow the steps in the workflow template page.
The problem trigger starts the workflow for almost every event type and any severity, but only for problems that last at least 5 minutes.
A custom filter then limits the forwarded problems to severity 1 to 3 and problems without a severity.
ACTIVE and CLOSED.
Alerts can be created and closed with the same workflow.Info) are selected by default.isNull(event.severity) or event.severity <= 3.
The trigger matches any severity, and this filter forwards problems with severity 1 to 3 as well as problems without a severity.
Problems with severity 4 or 5 are not forwarded by default.
To change this, adapt the filter or add further custom filtering.Send ITOM Event actionThe ServiceNow Send ITOM Event action creates and closes alerts automatically based on events.
The action uses Jinja expressions for workflows to populate the input fields with dynamic Davis problem data.
The action is configured with the following values:
Connection: Select one of the preconfigured connections to the ServiceNow ITOM Event API you have created during the setup.
Node: The name of the host, when the root cause entity or the first affected entity is of type HOST.
{% set hostName = "" %}{% if event().get("root_cause.smartscape_entity") %}{% if event()["root_cause.smartscape_entity"]["type"] | upper == "HOST" %}{% set hostName = event()["root_cause.smartscape_entity"]["name"] %}{% endif %}{% elif event().get("smartscape.affected_entities") and event()["smartscape.affected_entities"] | length == 1 and event()["smartscape.affected_entities"][0]["type"] | upper == "HOST" %}{% set hostName = event()["smartscape.affected_entities"][0]["name"] %}{% endif %}{{ hostName }}
Type: The category of the problem.
{{ event()["event.category"] | default ("") }}
Resource: Is left empty.
Message Key: The identifier for deduplication and correlating events in ServiceNow.
The environment ID and the display_id of the problem are used because these IDs won't change across updates to the same problem, and your Dynatrace environment is identified correctly.
{{ environment()['id'] }}: {{ event()["display_id"] | default("") }}
Severity: A mapping from Dynatrace problem severity to ServiceNow event severity is provided. One of 0, 1, 2, 3, or 4. A default value of 3 is assumed, which also applies to problems without a severity.
With the default trigger filter, severity 4 and 5 problems are not forwarded; widen the custom filter to include them.
{% set severity_mapping = {"1": "1","2": "2","3": "3","4": "4","5": "0"}%}{% set severity = event().get("event.severity") %}{{ severity_mapping.get(severity | string | trim, "3") }}
Resolution State: ACTIVE problems create new alerts, whereas CLOSED problems close alerts in ServiceNow.
{% set resolutionState = "UNKNOWN" %}{% if event().get("event.status") == "ACTIVE" %}{% set resolutionState = "New" %}{% elif event().get("event.status") == "CLOSED" %}{% set resolutionState = "Closing" %}{% endif %}{{ resolutionState }}
Time Of Event: A UTC timestamp in GlideDateTime format (YYYY-mm-dd HH:MM:SS) that represents either the start or the end of the problem. When neither can be identified, the action falls back to the event's timestamp.
{% set timeOfEvent = now() | string %}{% if event().get("event.status") == "ACTIVE" and event().get("event.status_transition") == "CREATED" and event().get("event.start") %}{% set timeOfEvent = event()["event.start"] %}{% elif event().get("event.status") == "CLOSED" and event().get("event.end") %}{% set timeOfEvent = event()["event.end"] %}{% elif event().get("timestamp") %}{% set timeOfEvent = event()["timestamp"] %}{% endif %}{{ (timeOfEvent | to_datetime(timezone='UTC')).strftime("%Y-%m-%d %H:%M:%S") if timeOfEvent else "" }}
Metric Name: A combination of the first impact level and the problem category, or only the first impact level, or only the category.
{% set metric = "" %}{% set impacts = event().get("dt.davis.impact_level") %}{% set category = event().get("event.category") %}{% if impacts and category %}{% set metric = impacts[0] ~ "-" ~ category %}{% elif impacts %}{% set metric = impacts[0] %}{% elif category %}{% set metric = category %}{% endif %}{{ metric }}
Description: A human-readable description of the problem.
{{ event()["event.description"] | to_json }}
Additional Info: The additional information included in the alert. When available, ServiceNow uses Dynatrace entity information to look up Configuration Items (CIs) and bind them to alerts. The root cause entities or the first affected entity are used for this purpose.
Also, primary Grail tags and classic tags (if available) are added as alert tags.
The URL of the workflow that sent the event, and the URL to the problem in Dynatrace are included.
The triggering event is included as extra metadata for later processing in ServiceNow.
For more details, see Send ITOM Event action.
{% set entityToBind = none %}{% if event().get("root_cause.smartscape_entity") %}{% set entityToBind = event()["root_cause.smartscape_entity"] %}{% elif event().get("smartscape.affected_entities") and event()["smartscape.affected_entities"] | length >= 1 %}{% set entityToBind = event()["smartscape.affected_entities"][0] %}{% endif %}{% set ns = namespace(classic_tags={}, grail_tags={}) %}{% for tag in event()["entity_tags"] | default([], true) %}{% set clean = tag.split(']')[-1] if ']' in tag else tag %}{% set parts = clean.split(':', 1) %}{% set key = parts[0].strip().lower() %}{% set value = parts[1].strip() if parts | length > 1 else '' %}{% set _ = ns.classic_tags.update({key: value}) %}{% endfor %}{% for key, value in event().items() if key.startswith('primary_tags.') %}{% if value is iterable and value is not string %}{% set _ = ns.grail_tags.update({key.split('.', 1)[1] | trim | lower: value | map('trim') | join(', ')}) %}{% else %}{% set _ = ns.grail_tags.update({key.split('.', 1)[1] | trim | lower: value | trim}) %}{% endif %}{% endfor %}{% set tags = {} %}{% set _ = tags.update(ns.classic_tags) %}{% set _ = tags.update(ns.grail_tags) %}{% set payload = {} %}{% if tags is mapping and tags | length > 0 %}{% set _ = payload.update({'alert_tags': tags}) %}{% endif %}{% if entityToBind is mapping and entityToBind | length > 0 %}{% if entityToBind.id is defined and entityToBind.id %}{% set _ = payload.update({'smartscape_entity_id': entityToBind.id}) %}{% endif %}{% if entityToBind.type is defined and entityToBind.type %}{% set _ = payload.update({'smartscape_entity_type': entityToBind.type}) %}{% endif %}{% if entityToBind.name is defined and entityToBind.name %}{% set _ = payload.update({'smartscape_entity_name': entityToBind.name}) %}{% endif %}{% endif %}{% set _ = payload.update({'problem_url': problem_link(),'workflow_link': execution()['workflow']['link'],'davis_problem': event()}) %}{{ payload | to_json }}