> ## Documentation Index
> Fetch the complete documentation index at: https://docs.germainux.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Edit a Template

> The GermainUX Template Editor defines the content, formatting, charts, tables, links, and actions included in alerts and reports.

Service
`Management`

Availability
8.6.0 or later

> [card] [Charts and Graphs](#charts-and-graphs)
>
> Render results as charts

> [card] [Tables](#tables)
>
> Formatted report tables

> [card] [Calls to Action](#calls-to-action)
>
> Trigger actions from alerts

> [card] [Template Context Data](#template-context-data)
>
> Objects available to templates

**Template Editor for Alerts and Reports**

The GermainUX Template Editor defines the content, formatting, charts, tables, links, and actions included in alerts and reports.

## Open a Template

| Method | Navigation |
| - | - |
| **From an SLA** | Go to **Germain Workspace > Left Menu > Analytics > SLAs**, select an SLA, and click **Edit Template**.  ![Edit a Template: Open a Template](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/image-20240327-192824.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=b360867b3fc63da2fd2f33d94d8cd137) |
| **From the Templates page** | Go to **Germain Workspace > Left Menu > System > Templates** and select a template.  ![Edit a Template: Open a Template, image 2](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/image-20260825-223249.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=773236f993d974021ebb0004214c629d) |
| **From a report** | Go to **Germain Workspace > Left Menu > Automation > Report**, select a report, and click **Edit Template** or **View Template**. |

When editing a report template, use **View** to preview the generated report and verify the result.

## Charts and Graphs

Report templates can render query results as charts. In these examples, `context.at(0)` refers to the first report result set. The `.inline(800, 400)` method embeds a chart at 800 × 400 pixels.

### Area Chart

![Edit a Template: Area Chart](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/r.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=6fa572641cc8d1155efa97b8774b76ca)

Example data:

| Series | 2023-08-01 | 2023-08-02 | 2023-08-03 | 2023-08-04 | 2023-08-05 |
| - | - | - | - | - | - |
| area1 | 4,000 | 1,700 | 2,000 | 3,500 | 5,500 |
| area2 | 2,000 | 2,000 | 2,000 | 3,000 | 3,000 |
| area3 | 12,000 | 17,000 | 9,000 | 12,000 | 13,000 |

Use `DATE` for the horizontal axis, `VALUE` for the vertical axis, and `NAME` to identify each series:

```text theme={null}
${charts.area("Area Example", context.at(0), "DATE", "VALUE", "NAME").inline(800, 400)}
```

### Bar Chart

![Edit a Template: Bar Chart](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/r2.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=180a6241393ed5f0528ffc16b4da9faf)

Example data:

| NAME | VALUE |
| - | - |
| Chrome | 55 |
| Safari | 5 |
| Firefox | 25 |
| Edge | 12 |

```text theme={null}
${charts.bar("Bar Example", context.at(0), "NAME", "VALUE").inline(800, 400)}
```

### Histogram

![Edit a Template: Histogram](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/r4.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=6c54bc6e6d164e0f5e9eb6ac41309afc)

The following expression renders `SESSION_DURATION` with a bucket size of `10` and uses `BROWSER` to identify the series:

```text theme={null}
${charts.histogram("Histogram Example", context.at(0), 10, "SESSION_DURATION", "BROWSER").inline(800, 400)}
```

### Pie Chart

![Edit a Template: Pie Chart](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/r6.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=0b7c6ea315cfeb3a8e56206375dc054b)

```text theme={null}
${charts.pie("Pie Chart", context.at(0), "NAME", "VALUE").inline(800, 400)}
```

### Ring Chart

![Edit a Template: Ring Chart](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/r7.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=d28c804f7b9c098f7640a0fb74b51d6d)

```text theme={null}
${charts.ring("Ring Chart", context.at(0), "NAME", "VALUE").inline(800, 400)}
```

### Trend Chart

![Edit a Template: Trend Chart](https://mintcdn.com/germain-ux/8KX3c-GSSWR99tdN/images/main/edit-a-template/r8.png?fit=max\&auto=format\&n=8KX3c-GSSWR99tdN\&q=85\&s=281a1a0385e5de8d6a15dadf7b7057b5)

The following expression creates a daily trend using `DATE`, `VALUE`, and `NAME`. The trend chart automatically fills gaps in the timeline:

```text theme={null}
${charts.trend("Trend Example", context.at(0), "day", "DATE", "VALUE", "NAME").inline(800, 400)}
```

## Links to GermainUX

Use the `${links}` shortcut variable to direct recipients to a GermainUX dashboard, drill-through view, or Analysis screen.

### Dashboard with a Predefined Time Range

```html theme={null}
<a href="${links.predefinedTimeRange("Last 7 days", "AUTO").dashboard("My Dashboard")}">
  Open dashboard
</a>
```

### Drill-Through for a KPI and Time Range

```html theme={null}
<a href="${links.timeRange("2024-03-09T00:00:00Z", "2024-03-10T00:00:00Z").drillthrough("CPU Usage")}">
  Open drill-through
</a>
```

### Analysis Screen for a Specific Data Point

```html theme={null}
<a href="${links.rca("CPU Usage", "65ef2a134e72ab2d1c000060")}">
  Open analysis
</a>
```

### Link-Building Order

Build methods in the same order as the corresponding GermainUX navigation path:

```text theme={null}
#PredefinedTimeRange(Today,AUTO)/Filter(Color,%3D%3D,RED,%7B%7D)/Drillthrough(User%20Click)
```

```text theme={null}
.predefinedTimeRange(...)
.filter(...)
.drillthrough(...)
```

## Tables

GermainUX provides utility functions for generating formatted tables from report results.

### Simple Result Table

```text theme={null}
${
    tables.result(context.at(0))
        .columns("TIMESTAMP", "NAME", "COLOR", "VALUE")
}
```

### Custom Table Styles

```css theme={null}
${
    tables.result(context.at(0))
        .tableStyle("padding: 5px; border: 1px solid #ddd;")
        .oddRowStyle("background-color: rgb(0, 139, 201); color: #fff; font-style: italic;")
        .evenRowStyle("background-color: #fff; font-weight: bold;")
        .columns("TIMESTAMP", "NAME", "COLOR")
}
```

### Custom Column Labels

```text theme={null}
${
    tables.result(context.at(0))
        .textColumn("TIMESTAMP", "Day")
        .textColumn("NAME", "Server Type")
        .textColumn("COLOR", "SLA Color")
        .textColumn("VALUE", "Threshold")
}
```

### Number Formatting

This example limits the fractional part to three digits and appends a percent sign:

```text theme={null}
${
    tables.result(context.at(0))
        .textColumn("VALUE", "Original")
        .numberColumn("VALUE", "Formatted", "%.3f %%")
}
```

### Date and Time Formatting

```text theme={null}
${
    tables.result(context.at(0))
        .dateTimeColumn("TIMESTAMP", "Date + Time")
        .dateColumn("TIMESTAMP", "Date")
        .timeColumn("TIMESTAMP", "Time")
}
```

### Duration Formatting

```text theme={null}
${
    tables.result(context.at(0))
        .textColumn("duration", "Unformatted")
        .durationColumn("duration", "Formatted")
}
```

### Drill-Through Link with a Custom Time Range

```text theme={null}
${
    tables.result(context.at(0))
        .dateTimeColumn("TIMESTAMP", "Timestamp")
        .linkColumn(
            tables.link(links.drillthrough("My KPI"))
                .timeRange("TIMESTAMP", 0, 60000),
            "Link"
        )
}
```

### Drill-Through Link with a Custom Filter

```text theme={null}
${
    tables.result(context.at(0))
        .textColumn("COLOR", "Color")
        .linkColumn(
            tables.link(
                links.predefinedTimeRange("Last 7 days", "AUTO")
                    .drillthrough("My KPI")
            ).filter("color", "==", "COLOR"),
            "Link"
        )
}
```

## Calls to Action

A call to action (CTA) allows an alert recipient to trigger a configured GermainUX action by clicking a link.

Examples include:

* Starting, stopping, or restarting an application, service, server, or database
* Creating a ticket in an external system
* Updating a database
* Executing SQL, a script, an SSH command, or a local program
* Generating a [report](https://docs.germainux.com/main/reporting-automatic.md)

An alert can contain multiple customized action links.

### Action-Link Parameters

| Parameter | Required | Description |
| - | - | - |
| `id` | Yes | Name of the configured GermainUX action to execute. |
| `server` | No | Server identifier or hostname passed to the action. |
| `database` | No | Database identifier or connection reference passed to the action. |
| `app` | No | Application or service identifier passed to the action. |

```html theme={null}
<a href="${workspaceUrl}action.jsp?q=trigger&id=actionname&server=serverName">Run server action</a>

<a href="${workspaceUrl}action.jsp?q=trigger&id=actionname&database=databaseName">Run database action</a>

<a href="${workspaceUrl}action.jsp?q=trigger&id=actionname&app=appName">Run application action</a>
```

Only provide action links to authorized recipients. GermainUX permissions and the target system's security controls should determine whether an action can execute.

### Service-Restart Example

```html theme={null}
<#if context.fact?? && context.fact.name?? && context.fact.system?? && context.fact.system.hostname??>
<div><strong>This alert includes a restart action:</strong></div>
<div>
  <a href="${workspaceUrl}action.jsp?q=trigger&id=restartservice&app=${context.fact.name!}&server=${context.fact.system.hostname!}">
    Restart service "${context.fact.name!}" on "${context.fact.system.hostname!}"
  </a>
</div>
</#if>
```

| Variable | Description |
| - | - |
| `${workspaceUrl}` | Automatically contains the URL of the GermainUX server. Do not modify it. |
| `${context.fact.name!}` | Name of the affected service. |
| `${context.fact.system.hostname!}` | Hostname of the affected system. |

This example executes the `restartservice` action and passes the service name through `app` and the hostname through `server`.

The `<#if>` condition prevents GermainUX from generating the link when any required value is missing. It checks:

* `context.fact`
* `context.fact.name`
* `context.fact.system`
* `context.fact.system.hostname`

## Template Context Data

Templates can reference the following root objects:

| Object | Type | Description |
| - | - | - |
| `customerName` | String | Customer associated with the alert or report. |
| `environmentName` | String | Environment associated with the alert or report. |
| `alertType` | String | Type of alert being generated. |
| `alertGroup` | String | Alert distribution group. |
| `context` | Object | Type-specific data available to the template. |
| `firstOccurred` | Date | Date and time when the condition first occurred. |
| `occurrences` | Integer | Number of occurrences associated with the alert. |

The structure of `context` depends on `alertType`. Each alert type can expose different objects, but the structure remains consistent for alerts of the same type.

### SLA Alert Context

For SLA alerts, `context.fact` can contain one of these fact types:

| Fact Type | Type |
| - | - |
| `AVAILABILITY` | Object |
| `EVENT` | Object |
| `METRIC` | Object |
| `NETWORK_LATENCY` | Object |
| `TRANSACTION` | Object |
| `UX_EVENT` | Object |
| `UX_METRIC` | Object |
| `UX_TRANSACTION` | Object |

> [!NOTE]
>
> **Note:** Statistical SLA alerts do not provide a `fact` object.

## Fact Definitions

See [Data Model and Facts](https://docs.germainux.com/main/data-model.md#facts) for the fields available to each fact type.

## Get Help

> [card] [Contact GermainUX Support](https://docs.germainux.com/main/support.md)
>
> The GermainUX team helps you get up and running faster, empower your team, turn data into actionable insights, and optimize performance to deliver measurable business outcomes.

> [card] Can't find what you need?
>
> Search all GermainUX docs with **Ctrl + K**, or use the feedback buttons at the bottom of this page to tell us what is missing.

The content of this document is proprietary to GERMAIN SOFTWARE.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.