##// END OF EJS Templates
components: reports componentized
ergo -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,296 +1,296 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # AppEnlight Enterprise Edition, including its added features, Support
19 19 # services, and proprietary license terms, please see
20 20 # https://rhodecode.com/licenses/
21 21
22 22 import logging
23 23 import sqlalchemy as sa
24 24 import urllib.request, urllib.parse, urllib.error
25 25 from datetime import timedelta
26 26 from appenlight.models import Base
27 27 from appenlight.lib.utils.date_utils import convert_date
28 28 from sqlalchemy.dialects.postgresql import JSON
29 29 from ziggurat_foundations.models.base import BaseModel
30 30
31 31 log = logging.getLogger(__name__)
32 32
33 33 #
34 34 channel_rules_m2m_table = sa.Table(
35 35 'channels_actions', Base.metadata,
36 36 sa.Column('channel_pkey', sa.Integer,
37 37 sa.ForeignKey('alert_channels.pkey')),
38 38 sa.Column('action_pkey', sa.Integer,
39 39 sa.ForeignKey('alert_channels_actions.pkey'))
40 40 )
41 41
42 42 DATE_FRMT = '%Y-%m-%dT%H:%M'
43 43
44 44
45 45 class AlertChannel(Base, BaseModel):
46 46 """
47 47 Stores information about possible alerting options
48 48 """
49 49 __tablename__ = 'alert_channels'
50 50 __possible_channel_names__ = ['email']
51 51 __mapper_args__ = {
52 52 'polymorphic_on': 'channel_name',
53 53 'polymorphic_identity': 'integration'
54 54 }
55 55
56 56 owner_id = sa.Column(sa.Unicode(30),
57 57 sa.ForeignKey('users.id', onupdate='CASCADE',
58 58 ondelete='CASCADE'))
59 59 channel_name = sa.Column(sa.Unicode(25), nullable=False)
60 60 channel_value = sa.Column(sa.Unicode(80), nullable=False, default='')
61 61 channel_json_conf = sa.Column(JSON(), nullable=False, default='')
62 62 channel_validated = sa.Column(sa.Boolean, nullable=False,
63 63 default=False)
64 64 send_alerts = sa.Column(sa.Boolean, nullable=False,
65 65 default=True)
66 66 daily_digest = sa.Column(sa.Boolean, nullable=False,
67 67 default=True)
68 68 integration_id = sa.Column(sa.Integer, sa.ForeignKey('integrations.id'),
69 69 nullable=True)
70 70 pkey = sa.Column(sa.Integer(), nullable=False, primary_key=True)
71 71
72 72 channel_actions = sa.orm.relationship('AlertChannelAction',
73 73 cascade="all",
74 74 passive_deletes=True,
75 75 passive_updates=True,
76 76 secondary=channel_rules_m2m_table,
77 77 backref='channels')
78 78
79 79 @property
80 80 def channel_visible_value(self):
81 81 if self.integration:
82 82 return '{}: {}'.format(
83 83 self.channel_name,
84 84 self.integration.resource.resource_name
85 85 )
86 86
87 87 return '{}: {}'.format(
88 88 self.channel_name,
89 89 self.channel_value
90 90 )
91 91
92 92 def get_dict(self, exclude_keys=None, include_keys=None,
93 93 extended_info=True):
94 94 """
95 95 Returns dictionary with required information that will be consumed by
96 96 angular
97 97 """
98 98 instance_dict = super(AlertChannel, self).get_dict(exclude_keys,
99 99 include_keys)
100 100 exclude_keys_list = exclude_keys or []
101 101 include_keys_list = include_keys or []
102 102
103 103 instance_dict['supports_report_alerting'] = True
104 104 instance_dict['channel_visible_value'] = self.channel_visible_value
105 105
106 106 if extended_info:
107 107 instance_dict['actions'] = [
108 108 rule.get_dict(extended_info=True) for
109 109 rule in self.channel_actions]
110 110
111 111 del instance_dict['channel_json_conf']
112 112
113 113 if self.integration:
114 114 instance_dict[
115 115 'supports_report_alerting'] = \
116 116 self.integration.supports_report_alerting
117 117 d = {}
118 118 for k in instance_dict.keys():
119 119 if (k not in exclude_keys_list and
120 120 (k in include_keys_list or not include_keys)):
121 121 d[k] = instance_dict[k]
122 122 return d
123 123
124 124 def __repr__(self):
125 125 return '<AlertChannel: (%s,%s), user:%s>' % (self.channel_name,
126 126 self.channel_value,
127 127 self.user_name,)
128 128
129 129 def send_digest(self, **kwargs):
130 130 """
131 131 This should implement daily top error report notifications
132 132 """
133 133 log.warning('send_digest NOT IMPLEMENTED')
134 134
135 135 def notify_reports(self, **kwargs):
136 136 """
137 137 This should implement notification of reports that occured in 1 min
138 138 interval
139 139 """
140 140 log.warning('notify_reports NOT IMPLEMENTED')
141 141
142 142 def notify_alert(self, **kwargs):
143 143 """
144 144 Notify user of report/uptime/chart threshold events based on events alert
145 145 type
146 146
147 147 Kwargs:
148 148 application: application that the event applies for,
149 149 event: event that is notified,
150 150 user: user that should be notified
151 151 request: request object
152 152
153 153 """
154 154 alert_name = kwargs['event'].unified_alert_name()
155 155 if alert_name in ['slow_report_alert', 'error_report_alert']:
156 156 self.notify_report_alert(**kwargs)
157 157 elif alert_name == 'uptime_alert':
158 158 self.notify_uptime_alert(**kwargs)
159 159 elif alert_name == 'chart_alert':
160 160 self.notify_chart_alert(**kwargs)
161 161
162 162 def notify_chart_alert(self, **kwargs):
163 163 """
164 164 This should implement report open/close alerts notifications
165 165 """
166 166 log.warning('notify_chart_alert NOT IMPLEMENTED')
167 167
168 168 def notify_report_alert(self, **kwargs):
169 169 """
170 170 This should implement report open/close alerts notifications
171 171 """
172 172 log.warning('notify_report_alert NOT IMPLEMENTED')
173 173
174 174 def notify_uptime_alert(self, **kwargs):
175 175 """
176 176 This should implement uptime open/close alerts notifications
177 177 """
178 178 log.warning('notify_uptime_alert NOT IMPLEMENTED')
179 179
180 180 def get_notification_basic_vars(self, kwargs):
181 181 """
182 182 Sets most common variables used later for rendering notifications for
183 183 channel
184 184 """
185 185 if 'event' in kwargs:
186 186 kwargs['since_when'] = kwargs['event'].start_date
187 187
188 188 url_start_date = kwargs.get('since_when') - timedelta(minutes=1)
189 189 url_end_date = kwargs.get('since_when') + timedelta(minutes=4)
190 190 tmpl_vars = {
191 191 "timestamp": kwargs['since_when'],
192 192 "user": kwargs['user'],
193 193 "since_when": kwargs.get('since_when'),
194 194 "url_start_date": url_start_date,
195 195 "url_end_date": url_end_date
196 196 }
197 197 tmpl_vars["resource_name"] = kwargs['resource'].resource_name
198 198 tmpl_vars["resource"] = kwargs['resource']
199 199
200 200 if 'event' in kwargs:
201 201 tmpl_vars['event_values'] = kwargs['event'].values
202 202 tmpl_vars['alert_type'] = kwargs['event'].unified_alert_name()
203 203 tmpl_vars['alert_action'] = kwargs['event'].unified_alert_action()
204 204 return tmpl_vars
205 205
206 206 def report_alert_notification_vars(self, kwargs):
207 207 tmpl_vars = self.get_notification_basic_vars(kwargs)
208 208 reports = kwargs.get('reports', [])
209 209 tmpl_vars["reports"] = reports
210 210 tmpl_vars["confirmed_total"] = len(reports)
211 211
212 212 tmpl_vars["report_type"] = "error reports"
213 tmpl_vars["url_report_type"] = 'report'
213 tmpl_vars["url_report_type"] = 'report/list'
214 214
215 215 alert_type = tmpl_vars.get('alert_type', '')
216 216 if 'slow_report' in alert_type:
217 217 tmpl_vars["report_type"] = "slow reports"
218 218 tmpl_vars["url_report_type"] = 'report/list_slow'
219 219
220 220 app_url = kwargs['request'].registry.settings['_mail_url']
221 221
222 222 destination_url = kwargs['request'].route_url('/',
223 223 _app_url=app_url)
224 224 if alert_type:
225 225 destination_url += 'ui/{}?resource={}&start_date={}&end_date={}'.format(
226 226 tmpl_vars["url_report_type"],
227 227 tmpl_vars['resource'].resource_id,
228 228 tmpl_vars['url_start_date'].strftime(DATE_FRMT),
229 229 tmpl_vars['url_end_date'].strftime(DATE_FRMT)
230 230 )
231 231 else:
232 232 destination_url += 'ui/{}?resource={}'.format(
233 233 tmpl_vars["url_report_type"],
234 234 tmpl_vars['resource'].resource_id
235 235 )
236 236 tmpl_vars["destination_url"] = destination_url
237 237
238 238 return tmpl_vars
239 239
240 240 def uptime_alert_notification_vars(self, kwargs):
241 241 tmpl_vars = self.get_notification_basic_vars(kwargs)
242 242 app_url = kwargs['request'].registry.settings['_mail_url']
243 243 destination_url = kwargs['request'].route_url('/', _app_url=app_url)
244 244 destination_url += 'ui/{}?resource={}'.format(
245 245 'uptime',
246 246 tmpl_vars['resource'].resource_id)
247 247 tmpl_vars['destination_url'] = destination_url
248 248
249 249 reason = ''
250 250 e_values = tmpl_vars.get('event_values')
251 251
252 252 if e_values and e_values.get('response_time') == 0:
253 253 reason += ' Response time was slower than 20 seconds.'
254 254 elif e_values:
255 255 code = e_values.get('status_code')
256 256 reason += ' Response status code: %s.' % code
257 257
258 258 tmpl_vars['reason'] = reason
259 259 return tmpl_vars
260 260
261 261 def chart_alert_notification_vars(self, kwargs):
262 262 tmpl_vars = self.get_notification_basic_vars(kwargs)
263 263 tmpl_vars['chart_name'] = tmpl_vars['event_values']['chart_name']
264 264 tmpl_vars['action_name'] = tmpl_vars['event_values'].get(
265 265 'action_name') or ''
266 266 matched_values = tmpl_vars['event_values']['matched_step_values']
267 267 tmpl_vars['readable_values'] = []
268 268 for key, value in list(matched_values['values'].items()):
269 269 matched_label = matched_values['labels'].get(key)
270 270 if matched_label:
271 271 tmpl_vars['readable_values'].append({
272 272 'label': matched_label['human_label'],
273 273 'value': value
274 274 })
275 275 tmpl_vars['readable_values'] = sorted(tmpl_vars['readable_values'],
276 276 key=lambda x: x['label'])
277 277 start_date = convert_date(tmpl_vars['event_values']['start_interval'])
278 278 end_date = None
279 279 if tmpl_vars['event_values'].get('end_interval'):
280 280 end_date = convert_date(tmpl_vars['event_values']['end_interval'])
281 281
282 282 app_url = kwargs['request'].registry.settings['_mail_url']
283 283 destination_url = kwargs['request'].route_url('/', _app_url=app_url)
284 284 to_encode = {
285 285 'resource': tmpl_vars['event_values']['resource'],
286 286 'start_date': start_date.strftime(DATE_FRMT),
287 287 }
288 288 if end_date:
289 289 to_encode['end_date'] = end_date.strftime(DATE_FRMT)
290 290
291 291 destination_url += 'ui/{}?{}'.format(
292 292 'logs',
293 293 urllib.parse.urlencode(to_encode)
294 294 )
295 295 tmpl_vars['destination_url'] = destination_url
296 296 return tmpl_vars
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from frontend/src/templates/reports/view.html to frontend/src/components/views/report-view/report-view.html
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from frontend/src/controllers/reports/view.js to frontend/src/components/views/report-view/report-view.js
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from frontend/src/templates/reports/list.html to frontend/src/components/views/reports-browser-view/reports-browser-view.html
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from frontend/src/controllers/reports/list.js to frontend/src/components/views/reports-browser-view/reports-browser-view.js
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from frontend/src/templates/reports/list_slow.html to frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.html
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from frontend/src/controllers/reports/list_slow.js to frontend/src/components/views/reports-slow-browser-view/reports-slow-browser-view.js
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now