Skip to content

Commit fef5ef3

Browse files
DTOSS-12524: Add logic-app-slack-alert module for Azure Monitor Slack notifications
1 parent 70342c8 commit fef5ef3

File tree

6 files changed

+216
-0
lines changed

6 files changed

+216
-0
lines changed

infrastructure/modules/app-insights/tfdocs.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,25 @@ Type: `map(string)`
7070

7171
Default: `{}`
7272

73+
### <a name="input_use_log_based_exception_alert"></a> [use\_log\_based\_exception\_alert](#input\_use\_log\_based\_exception\_alert)
74+
75+
Description: Replace the default metric-based exceptions alert with a log-based scheduled query alert.
76+
The log-based alert projects exception type, message, affected URL, and operation ID,
77+
which enables the Slack notification transformer to include those fields directly.
78+
Existing consumers of this module are unaffected — the default retains the metric alert.
79+
80+
Type: `bool`
81+
82+
Default: `false`
83+
7384
## Outputs
7485

7586
The following outputs are exported:
7687

88+
### <a name="output_app_id"></a> [app\_id](#output\_app\_id)
89+
90+
Description: The Application ID (GUID) used to authenticate with the App Insights REST API.
91+
7792
### <a name="output_connection_string"></a> [connection\_string](#output\_connection\_string)
7893

7994
Description: n/a
@@ -95,3 +110,4 @@ The following resources are used by this module:
95110

96111
- [azurerm_application_insights.appins](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_insights) (resource)
97112
- [azurerm_monitor_metric_alert.exceptions](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_metric_alert) (resource)
113+
- [azurerm_monitor_scheduled_query_rules_alert_v2.exceptions](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_scheduled_query_rules_alert_v2) (resource)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
resource "azurerm_logic_app_workflow" "this" {
2+
name = var.name
3+
resource_group_name = var.resource_group_name
4+
location = var.location
5+
6+
workflow_parameters = {
7+
"slackWebhookUrl" = jsonencode({
8+
type = "SecureString"
9+
defaultValue = ""
10+
})
11+
}
12+
13+
parameters = {
14+
"slackWebhookUrl" = var.slack_webhook_url
15+
}
16+
}
17+
18+
resource "azurerm_logic_app_trigger_http_request" "this" {
19+
name = "When_an_HTTP_request_is_received"
20+
logic_app_id = azurerm_logic_app_workflow.this.id
21+
method = "POST"
22+
23+
schema = jsonencode({
24+
"$schema" = "http://json-schema.org/draft-04/schema#"
25+
type = "object"
26+
properties = {
27+
schemaId = { type = "string" }
28+
data = {
29+
type = "object"
30+
properties = {
31+
essentials = {
32+
type = "object"
33+
properties = {
34+
alertRule = { type = "string" }
35+
severity = { type = "string" }
36+
firedDateTime = { type = "string" }
37+
resolvedDateTime = { type = "string" }
38+
monitorCondition = { type = "string" }
39+
description = { type = "string" }
40+
alertTargetIDs = {
41+
type = "array"
42+
items = { type = "string" }
43+
}
44+
configurationItems = {
45+
type = "array"
46+
items = { type = "string" }
47+
}
48+
}
49+
}
50+
}
51+
}
52+
}
53+
})
54+
}
55+
56+
resource "azurerm_logic_app_action_custom" "post_to_slack" {
57+
name = "Post_to_Slack"
58+
logic_app_id = azurerm_logic_app_workflow.this.id
59+
60+
body = <<-BODY
61+
{
62+
"type": "Http",
63+
"inputs": {
64+
"method": "POST",
65+
"uri": "@parameters('slackWebhookUrl')",
66+
"headers": {
67+
"Content-Type": "application/json"
68+
},
69+
"body": {
70+
"blocks": [
71+
{
72+
"type": "header",
73+
"text": {
74+
"type": "plain_text",
75+
"text": "@{if(equals(triggerBody()?['data']?['essentials']?['monitorCondition'], 'Resolved'), concat('✅ Resolved – ', triggerBody()?['data']?['essentials']?['alertRule']), concat('🚨 Alert – ', triggerBody()?['data']?['essentials']?['alertRule']))}",
76+
"emoji": true
77+
}
78+
},
79+
{
80+
"type": "section",
81+
"fields": [
82+
{
83+
"type": "mrkdwn",
84+
"text": "@{concat('*Severity*\n', triggerBody()?['data']?['essentials']?['severity'])}"
85+
},
86+
{
87+
"type": "mrkdwn",
88+
"text": "@{concat('*Status*\n', triggerBody()?['data']?['essentials']?['monitorCondition'])}"
89+
},
90+
{
91+
"type": "mrkdwn",
92+
"text": "@{concat('*Fired At*\n', triggerBody()?['data']?['essentials']?['firedDateTime'])}"
93+
},
94+
{
95+
"type": "mrkdwn",
96+
"text": "@{concat('*Resource*\n`', coalesce(triggerBody()?['data']?['essentials']?['configurationItems']?[0], 'N/A'), '`')}"
97+
}
98+
]
99+
},
100+
{
101+
"type": "section",
102+
"text": {
103+
"type": "mrkdwn",
104+
"text": "@{concat('*Description*\n> ', coalesce(triggerBody()?['data']?['essentials']?['description'], 'N/A'))}"
105+
}
106+
},
107+
{
108+
"type": "section",
109+
"text": {
110+
"type": "mrkdwn",
111+
"text": "@{if(contains(triggerBody()?['data']?['essentials']?['alertTargetIDs']?[0], 'microsoft.insights/components'), concat(':mag: <https://portal.azure.com/#resource', triggerBody()?['data']?['essentials']?['alertTargetIDs']?[0], '/failures|View Failures in App Insights>'), concat(':mag: <https://portal.azure.com/#resource', triggerBody()?['data']?['essentials']?['alertTargetIDs']?[0], '|View Resource in Azure Portal>'))}"
112+
}
113+
}
114+
]
115+
}
116+
},
117+
"runAfter": {}
118+
}
119+
BODY
120+
121+
depends_on = [azurerm_logic_app_trigger_http_request.this]
122+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
output "trigger_callback_url" {
2+
description = "HTTP trigger callback URL to register with an Azure Monitor action group webhook receiver."
3+
value = azurerm_logic_app_trigger_http_request.this.callback_url
4+
sensitive = true
5+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Module documentation
2+
3+
## Required Inputs
4+
5+
The following input variables are required:
6+
7+
### <a name="input_location"></a> [location](#input\_location)
8+
9+
Description: Azure region in which to create the Logic App.
10+
11+
Type: `string`
12+
13+
### <a name="input_name"></a> [name](#input\_name)
14+
15+
Description: Name of the Logic App workflow.
16+
17+
Type: `string`
18+
19+
### <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name)
20+
21+
Description: Resource group in which to create the Logic App.
22+
23+
Type: `string`
24+
25+
### <a name="input_slack_webhook_url"></a> [slack\_webhook\_url](#input\_slack\_webhook\_url)
26+
27+
Description: Slack incoming webhook URL. Stored as a SecureString workflow parameter.
28+
29+
Type: `string`
30+
31+
## Outputs
32+
33+
The following outputs are exported:
34+
35+
### <a name="output_trigger_callback_url"></a> [trigger\_callback\_url](#output\_trigger\_callback\_url)
36+
37+
Description: HTTP trigger callback URL to register with an Azure Monitor action group webhook receiver.
38+
## Resources
39+
40+
The following resources are used by this module:
41+
42+
- [azurerm_logic_app_action_custom.post_to_slack](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/logic_app_action_custom) (resource)
43+
- [azurerm_logic_app_trigger_http_request.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/logic_app_trigger_http_request) (resource)
44+
- [azurerm_logic_app_workflow.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/logic_app_workflow) (resource)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
variable "name" {
2+
type = string
3+
description = "Name of the Logic App workflow."
4+
}
5+
6+
variable "resource_group_name" {
7+
type = string
8+
description = "Resource group in which to create the Logic App."
9+
}
10+
11+
variable "location" {
12+
type = string
13+
description = "Azure region in which to create the Logic App."
14+
}
15+
16+
variable "slack_webhook_url" {
17+
type = string
18+
description = "Slack incoming webhook URL. Stored as a SecureString workflow parameter."
19+
sensitive = true
20+
}

infrastructure/modules/virtual-desktop/tfdocs.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ Type: `number`
168168

169169
Default: `16`
170170

171+
### <a name="input_principal_id"></a> [principal\_id](#input\_principal\_id)
172+
173+
Description: The principal (object) ID to assign the 'Desktop Virtualization Power On Off Contributor' role to the host pool. If null, the role assignment will not be created. This maintains backward compatibility for existing deployments. The role is required for autoscaling but can be omitted if autoscaling is not used or the role is assigned manually.
174+
175+
Type: `string`
176+
177+
Default: `null`
178+
171179
### <a name="input_source_image_from_gallery"></a> [source\_image\_from\_gallery](#input\_source\_image\_from\_gallery)
172180

173181
Description: n/a
@@ -279,6 +287,7 @@ Default: `null`
279287
The following resources are used by this module:
280288

281289
- [azurerm_network_interface.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface) (resource)
290+
- [azurerm_role_assignment.avd_autoscale_hostpool](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource)
282291
- [azurerm_role_assignment.dag_admins](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource)
283292
- [azurerm_role_assignment.dag_users](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource)
284293
- [azurerm_role_assignment.rg_admins](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource)

0 commit comments

Comments
 (0)