Skip to content

Commit f892d83

Browse files
committed
(docs): add template syntax document page
1 parent a0499c2 commit f892d83

File tree

7 files changed

+259
-4
lines changed

7 files changed

+259
-4
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ An open-source incident management system with multi-channel alerting capabiliti
2222
- [Advanced API Usage](#advanced-api-usage)
2323
- [SNS Usage](#sns-usage)
2424
- [Example](#example)
25+
- [Template Syntax](https://versuscontrol.github.io/versus-incident/template_syntax.html)
2526
- [Roadmap](#roadmap)
2627
- [Contributing](#contributing)
2728
- [License](#license)

config/telegram_message.tmpl

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
🚨 <b>Critical Error Detected!</b> 🚨
22
📌 <b>Service:</b> {{.ServiceName}}
33
⚠️ <b>Error Details:</b>
4-
{{.Logs}}
4+
{{.Logs}}
5+
---
6+
{{- if contains .Logs "error" }}
7+
This is critical error
8+
{{ else }}
9+
This is warning error
10+
{{ end -}}

pkg/common/email.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/smtp"
88
"path/filepath"
99
"strconv"
10+
"strings"
1011
m "versus-incident/pkg/models"
1112
)
1213

@@ -33,8 +34,12 @@ func NewEmailProvider(cfg EmailConfig) *EmailProvider {
3334
}
3435

3536
func (e *EmailProvider) SendAlert(i *m.Incident) error {
37+
funcMapContains := template.FuncMap{
38+
"contains": strings.Contains,
39+
}
40+
3641
// Parse template
37-
tmpl, err := template.New(filepath.Base(e.templatePath)).ParseFiles(e.templatePath)
42+
tmpl, err := template.New(filepath.Base(e.templatePath)).Funcs(funcMapContains).ParseFiles(e.templatePath)
3843
if err != nil {
3944
return fmt.Errorf("failed to parse template: %w", err)
4045
}

pkg/common/slack.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package common
22

33
import (
44
"fmt"
5+
"path/filepath"
56
"strings"
67
"text/template"
78
m "versus-incident/pkg/models"
@@ -24,7 +25,11 @@ func NewSlackProvider(cfg SlackConfig) *SlackProvider {
2425
}
2526

2627
func (s *SlackProvider) SendAlert(i *m.Incident) error {
27-
tmpl, err := template.ParseFiles(s.templatePath)
28+
funcMapContains := template.FuncMap{
29+
"contains": strings.Contains,
30+
}
31+
32+
tmpl, err := template.New(filepath.Base(s.templatePath)).Funcs(funcMapContains).ParseFiles(s.templatePath)
2833
if err != nil {
2934
return fmt.Errorf("failed to parse template: %w", err)
3035
}

pkg/common/telegram.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ func (t *TelegramProvider) SendAlert(i *m.Incident) error {
3737
"replaceAll": strings.ReplaceAll,
3838
}
3939

40-
tmpl, err := template.New(filepath.Base(t.templatePath)).Funcs(funcMap).ParseFiles(t.templatePath)
40+
funcMapContains := template.FuncMap{
41+
"contains": strings.Contains,
42+
}
43+
44+
tmpl, err := template.New(filepath.Base(t.templatePath)).Funcs(funcMap).Funcs(funcMapContains).ParseFiles(t.templatePath)
4145
if err != nil {
4246
return fmt.Errorf("failed to parse template: %w", err)
4347
}

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
# User Guide
55
- [Getting Started](./getting_started.md)
6+
- [Template Syntax](./template_syntax.md)
67

78
# How to Send Error Logs to Versus Incident
89

src/template_syntax.md

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Template Syntax Guide
2+
3+
This document explains the template syntax (Go template syntax) used for create a custom alert template in Versus Incident.
4+
5+
## Table of Contents
6+
- [Basic Syntax](#basic-syntax)
7+
- [Access Data](#access-data)
8+
- [Variables](#variables)
9+
- [Pipelines](#pipelines)
10+
- [Control Structures](#control-structures)
11+
- [Conditionals (if/else)](#conditionals)
12+
- [Loops (range)](#loops)
13+
14+
15+
## Basic Syntax
16+
17+
### Access Data
18+
19+
Access data fields using double curly braces and dot notation, for example, with the data:
20+
21+
```json
22+
{
23+
"Logs": "[ERROR] This is an error log from User Service that we can obtain using Fluent Bit.",
24+
"ServiceName": "order-service",
25+
}
26+
```
27+
28+
Example template:
29+
```
30+
*Error in {{ .ServiceName }}*
31+
{{ .Logs }}
32+
```
33+
34+
### Variables
35+
You can declare variables within a template using the {{ $variable := value }} syntax. Once declared, variables can be used throughout the template, for example:
36+
37+
```
38+
{{ $owner := "Team Alpha" }}
39+
Owner: {{ $owner }}
40+
```
41+
42+
Output:
43+
```
44+
Owner: Team Alpha
45+
```
46+
47+
### Pipelines
48+
Pipelines allow you to chain together multiple actions or functions. The result of one action can be passed as input to another, for example:
49+
50+
**upper**: Converts a string to uppercase.
51+
52+
```
53+
*{{ .ServiceName | upper }} Failure*
54+
```
55+
56+
**lower**: Converts a string to lowercase.
57+
58+
```
59+
*{{ .ServiceName | lower }} Failure*
60+
```
61+
62+
**title**: Converts a string to title case (first letter of each word capitalized).
63+
64+
```
65+
*{{ .ServiceName | title }} Failure*
66+
```
67+
68+
**default**: Provides a default value if the input is empty.
69+
70+
```
71+
*{{ .ServiceName | default "unknown-service" }} Failure*
72+
```
73+
74+
**slice**: Extracts a sub-slice from a slice or string.
75+
76+
```
77+
{{ .Logs | slice 0 50 }} // First 50 characters
78+
```
79+
80+
**replace**: Replaces occurrences of a substring.
81+
82+
```
83+
{{ .Logs | replace "error" "issue" }}
84+
```
85+
86+
**trimPrefix**: Trims a prefix from a string.
87+
88+
```
89+
{{ .Logs | trimPrefix "prod-" }}
90+
```
91+
92+
**trimSuffix**: Trims a suffix from a string.
93+
94+
```
95+
{{ .Logs | trimSuffix "-service" }}
96+
```
97+
98+
**len**: Returns the length
99+
100+
```
101+
{{ .Logs | len }} // Length of the message
102+
```
103+
104+
**urlquery**: Escapes a string for use in a URL query.
105+
106+
```
107+
uri /search?q={{ .Query | urlquery }}
108+
```
109+
110+
**You can chain multiple pipes together**:
111+
112+
```
113+
{{ .Logs | trim | lower | truncate 50 }}
114+
```
115+
116+
## Control Structures
117+
118+
### Conditionals
119+
120+
The templates support conditional logic using if, else, and end keywords.
121+
122+
```
123+
{{ if .IsCritical }}
124+
🚨 CRITICAL ALERT 🚨
125+
{{ else }}
126+
⚠️ Warning Alert ⚠️
127+
{{ end }}
128+
```
129+
130+
and:
131+
132+
```
133+
{{ and .Value1 .Value2 .Value3 }}
134+
```
135+
136+
or:
137+
138+
```
139+
{{ or .Value1 .Value2 "default" }}
140+
```
141+
142+
**Best Practices**
143+
144+
Error Handling:
145+
146+
```
147+
{{ If .Error }}
148+
{{ .Details }}
149+
{{ else }}
150+
No error details
151+
{{ end }}
152+
```
153+
154+
Whitespace Control:
155+
156+
```
157+
{{- if .Production }} // Remove preceding whitespace
158+
PROD ALERT{{ end -}} // Remove trailing whitespace
159+
```
160+
161+
Template Comments:
162+
163+
```
164+
{{/* This is a hidden comment */}}
165+
```
166+
167+
Negates a boolean value:
168+
169+
```
170+
{{ if not .IsCritical }}
171+
This is not a critical issue.
172+
{{ end }}
173+
```
174+
175+
Checks if two values are equal:
176+
177+
```
178+
{{ if eq .Status "critical" }}
179+
🚨 Critical Alert 🚨
180+
{{ end }}
181+
```
182+
183+
Checks if two values are not equal:
184+
185+
```
186+
{{ if ne .Env "production" }}
187+
This is not a production environment.
188+
{{ end }}
189+
```
190+
191+
Returns the length of a string, slice, array, or map:
192+
193+
```
194+
{{ if gt (len .Errors) 0 }}
195+
There are {{ len .Errors }} errors.
196+
{{ end }}
197+
```
198+
199+
Checks if a string has a specific prefix:
200+
201+
```
202+
{{ if .ServiceName | hasPrefix "prod-" }}
203+
Production service!
204+
{{ end }}
205+
```
206+
207+
Checks if a string has a specific suffix:
208+
209+
```
210+
{{ if .ServiceName | hasSuffix "-service" }}
211+
This is a service.
212+
{{ end }}
213+
```
214+
215+
Checks if a message contains a specific strings:
216+
217+
```
218+
{{ if contains .Logs "error" }}
219+
The message contains error logs.
220+
{{ else }}
221+
The message does NOT contain error.
222+
{{ end }}
223+
```
224+
225+
### Loops
226+
227+
Iterate over slices/arrays with range:
228+
229+
```
230+
{{ range .ErrorStack }}
231+
- {{ . }}
232+
{{ end }}
233+
```

0 commit comments

Comments
 (0)