auto-data-alerts 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- auto_data_alerts/__init__.py +1 -0
- auto_data_alerts/_modidx.py +177 -0
- auto_data_alerts/block_builder.py +323 -0
- auto_data_alerts/core.py +47 -0
- auto_data_alerts/interaction_builder.py +490 -0
- auto_data_alerts/message_formating.py +263 -0
- auto_data_alerts/message_templates.py +218 -0
- auto_data_alerts/slack_api.py +112 -0
- auto_data_alerts/snowflake.py +211 -0
- auto_data_alerts/template_engine.py +14 -0
- auto_data_alerts/templates.py +1066 -0
- auto_data_alerts-0.0.1.dist-info/METADATA +88 -0
- auto_data_alerts-0.0.1.dist-info/RECORD +16 -0
- auto_data_alerts-0.0.1.dist-info/WHEEL +5 -0
- auto_data_alerts-0.0.1.dist-info/entry_points.txt +2 -0
- auto_data_alerts-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.1"
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Autogenerated by nbdev
|
|
2
|
+
|
|
3
|
+
d = { 'settings': { 'branch': 'main',
|
|
4
|
+
'doc_baseurl': '/auto-data-alerts',
|
|
5
|
+
'doc_host': 'https://cooper-richason.github.io',
|
|
6
|
+
'git_url': 'https://github.com/cooper-richason/auto-data-alerts',
|
|
7
|
+
'lib_path': 'auto_data_alerts'},
|
|
8
|
+
'syms': { 'auto_data_alerts.block_builder': { 'auto_data_alerts.block_builder.SlackBlockBuilder': ( 'API/Templating/block_builder.html#slackblockbuilder',
|
|
9
|
+
'auto_data_alerts/block_builder.py'),
|
|
10
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_context_block': ( 'API/Templating/block_builder.html#slackblockbuilder.create_context_block',
|
|
11
|
+
'auto_data_alerts/block_builder.py'),
|
|
12
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_divider': ( 'API/Templating/block_builder.html#slackblockbuilder.create_divider',
|
|
13
|
+
'auto_data_alerts/block_builder.py'),
|
|
14
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_field': ( 'API/Templating/block_builder.html#slackblockbuilder.create_field',
|
|
15
|
+
'auto_data_alerts/block_builder.py'),
|
|
16
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_fields_section': ( 'API/Templating/block_builder.html#slackblockbuilder.create_fields_section',
|
|
17
|
+
'auto_data_alerts/block_builder.py'),
|
|
18
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_header_block': ( 'API/Templating/block_builder.html#slackblockbuilder.create_header_block',
|
|
19
|
+
'auto_data_alerts/block_builder.py'),
|
|
20
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_metadata_context': ( 'API/Templating/block_builder.html#slackblockbuilder.create_metadata_context',
|
|
21
|
+
'auto_data_alerts/block_builder.py'),
|
|
22
|
+
'auto_data_alerts.block_builder.SlackBlockBuilder.create_section_block': ( 'API/Templating/block_builder.html#slackblockbuilder.create_section_block',
|
|
23
|
+
'auto_data_alerts/block_builder.py'),
|
|
24
|
+
'auto_data_alerts.block_builder.SlackMessenger': ( 'API/Templating/block_builder.html#slackmessenger',
|
|
25
|
+
'auto_data_alerts/block_builder.py'),
|
|
26
|
+
'auto_data_alerts.block_builder.SlackMessenger._format_data_for_logging': ( 'API/Templating/block_builder.html#slackmessenger._format_data_for_logging',
|
|
27
|
+
'auto_data_alerts/block_builder.py'),
|
|
28
|
+
'auto_data_alerts.block_builder.SlackMessenger._log_alert': ( 'API/Templating/block_builder.html#slackmessenger._log_alert',
|
|
29
|
+
'auto_data_alerts/block_builder.py'),
|
|
30
|
+
'auto_data_alerts.block_builder.SlackMessenger._send_alert_to_slack': ( 'API/Templating/block_builder.html#slackmessenger._send_alert_to_slack',
|
|
31
|
+
'auto_data_alerts/block_builder.py'),
|
|
32
|
+
'auto_data_alerts.block_builder.SlackMessenger.create_header_block': ( 'API/Templating/block_builder.html#slackmessenger.create_header_block',
|
|
33
|
+
'auto_data_alerts/block_builder.py'),
|
|
34
|
+
'auto_data_alerts.block_builder.SlackMessenger.get_metadata': ( 'API/Templating/block_builder.html#slackmessenger.get_metadata',
|
|
35
|
+
'auto_data_alerts/block_builder.py'),
|
|
36
|
+
'auto_data_alerts.block_builder.SlackMessenger.process_section_row': ( 'API/Templating/block_builder.html#slackmessenger.process_section_row',
|
|
37
|
+
'auto_data_alerts/block_builder.py')},
|
|
38
|
+
'auto_data_alerts.core': {'auto_data_alerts.core.send_alert': ('API/core.html#send_alert', 'auto_data_alerts/core.py')},
|
|
39
|
+
'auto_data_alerts.interaction_builder': { 'auto_data_alerts.interaction_builder.InteractionBuilder': ( 'API/Templating/interection_builder.html#interactionbuilder',
|
|
40
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
41
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_actions_block': ( 'API/Templating/interection_builder.html#interactionbuilder.create_actions_block',
|
|
42
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
43
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_button': ( 'API/Templating/interection_builder.html#interactionbuilder.create_button',
|
|
44
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
45
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_channels_select': ( 'API/Templating/interection_builder.html#interactionbuilder.create_channels_select',
|
|
46
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
47
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_datepicker': ( 'API/Templating/interection_builder.html#interactionbuilder.create_datepicker',
|
|
48
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
49
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_multi_select': ( 'API/Templating/interection_builder.html#interactionbuilder.create_multi_select',
|
|
50
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
51
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_static_select': ( 'API/Templating/interection_builder.html#interactionbuilder.create_static_select',
|
|
52
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
53
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.create_users_select': ( 'API/Templating/interection_builder.html#interactionbuilder.create_users_select',
|
|
54
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
55
|
+
'auto_data_alerts.interaction_builder.InteractionBuilder.detect_and_create_interactive_elements': ( 'API/Templating/interection_builder.html#interactionbuilder.detect_and_create_interactive_elements',
|
|
56
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
57
|
+
'auto_data_alerts.interaction_builder.SlackMessenger': ( 'API/Templating/interection_builder.html#slackmessenger',
|
|
58
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
59
|
+
'auto_data_alerts.interaction_builder.SlackMessenger._format_data_for_logging': ( 'API/Templating/interection_builder.html#slackmessenger._format_data_for_logging',
|
|
60
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
61
|
+
'auto_data_alerts.interaction_builder.SlackMessenger._log_alert': ( 'API/Templating/interection_builder.html#slackmessenger._log_alert',
|
|
62
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
63
|
+
'auto_data_alerts.interaction_builder.SlackMessenger._send_alert_to_slack': ( 'API/Templating/interection_builder.html#slackmessenger._send_alert_to_slack',
|
|
64
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
65
|
+
'auto_data_alerts.interaction_builder.SlackMessenger.create_header_block': ( 'API/Templating/interection_builder.html#slackmessenger.create_header_block',
|
|
66
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
67
|
+
'auto_data_alerts.interaction_builder.SlackMessenger.get_metadata': ( 'API/Templating/interection_builder.html#slackmessenger.get_metadata',
|
|
68
|
+
'auto_data_alerts/interaction_builder.py'),
|
|
69
|
+
'auto_data_alerts.interaction_builder.SlackMessenger.process_section_row': ( 'API/Templating/interection_builder.html#slackmessenger.process_section_row',
|
|
70
|
+
'auto_data_alerts/interaction_builder.py')},
|
|
71
|
+
'auto_data_alerts.message_formating': { 'auto_data_alerts.message_formating.ColumnUtils': ( 'API/message_formating.html#columnutils',
|
|
72
|
+
'auto_data_alerts/message_formating.py'),
|
|
73
|
+
'auto_data_alerts.message_formating.ColumnUtils.get_column_synonyms': ( 'API/message_formating.html#columnutils.get_column_synonyms',
|
|
74
|
+
'auto_data_alerts/message_formating.py'),
|
|
75
|
+
'auto_data_alerts.message_formating.ColumnUtils.get_detail_columns': ( 'API/message_formating.html#columnutils.get_detail_columns',
|
|
76
|
+
'auto_data_alerts/message_formating.py'),
|
|
77
|
+
'auto_data_alerts.message_formating.ColumnUtils.normalize_columns': ( 'API/message_formating.html#columnutils.normalize_columns',
|
|
78
|
+
'auto_data_alerts/message_formating.py'),
|
|
79
|
+
'auto_data_alerts.message_formating.DebugLogger': ( 'API/message_formating.html#debuglogger',
|
|
80
|
+
'auto_data_alerts/message_formating.py'),
|
|
81
|
+
'auto_data_alerts.message_formating.DebugLogger.log': ( 'API/message_formating.html#debuglogger.log',
|
|
82
|
+
'auto_data_alerts/message_formating.py'),
|
|
83
|
+
'auto_data_alerts.message_formating.SlackFormatter': ( 'API/message_formating.html#slackformatter',
|
|
84
|
+
'auto_data_alerts/message_formating.py'),
|
|
85
|
+
'auto_data_alerts.message_formating.SlackFormatter.format_section_name': ( 'API/message_formating.html#slackformatter.format_section_name',
|
|
86
|
+
'auto_data_alerts/message_formating.py'),
|
|
87
|
+
'auto_data_alerts.message_formating.SlackFormatter.right_hand_details': ( 'API/message_formating.html#slackformatter.right_hand_details',
|
|
88
|
+
'auto_data_alerts/message_formating.py'),
|
|
89
|
+
'auto_data_alerts.message_formating.ValueFormatter': ( 'API/message_formating.html#valueformatter',
|
|
90
|
+
'auto_data_alerts/message_formating.py'),
|
|
91
|
+
'auto_data_alerts.message_formating.ValueFormatter.format_value': ( 'API/message_formating.html#valueformatter.format_value',
|
|
92
|
+
'auto_data_alerts/message_formating.py'),
|
|
93
|
+
'auto_data_alerts.message_formating.f1_section_name': ( 'API/message_formating.html#f1_section_name',
|
|
94
|
+
'auto_data_alerts/message_formating.py'),
|
|
95
|
+
'auto_data_alerts.message_formating.format_value': ( 'API/message_formating.html#format_value',
|
|
96
|
+
'auto_data_alerts/message_formating.py'),
|
|
97
|
+
'auto_data_alerts.message_formating.get_detail_columns': ( 'API/message_formating.html#get_detail_columns',
|
|
98
|
+
'auto_data_alerts/message_formating.py'),
|
|
99
|
+
'auto_data_alerts.message_formating.right_hand_details': ( 'API/message_formating.html#right_hand_details',
|
|
100
|
+
'auto_data_alerts/message_formating.py')},
|
|
101
|
+
'auto_data_alerts.message_templates': { 'auto_data_alerts.message_templates.SlackMessageTemplate': ( 'API/Templating/message_templates.html#slackmessagetemplate',
|
|
102
|
+
'auto_data_alerts/message_templates.py'),
|
|
103
|
+
'auto_data_alerts.message_templates.SlackMessageTemplate._send_messages_and_log': ( 'API/Templating/message_templates.html#slackmessagetemplate._send_messages_and_log',
|
|
104
|
+
'auto_data_alerts/message_templates.py'),
|
|
105
|
+
'auto_data_alerts.message_templates.SlackMessageTemplate.template_f1': ( 'API/Templating/message_templates.html#slackmessagetemplate.template_f1',
|
|
106
|
+
'auto_data_alerts/message_templates.py'),
|
|
107
|
+
'auto_data_alerts.message_templates.SlackMessageTemplate.template_f2': ( 'API/Templating/message_templates.html#slackmessagetemplate.template_f2',
|
|
108
|
+
'auto_data_alerts/message_templates.py')},
|
|
109
|
+
'auto_data_alerts.slack_api': { 'auto_data_alerts.slack_api.find_dm_channel': ( 'API/slack_api.html#find_dm_channel',
|
|
110
|
+
'auto_data_alerts/slack_api.py'),
|
|
111
|
+
'auto_data_alerts.slack_api.find_slack_member': ( 'API/slack_api.html#find_slack_member',
|
|
112
|
+
'auto_data_alerts/slack_api.py'),
|
|
113
|
+
'auto_data_alerts.slack_api.get_slack_members': ( 'API/slack_api.html#get_slack_members',
|
|
114
|
+
'auto_data_alerts/slack_api.py'),
|
|
115
|
+
'auto_data_alerts.slack_api.send_to_slack': ( 'API/slack_api.html#send_to_slack',
|
|
116
|
+
'auto_data_alerts/slack_api.py')},
|
|
117
|
+
'auto_data_alerts.snowflake': { 'auto_data_alerts.snowflake.connect': ( 'API/snowflake.html#connect',
|
|
118
|
+
'auto_data_alerts/snowflake.py'),
|
|
119
|
+
'auto_data_alerts.snowflake.get_channel_config': ( 'API/snowflake.html#get_channel_config',
|
|
120
|
+
'auto_data_alerts/snowflake.py'),
|
|
121
|
+
'auto_data_alerts.snowflake.get_df_data': ( 'API/snowflake.html#get_df_data',
|
|
122
|
+
'auto_data_alerts/snowflake.py'),
|
|
123
|
+
'auto_data_alerts.snowflake.get_view_configs': ( 'API/snowflake.html#get_view_configs',
|
|
124
|
+
'auto_data_alerts/snowflake.py'),
|
|
125
|
+
'auto_data_alerts.snowflake.get_view_data': ( 'API/snowflake.html#get_view_data',
|
|
126
|
+
'auto_data_alerts/snowflake.py'),
|
|
127
|
+
'auto_data_alerts.snowflake.get_views': ( 'API/snowflake.html#get_views',
|
|
128
|
+
'auto_data_alerts/snowflake.py'),
|
|
129
|
+
'auto_data_alerts.snowflake.log_alert_history': ( 'API/snowflake.html#log_alert_history',
|
|
130
|
+
'auto_data_alerts/snowflake.py')},
|
|
131
|
+
'auto_data_alerts.template_engine': {},
|
|
132
|
+
'auto_data_alerts.templates': { 'auto_data_alerts.templates.SlackMessenger': ( 'API/templates.html#slackmessenger',
|
|
133
|
+
'auto_data_alerts/templates.py'),
|
|
134
|
+
'auto_data_alerts.templates.SlackMessenger._format_data_for_logging': ( 'API/templates.html#slackmessenger._format_data_for_logging',
|
|
135
|
+
'auto_data_alerts/templates.py'),
|
|
136
|
+
'auto_data_alerts.templates.SlackMessenger._log_alert': ( 'API/templates.html#slackmessenger._log_alert',
|
|
137
|
+
'auto_data_alerts/templates.py'),
|
|
138
|
+
'auto_data_alerts.templates.SlackMessenger._send_alert_to_slack': ( 'API/templates.html#slackmessenger._send_alert_to_slack',
|
|
139
|
+
'auto_data_alerts/templates.py'),
|
|
140
|
+
'auto_data_alerts.templates.SlackMessenger.create_header_block': ( 'API/templates.html#slackmessenger.create_header_block',
|
|
141
|
+
'auto_data_alerts/templates.py'),
|
|
142
|
+
'auto_data_alerts.templates.SlackMessenger.get_metadata': ( 'API/templates.html#slackmessenger.get_metadata',
|
|
143
|
+
'auto_data_alerts/templates.py'),
|
|
144
|
+
'auto_data_alerts.templates.SlackMessenger.process_section_row': ( 'API/templates.html#slackmessenger.process_section_row',
|
|
145
|
+
'auto_data_alerts/templates.py'),
|
|
146
|
+
'auto_data_alerts.templates.SlackTemplates': ( 'API/templates.html#slacktemplates',
|
|
147
|
+
'auto_data_alerts/templates.py'),
|
|
148
|
+
'auto_data_alerts.templates.SlackTemplates.create_actions_block': ( 'API/templates.html#slacktemplates.create_actions_block',
|
|
149
|
+
'auto_data_alerts/templates.py'),
|
|
150
|
+
'auto_data_alerts.templates.SlackTemplates.create_button': ( 'API/templates.html#slacktemplates.create_button',
|
|
151
|
+
'auto_data_alerts/templates.py'),
|
|
152
|
+
'auto_data_alerts.templates.SlackTemplates.create_context_block': ( 'API/templates.html#slacktemplates.create_context_block',
|
|
153
|
+
'auto_data_alerts/templates.py'),
|
|
154
|
+
'auto_data_alerts.templates.SlackTemplates.create_divider': ( 'API/templates.html#slacktemplates.create_divider',
|
|
155
|
+
'auto_data_alerts/templates.py'),
|
|
156
|
+
'auto_data_alerts.templates.SlackTemplates.template_f1': ( 'API/templates.html#slacktemplates.template_f1',
|
|
157
|
+
'auto_data_alerts/templates.py'),
|
|
158
|
+
'auto_data_alerts.templates.SlackTemplates.template_f2_summary_with_expand': ( 'API/templates.html#slacktemplates.template_f2_summary_with_expand',
|
|
159
|
+
'auto_data_alerts/templates.py'),
|
|
160
|
+
'auto_data_alerts.templates.SlackTemplates.template_f3_grouped_data': ( 'API/templates.html#slacktemplates.template_f3_grouped_data',
|
|
161
|
+
'auto_data_alerts/templates.py'),
|
|
162
|
+
'auto_data_alerts.templates.SlackTemplates.template_f4_metrics_dashboard': ( 'API/templates.html#slacktemplates.template_f4_metrics_dashboard',
|
|
163
|
+
'auto_data_alerts/templates.py'),
|
|
164
|
+
'auto_data_alerts.templates.SlackTemplates.template_f5': ( 'API/templates.html#slacktemplates.template_f5',
|
|
165
|
+
'auto_data_alerts/templates.py'),
|
|
166
|
+
'auto_data_alerts.templates._f1_process_row': ( 'API/templates.html#_f1_process_row',
|
|
167
|
+
'auto_data_alerts/templates.py'),
|
|
168
|
+
'auto_data_alerts.templates._get_metadata': ( 'API/templates.html#_get_metadata',
|
|
169
|
+
'auto_data_alerts/templates.py'),
|
|
170
|
+
'auto_data_alerts.templates.template_f1': ( 'API/templates.html#template_f1',
|
|
171
|
+
'auto_data_alerts/templates.py'),
|
|
172
|
+
'auto_data_alerts.templates.template_f2_summary_with_expand': ( 'API/templates.html#template_f2_summary_with_expand',
|
|
173
|
+
'auto_data_alerts/templates.py'),
|
|
174
|
+
'auto_data_alerts.templates.template_f3_grouped_data': ( 'API/templates.html#template_f3_grouped_data',
|
|
175
|
+
'auto_data_alerts/templates.py'),
|
|
176
|
+
'auto_data_alerts.templates.template_f4_metrics_dashboard': ( 'API/templates.html#template_f4_metrics_dashboard',
|
|
177
|
+
'auto_data_alerts/templates.py')}}}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/API/Templating/01_block_builder.ipynb.
|
|
2
|
+
|
|
3
|
+
# %% auto #0
|
|
4
|
+
__all__ = ['SlackMessenger', 'SlackBlockBuilder']
|
|
5
|
+
|
|
6
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #b08569f3
|
|
7
|
+
from fastcore.basics import patch_to
|
|
8
|
+
from fastcore.test import *
|
|
9
|
+
from typing import List, Tuple, Dict, Any, Callable, Optional
|
|
10
|
+
from .message_formating import *
|
|
11
|
+
import pandas as pd
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #96efc7df
|
|
15
|
+
class SlackMessenger:
|
|
16
|
+
"""Handles creation and sending of Slack messages in various templates."""
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def process_section_row(section_text: str, detail_text: str) -> Dict[str, Any]:
|
|
20
|
+
"""Create Slack message section block.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
section_text: Main section text with markdown formatting
|
|
24
|
+
detail_text: Detailed information with markdown formatting
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Slack block kit section object
|
|
28
|
+
"""
|
|
29
|
+
return {
|
|
30
|
+
"type": "section",
|
|
31
|
+
"fields": [
|
|
32
|
+
{"type": "mrkdwn", "text": section_text},
|
|
33
|
+
{"type": "mrkdwn", "text": detail_text}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def create_header_block(title: str) -> Dict[str, Any]:
|
|
39
|
+
"""Create a header block for Slack messages.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
title: The title text for the header
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Slack block kit header object
|
|
46
|
+
"""
|
|
47
|
+
return {
|
|
48
|
+
"type": "header",
|
|
49
|
+
"text": {"type": "plain_text", "text": title, "emoji": True}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def get_metadata(row: pd.Series, df_columns: List[str]) -> Dict[str, Any]:
|
|
54
|
+
"""Extract metadata from row for logging.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
row: DataFrame row
|
|
58
|
+
df_columns: List of column names
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Dictionary of column values
|
|
62
|
+
"""
|
|
63
|
+
# Fixed the incorrect implementation
|
|
64
|
+
return {column: row.get(column) for column in df_columns}
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def _send_alert_to_slack(
|
|
68
|
+
send_to_slack_func: callable,
|
|
69
|
+
channel_id: str,
|
|
70
|
+
message_text: str,
|
|
71
|
+
payload_blocks: List[Dict[str, Any]],
|
|
72
|
+
view: str
|
|
73
|
+
) -> Tuple[bool, Optional[Dict[str, Any]]]:
|
|
74
|
+
"""Send alert to Slack and handle response.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
send_to_slack_func: Function to send messages to Slack
|
|
78
|
+
channel_id: Slack channel ID
|
|
79
|
+
message_text: Main message text
|
|
80
|
+
payload_blocks: Slack blocks to send
|
|
81
|
+
view: View name for logging
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Tuple of (success_flag, error_details)
|
|
85
|
+
"""
|
|
86
|
+
try:
|
|
87
|
+
response = send_to_slack_func(channel_id, message_text, payload_blocks=payload_blocks)
|
|
88
|
+
DebugLogger.log(f'Response: {response.text if hasattr(response, "text") else response}')
|
|
89
|
+
|
|
90
|
+
# Check response
|
|
91
|
+
if hasattr(response, 'status_code') and response.status_code == 200:
|
|
92
|
+
# Handle JSON response
|
|
93
|
+
if hasattr(response, 'json'):
|
|
94
|
+
try:
|
|
95
|
+
json_response = response.json()
|
|
96
|
+
if json_response.get('ok'):
|
|
97
|
+
print(f' Alert sent for {view}')
|
|
98
|
+
return True, None
|
|
99
|
+
except Exception as json_err:
|
|
100
|
+
print(f' Error parsing JSON response for {view}: {json_err}')
|
|
101
|
+
return False, {'slack_api_error': f'JSON parse error: {str(json_err)}'}
|
|
102
|
+
else:
|
|
103
|
+
# Simple success response
|
|
104
|
+
print(f' Alert sent for {view}')
|
|
105
|
+
return True, None
|
|
106
|
+
|
|
107
|
+
# Handle error response
|
|
108
|
+
error_text = response.text if hasattr(response, 'text') else str(response)
|
|
109
|
+
print(f' Error sending alert for {view}: {error_text}')
|
|
110
|
+
return False, {'slack_api_error': error_text}
|
|
111
|
+
|
|
112
|
+
except Exception as e:
|
|
113
|
+
print(f' Error sending alert for {view}: {e}')
|
|
114
|
+
return False, {'slack_api_error': str(e)}
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def _format_data_for_logging(df: pd.DataFrame) -> List[Dict[str, Any]]:
|
|
118
|
+
"""Format DataFrame data for logging.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
df: DataFrame with alert data
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
List of dictionaries with formatted values
|
|
125
|
+
"""
|
|
126
|
+
return [{
|
|
127
|
+
key: ValueFormatter.format_value(value)
|
|
128
|
+
for key, value in row.items()
|
|
129
|
+
} for row in df.to_dict('records')]
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def _log_alert(
|
|
133
|
+
log_alert_history_func: callable,
|
|
134
|
+
view: str,
|
|
135
|
+
view_group: str,
|
|
136
|
+
channel_id: str,
|
|
137
|
+
success: bool,
|
|
138
|
+
error_details: Optional[Dict[str, Any]],
|
|
139
|
+
formatted_data: List[Dict[str, Any]],
|
|
140
|
+
message_text: str
|
|
141
|
+
) -> None:
|
|
142
|
+
"""Log alert history.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
log_alert_history_func: Function to log alert history
|
|
146
|
+
view: View name
|
|
147
|
+
view_group: Group name for the view
|
|
148
|
+
channel_id: Slack channel ID
|
|
149
|
+
success: Whether the alert was sent successfully
|
|
150
|
+
error_details: Details of any error
|
|
151
|
+
formatted_data: Formatted data for logging
|
|
152
|
+
message_text: Main message text
|
|
153
|
+
"""
|
|
154
|
+
try:
|
|
155
|
+
log_alert_history_func(
|
|
156
|
+
related_view=view,
|
|
157
|
+
team=view_group,
|
|
158
|
+
channel=channel_id,
|
|
159
|
+
rows_grouped=True,
|
|
160
|
+
row_num=None,
|
|
161
|
+
data=formatted_data,
|
|
162
|
+
was_success=success,
|
|
163
|
+
error_details=error_details,
|
|
164
|
+
message_details={'format': 'f1', 'message_text': message_text}
|
|
165
|
+
)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
print(f"Error logging alert history: {e}")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #465365d7
|
|
171
|
+
class SlackBlockBuilder:
|
|
172
|
+
"""
|
|
173
|
+
Utility class for building Slack Block Kit elements.
|
|
174
|
+
Provides methods to create various block types for Slack messages.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
pass
|
|
178
|
+
|
|
179
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #bf4a6596
|
|
180
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
181
|
+
def create_header_block(self, text: str) -> Dict[str, Any]:
|
|
182
|
+
"""Create a header block for Slack messages.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
text: The text to display in the header
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Slack block kit header object
|
|
189
|
+
"""
|
|
190
|
+
return {
|
|
191
|
+
"type": "header",
|
|
192
|
+
"text": {
|
|
193
|
+
"type": "plain_text",
|
|
194
|
+
"text": text,
|
|
195
|
+
"emoji": True
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #972b8523
|
|
200
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
201
|
+
def create_section_block(self, text: str, fields: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
|
|
202
|
+
"""Create a section block for Slack messages.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
text: The text to display in the section
|
|
206
|
+
fields: Optional list of field objects for the section
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Slack block kit section object
|
|
210
|
+
"""
|
|
211
|
+
section = {
|
|
212
|
+
"type": "section",
|
|
213
|
+
"text": {
|
|
214
|
+
"type": "mrkdwn",
|
|
215
|
+
"text": text
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if fields:
|
|
220
|
+
section["fields"] = fields
|
|
221
|
+
|
|
222
|
+
return section
|
|
223
|
+
|
|
224
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #34702c77
|
|
225
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
226
|
+
def create_field(self, title: str, value: str) -> Dict[str, Any]:
|
|
227
|
+
"""Create a field for a section block.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
title: The title of the field (will be bolded)
|
|
231
|
+
value: The value of the field
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Field object for use in section blocks
|
|
235
|
+
"""
|
|
236
|
+
return {
|
|
237
|
+
"type": "mrkdwn",
|
|
238
|
+
"text": f"*{title}*\n{value}"
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #372af04b
|
|
242
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
243
|
+
def create_fields_section(self, fields_data: List[Tuple[str, str]], max_fields_per_section: int = 10) -> List[Dict[str, Any]]:
|
|
244
|
+
"""Create one or more section blocks with fields.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
fields_data: List of (label, value) tuples
|
|
248
|
+
max_fields_per_section: Maximum fields per section (Slack limit is 10)
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
List of section blocks
|
|
252
|
+
"""
|
|
253
|
+
if not fields_data: return []
|
|
254
|
+
|
|
255
|
+
# Create field objects
|
|
256
|
+
fields = [
|
|
257
|
+
SlackBlockBuilder.create_field(label, value)
|
|
258
|
+
for label, value in fields_data
|
|
259
|
+
if value # Only include non-empty values
|
|
260
|
+
]
|
|
261
|
+
|
|
262
|
+
if not fields: return []
|
|
263
|
+
|
|
264
|
+
# Split into multiple sections if needed
|
|
265
|
+
sections = []
|
|
266
|
+
for i in range(0, len(fields), max_fields_per_section):
|
|
267
|
+
section_fields = fields[i:i + max_fields_per_section]
|
|
268
|
+
sections.append({
|
|
269
|
+
"type": "section",
|
|
270
|
+
"fields": section_fields
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
return sections
|
|
274
|
+
|
|
275
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #5872028e
|
|
276
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
277
|
+
def create_context_block(self, text: str) -> Dict[str, Any]:
|
|
278
|
+
"""Create a context block for Slack messages.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
text: The text to show in the context block
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Slack block kit context object
|
|
285
|
+
"""
|
|
286
|
+
return {
|
|
287
|
+
"type": "context",
|
|
288
|
+
"elements": [
|
|
289
|
+
{
|
|
290
|
+
"type": "mrkdwn",
|
|
291
|
+
"text": text
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #84bc9751
|
|
297
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
298
|
+
def create_divider(self) -> Dict[str, str]:
|
|
299
|
+
"""Create a divider block for Slack messages.
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
Slack block kit divider object
|
|
303
|
+
"""
|
|
304
|
+
return {"type": "divider"}
|
|
305
|
+
|
|
306
|
+
# %% ../nbs/API/Templating/01_block_builder.ipynb #aaa964ef
|
|
307
|
+
@patch_to(SlackBlockBuilder,cls_method=True)
|
|
308
|
+
def create_metadata_context(self, metadata_items: List[Tuple[str, str|List|dict]]) -> Dict[str, Any]:
|
|
309
|
+
"""Create a context block for metadata items.
|
|
310
|
+
|
|
311
|
+
Args:
|
|
312
|
+
metadata_items: List of (label, value) tuples
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
Formatted metadata field
|
|
316
|
+
"""
|
|
317
|
+
meta_parts = {}
|
|
318
|
+
for label, value in metadata_items:
|
|
319
|
+
if value: meta_parts[label]=value
|
|
320
|
+
|
|
321
|
+
if not meta_parts: return None
|
|
322
|
+
|
|
323
|
+
return {'metadata':meta_parts}
|
auto_data_alerts/core.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Fill in a module description here"""
|
|
2
|
+
|
|
3
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/API/core.ipynb.
|
|
4
|
+
|
|
5
|
+
# %% auto #0
|
|
6
|
+
__all__ = ['send_alert']
|
|
7
|
+
|
|
8
|
+
# %% ../nbs/API/core.ipynb #e60c4322
|
|
9
|
+
from .templates import SlackTemplates, template_f1
|
|
10
|
+
from .snowflake import *
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
# %% ../nbs/API/core.ipynb #58e22cf4
|
|
14
|
+
def send_alert(view,view_group,view_config,slack_channel = None):
|
|
15
|
+
"""Send Alert for a veiw"""
|
|
16
|
+
|
|
17
|
+
df = get_view_data(view)
|
|
18
|
+
|
|
19
|
+
if len(df) == 0:
|
|
20
|
+
print(f' The View {view} did not have any alerts today.')
|
|
21
|
+
log_alert_history(
|
|
22
|
+
related_view = view,
|
|
23
|
+
team = view_group,
|
|
24
|
+
was_success=True,
|
|
25
|
+
message_details = {'skipped':'No Results'}
|
|
26
|
+
)
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
if os.environ['DEBUG'] == 'TRUE': slack_channel = 'C0713PW8A68' # Send messeges to testing channel
|
|
30
|
+
message_text = view_config.get('message_text',"@here, you have a new data alert:")
|
|
31
|
+
|
|
32
|
+
## Logic to split off message styles could go here
|
|
33
|
+
match view_config.get('format_template','Default'):
|
|
34
|
+
case 'Default':
|
|
35
|
+
SlackTemplates.template_f1(df,view,view_group,message_text,slack_channel,view_config)
|
|
36
|
+
case 'F1':
|
|
37
|
+
SlackTemplates.template_f1(df,view,view_group,message_text,slack_channel,view_config)
|
|
38
|
+
case 'F2':
|
|
39
|
+
SlackTemplates.template_f2_summary_with_expand(df,view,view_group,message_text,slack_channel,view_config)
|
|
40
|
+
case 'F3':
|
|
41
|
+
SlackTemplates.template_f3_grouped_data(df,view,view_group,message_text,slack_channel,view_config)
|
|
42
|
+
case 'F4':
|
|
43
|
+
SlackTemplates.template_f4_metrics_dashboard(df,view,view_group,message_text,slack_channel,view_config)
|
|
44
|
+
case 'F5':
|
|
45
|
+
SlackTemplates.template_f5(df,view,view_group,message_text,slack_channel,view_config)
|
|
46
|
+
case _:
|
|
47
|
+
template_f1(df,view,view_group,message_text,slack_channel,view_config)
|