Skip to content

Commit d8b4d10

Browse files
authored
v1.9.0
2 parents 4696add + 67fc52d commit d8b4d10

35 files changed

+867
-62
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
---
2+
canonical: https://grafana.com/docs/oncall/latest/oncall-api-reference/escalation/
3+
title: Escalation HTTP API
4+
weight: 1200
5+
refs:
6+
users:
7+
- pattern: /docs/oncall/
8+
destination: /docs/oncall/<ONCALL_VERSION>/oncall-api-reference/users
9+
- pattern: /docs/grafana-cloud/
10+
destination: /docs/grafana-cloud/alerting-and-irm/oncall/oncall-api-reference/users
11+
teams:
12+
- pattern: /docs/oncall/
13+
destination: /docs/oncall/<ONCALL_VERSION>/oncall-api-reference/teams
14+
- pattern: /docs/grafana-cloud/
15+
destination: /docs/grafana-cloud/alerting-and-irm/oncall/oncall-api-reference/teams
16+
manual-paging:
17+
- pattern: /docs/oncall/
18+
destination: /docs/oncall/<ONCALL_VERSION>/configure/integrations/references/manual
19+
- pattern: /docs/grafana-cloud/
20+
destination: /docs/grafana-cloud/configure/integrations/references/manual
21+
---
22+
23+
# Escalation HTTP API
24+
25+
See [Manual paging integration](ref:manual-paging) for more background on how escalating to a team or user(s) works.
26+
27+
## Escalate to a set of users
28+
29+
For more details about how to fetch a user's Grafana OnCall ID, refer to the [Users](ref:users) public API documentation.
30+
31+
```shell
32+
curl "{{API_URL}}/api/v1/escalation/" \
33+
--request POST \
34+
--header "Authorization: meowmeowmeow" \
35+
--header "Content-Type: application/json" \
36+
--data '{
37+
"title": "We are seeing a network outage in the datacenter",
38+
"message": "I need help investigating, can you join the investigation?",
39+
"source_url": "https://github.com/myorg/myrepo/issues/123",
40+
"users": [
41+
{
42+
"id": "U281SN24AVVJX",
43+
"important": false
44+
},
45+
{
46+
"id": "U5AKCVNDEDUE7",
47+
"important": true
48+
}
49+
]
50+
}'
51+
```
52+
53+
The above command returns JSON structured in the following way:
54+
55+
```json
56+
{
57+
"id": "IZHCC4GTNPZ93",
58+
"integration_id": "CC3GZYZNIIEH5",
59+
"route_id": "RDN8LITALJXCJ",
60+
"alerts_count": 1,
61+
"state": "firing",
62+
"created_at": "2024-08-15T18:05:36.801215Z",
63+
"resolved_at": null,
64+
"resolved_by": null,
65+
"acknowledged_at": null,
66+
"acknowledged_by": null,
67+
"title": "We're seeing a network outage in the datacenter",
68+
"permalinks": {
69+
"slack": null,
70+
"slack_app": null,
71+
"telegram": null,
72+
"web": "http://<my_grafana_url>/a/grafana-oncall-app/alert-groups/I5LAZ2MXGPUAH"
73+
},
74+
"silenced_at": null
75+
}
76+
```
77+
78+
## Escalate to a team
79+
80+
For more details about how to fetch a team's Grafana OnCall ID, refer to the [Teams](ref:teams) public API documentation.
81+
82+
```shell
83+
curl "{{API_URL}}/api/v1/escalation/" \
84+
--request POST \
85+
--header "Authorization: meowmeowmeow" \
86+
--header "Content-Type: application/json" \
87+
--data '{
88+
"title": "We are seeing a network outage in the datacenter",
89+
"message": "I need help investigating, can you join the investigation?",
90+
"source_url": "https://github.com/myorg/myrepo/issues/123",
91+
"team": "TI73TDU19W48J"
92+
}'
93+
```
94+
95+
The above command returns JSON structured in the following way:
96+
97+
```json
98+
{
99+
"id": "IZHCC4GTNPZ93",
100+
"integration_id": "CC3GZYZNIIEH5",
101+
"route_id": "RDN8LITALJXCJ",
102+
"alerts_count": 1,
103+
"state": "firing",
104+
"created_at": "2024-08-15T18:05:36.801215Z",
105+
"resolved_at": null,
106+
"resolved_by": null,
107+
"acknowledged_at": null,
108+
"acknowledged_by": null,
109+
"title": "We're seeing a network outage in the datacenter",
110+
"permalinks": {
111+
"slack": null,
112+
"slack_app": null,
113+
"telegram": null,
114+
"web": "http://<my_grafana_url>/a/grafana-oncall-app/alert-groups/I5LAZ2MXGPUAH"
115+
},
116+
"silenced_at": null
117+
}
118+
```
119+
120+
## Escalate to a set of user(s) for an existing Alert Group
121+
122+
The following shows how you can escalate to a set of user(s) for an existing Alert Group.
123+
124+
```shell
125+
curl "{{API_URL}}/api/v1/escalation/" \
126+
--request POST \
127+
--header "Authorization: meowmeowmeow" \
128+
--header "Content-Type: application/json" \
129+
--data '{
130+
"alert_group_id": "IZMRNNY8RFS94",
131+
"users": [
132+
{
133+
"id": "U281SN24AVVJX",
134+
"important": false
135+
},
136+
{
137+
"id": "U5AKCVNDEDUE7",
138+
"important": true
139+
}
140+
]
141+
}'
142+
```
143+
144+
The above command returns JSON structured in the following way:
145+
146+
```json
147+
{
148+
"id": "IZHCC4GTNPZ93",
149+
"integration_id": "CC3GZYZNIIEH5",
150+
"route_id": "RDN8LITALJXCJ",
151+
"alerts_count": 1,
152+
"state": "firing",
153+
"created_at": "2024-08-15T18:05:36.801215Z",
154+
"resolved_at": null,
155+
"resolved_by": null,
156+
"acknowledged_at": null,
157+
"acknowledged_by": null,
158+
"title": "We're seeing a network outage in the datacenter",
159+
"permalinks": {
160+
"slack": null,
161+
"slack_app": null,
162+
"telegram": null,
163+
"web": "http://<my_grafana_url>/a/grafana-oncall-app/alert-groups/I5LAZ2MXGPUAH"
164+
},
165+
"silenced_at": null
166+
}
167+
```
168+
169+
| Parameter | Unique | Required | Description |
170+
| -------------------- | :----: | :--------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
171+
| `title` | No | No | Name of the Alert Group that will be created |
172+
| `message` | No | No | Content of the Alert Group that will be created |
173+
| `source_url` | No | No | Value that will be added in the Alert's payload as `oncall.permalink`. This can be useful to have the source URL/button autopopulated with a URL of interest. |
174+
| `team` | No | Yes (see [Things to Note](#things-to-note)) | Grafana OnCall team ID. If specified, will use the "Direct Paging" Integration associated with this Grafana OnCall team, to create the Alert Group. |
175+
| `users` | No | Yes (see [Things to Note](#things-to-note)) | List of user(s) to escalate to. See above request example for object schema. `id` represents the Grafana OnCall user's ID. `important` is a boolean representing whether to escalate the Alert Group using this user's default or important personal notification policy. |
176+
| `alert_group_id` | No | No | If specified, will escalate the specified users for this Alert Group. |
177+
178+
## Things to note
179+
180+
- `team` and `users` are mutually exclusive in the request payload. If you would like to escalate to a team AND user(s),
181+
first escalate to a team, then using the Alert Group ID returned in the response payload, add the required users to the
182+
existing Alert Group
183+
- `alert_group_id` is mutually exclusive with `title`, `message`, and `source_url`. Practically speaking this means that
184+
if you are trying to escalate to a set of users on an existing Alert Group, you cannot update the `title`, `message`, or
185+
`source_url` of that Alert Group
186+
- If escalating to a set of users for an existing Alert Group, the Alert Group cannot be in a resolved state
187+
188+
**HTTP request**
189+
190+
`POST {{API_URL}}/api/v1/escalation/`
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
canonical: https://grafana.com/docs/oncall/latest/oncall-api-reference/organizations/
3+
title: Grafana OnCall organizations HTTP API
4+
weight: 1500
5+
refs:
6+
pagination:
7+
- pattern: /docs/oncall/
8+
destination: /docs/oncall/<ONCALL_VERSION>/oncall-api-reference/#pagination
9+
- pattern: /docs/grafana-cloud/
10+
destination: /docs/grafana-cloud/alerting-and-irm/oncall/oncall-api-reference/#pagination
11+
---
12+
13+
# Grafana OnCall organizations HTTP API
14+
15+
## Get an organization
16+
17+
This endpoint retrieves the organization object.
18+
19+
```shell
20+
curl "{{API_URL}}/api/v1/organizations/O53AAGWFBPE5W/" \
21+
--request GET \
22+
--header "Authorization: meowmeowmeow" \
23+
--header "Content-Type: application/json"
24+
````
25+
26+
The above command returns JSON structured in the following way:
27+
28+
```json
29+
{
30+
"id": "O53AAGWFBPE5W"
31+
}
32+
```
33+
34+
**HTTP request**
35+
36+
`GET {{API_URL}}/api/v1/organizations/<ORGANIZATION_ID>/`
37+
38+
| Parameter | Unique | Description |
39+
| ---------- | :-----: | :----------------------------------------------------------------- |
40+
| `id` | Yes | Organization ID |
41+
42+
## List Organizations
43+
44+
```shell
45+
curl "{{API_URL}}/api/v1/organizations/" \
46+
--request GET \
47+
--header "Authorization: meowmeowmeow" \
48+
--header "Content-Type: application/json"
49+
```
50+
51+
The above command returns JSON structured in the following way:
52+
53+
```json
54+
{
55+
"count": 1,
56+
"next": null,
57+
"previous": null,
58+
"results": [
59+
{
60+
"id": "O53AAGWFBPE5W"
61+
}
62+
],
63+
"page_size": 25,
64+
"current_page_number": 1,
65+
"total_pages": 1
66+
}
67+
```
68+
69+
> **Note**: The response is [paginated](ref:pagination). You may need to make multiple requests to get all records.
70+
71+
**HTTP request**
72+
73+
`GET {{API_URL}}/api/v1/organizations/`
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
canonical: https://grafana.com/docs/oncall/latest/oncall-api-reference/teams/
3+
title: Grafana OnCall teams HTTP API
4+
weight: 1500
5+
refs:
6+
pagination:
7+
- pattern: /docs/oncall/
8+
destination: /docs/oncall/<ONCALL_VERSION>/oncall-api-reference/#pagination
9+
- pattern: /docs/grafana-cloud/
10+
destination: /docs/grafana-cloud/alerting-and-irm/oncall/oncall-api-reference/#pagination
11+
---
12+
13+
# Grafana OnCall teams HTTP API
14+
15+
## Get a team
16+
17+
This endpoint retrieves the team object.
18+
19+
```shell
20+
curl "{{API_URL}}/api/v1/teams/TI73TDU19W48J/" \
21+
--request GET \
22+
--header "Authorization: meowmeowmeow" \
23+
--header "Content-Type: application/json"
24+
````
25+
26+
The above command returns JSON structured in the following way:
27+
28+
```json
29+
{
30+
"id": "TI73TDU19W48J",
31+
"name": "my test team",
32+
"email": "",
33+
"avatar_url": "/avatar/3f49c15916554246daa714b9bd0ee398"
34+
}
35+
```
36+
37+
**HTTP request**
38+
39+
`GET {{API_URL}}/api/v1/teams/<TEAM_ID>/`
40+
41+
| Parameter | Unique | Description |
42+
| ---------- | :-----: | :----------------------------------------------------------------- |
43+
| `id` | Yes/org | Team ID |
44+
| `name` | Yes/org | Team name |
45+
| `email` | Yes/org | Team e-mail |
46+
| `avatar_url` | Yes | Avatar URL of the Grafana team |
47+
48+
## List Teams
49+
50+
```shell
51+
curl "{{API_URL}}/api/v1/teams/" \
52+
--request GET \
53+
--header "Authorization: meowmeowmeow" \
54+
--header "Content-Type: application/json"
55+
```
56+
57+
The above command returns JSON structured in the following way:
58+
59+
```json
60+
{
61+
"count": 1,
62+
"next": null,
63+
"previous": null,
64+
"results": [
65+
{
66+
"id": "TI73TDU19W48J",
67+
"name": "my test team",
68+
"email": "",
69+
"avatar_url": "/avatar/3f49c15916554246daa714b9bd0ee398"
70+
}
71+
],
72+
"page_size": 50,
73+
"current_page_number": 1,
74+
"total_pages": 1
75+
}
76+
```
77+
78+
> **Note**: The response is [paginated](ref:pagination). You may need to make multiple requests to get all records.
79+
80+
The following available filter parameter should be provided as a `GET` argument:
81+
82+
- `name` (Exact match)
83+
84+
**HTTP request**
85+
86+
`GET {{API_URL}}/api/v1/teams/`

engine/apps/alerts/models/alert_group.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ def get_paged_users(self) -> typing.List[PagedUser]:
559559

560560
user_ids: typing.Set[str] = set()
561561
users: typing.Dict[str, PagedUser] = {}
562+
organization = self.channel.organization
562563

563564
log_records = self.log_records.filter(
564565
type__in=(AlertGroupLogRecord.TYPE_DIRECT_PAGING, AlertGroupLogRecord.TYPE_UNPAGE_USER)
@@ -594,7 +595,7 @@ def get_paged_users(self) -> typing.List[PagedUser]:
594595
"name": user.name,
595596
"username": user.username,
596597
"avatar": user.avatar_url,
597-
"avatar_full": user.avatar_full_url,
598+
"avatar_full": user.avatar_full_url(organization),
598599
"important": important,
599600
"teams": [{"pk": t.public_primary_key, "name": t.name} for t in user.teams.all()],
600601
}

engine/apps/alerts/models/alert_group_log_record.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,10 @@ class AlertGroupLogRecord(models.Model):
230230
def render_log_line_json(self):
231231
time = humanize.naturaldelta(self.alert_group.started_at - self.created_at)
232232
created_at = DateTimeField().to_representation(self.created_at)
233-
author = self.author.short() if self.author is not None else None
233+
organization = self.alert_group.channel.organization
234+
author = self.author.short(organization) if self.author is not None else None
234235

235-
sf = SlackFormatter(self.alert_group.channel.organization)
236+
sf = SlackFormatter(organization)
236237
action = sf.format(self.rendered_log_line_action(substitute_author_with_tag=True))
237238
action = clean_markup(action)
238239

engine/apps/alerts/models/resolution_note.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,10 @@ def recreate(self):
179179
def render_log_line_json(self):
180180
time = humanize.naturaldelta(self.alert_group.started_at - self.created_at)
181181
created_at = DateTimeField().to_representation(self.created_at)
182-
author = self.author.short() if self.author is not None else None
182+
organization = self.alert_group.channel.organization
183+
author = self.author.short(organization) if self.author is not None else None
183184

184-
sf = SlackFormatter(self.alert_group.channel.organization)
185+
sf = SlackFormatter(organization)
185186
action = sf.format(self.text)
186187
action = clean_markup(action)
187188

0 commit comments

Comments
 (0)