##// END OF EJS Templates
exception-tracker: enable send email on exception
marcink -
r4276:cf661342 default
parent child Browse files
Show More
@@ -0,0 +1,18 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base.mako"/>
3 <%namespace name="base" file="base.mako"/>
4
5 <%def name="subject()" filter="n,trim,whitespace_filter">
6 ${email_prefix} ${exc_type_name} (${exc_id})
7 </%def>
8
9 ## plain text version of the email. Empty by default
10 <%def name="body_plaintext()" filter="n,trim">
11 NO PLAINTEXT VERSION
12 </%def>
13
14 <h4>${_('Exception `{}` generated on UTC date: {}').format(exc_traceback.get('exc_type', 'NO_TYPE'), exc_traceback.get('exc_utc_date', 'NO_DATE'))}</h4>
15 <p>
16 View exception <a href="${exc_url}">${exc_id}</a>
17 </p>
18 <pre>${exc_traceback.get('exc_message', 'NO_MESSAGE')}</pre>
@@ -350,6 +350,17 b' labs_settings_active = true'
350 350 ; This is used to store exception from RhodeCode in shared directory
351 351 #exception_tracker.store_path =
352 352
353 ; Send email with exception details when it happens
354 #exception_tracker.send_email = false
355
356 ; Comma separated list of recipients for exception emails,
357 ; e.g admin@rhodecode.com,devops@rhodecode.com
358 ; Can be left empty, then emails will be sent to ALL super-admins
359 #exception_tracker.send_email_recipients =
360
361 ; optional prefix to Add to email Subject
362 #exception_tracker.email_prefix = [RHODECODE ERROR]
363
353 364 ; File store configuration. This is used to store and serve uploaded files
354 365 file_store.enabled = true
355 366
@@ -301,6 +301,17 b' labs_settings_active = true'
301 301 ; This is used to store exception from RhodeCode in shared directory
302 302 #exception_tracker.store_path =
303 303
304 ; Send email with exception details when it happens
305 #exception_tracker.send_email = false
306
307 ; Comma separated list of recipients for exception emails,
308 ; e.g admin@rhodecode.com,devops@rhodecode.com
309 ; Can be left empty, then emails will be sent to ALL super-admins
310 #exception_tracker.send_email_recipients =
311
312 ; optional prefix to Add to email Subject
313 #exception_tracker.email_prefix = [RHODECODE ERROR]
314
304 315 ; File store configuration. This is used to store and serve uploaded files
305 316 file_store.enabled = true
306 317
@@ -88,6 +88,15 b' Check if we should use full-topic or min'
88 88 'modified': ['b/modified_file.rst'],
89 89 'removed': ['.idea'],
90 90 })
91
92 exc_traceback = {
93 'exc_utc_date': '2020-03-26T12:54:50.683281',
94 'exc_id': 139638856342656,
95 'exc_timestamp': '1585227290.683288',
96 'version': 'v1',
97 'exc_message': 'Traceback (most recent call last):\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/tweens.py", line 41, in excview_tween\n response = handler(request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/router.py", line 148, in handle_request\n registry, request, context, context_iface, view_name\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/view.py", line 667, in _call_view\n response = view_callable(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 188, in attr_view\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 214, in predicate_wrapper\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 401, in viewresult_to_response\n result = view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 132, in _class_view\n response = getattr(inst, attr)()\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/apps/debug_style/views.py", line 355, in render_email\n template_type, **email_kwargs.get(email_id, {}))\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/model/notification.py", line 402, in render_email\n body = email_template.render(None, **_kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 95, in render\n return self._render_with_exc(tmpl, args, kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 79, in _render_with_exc\n return render_func.render(*args, **kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/template.py", line 476, in render\n return runtime._render(self, self.callable_, args, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 883, in _render\n **_kwargs_for_callable(callable_, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 920, in _render_context\n _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 947, in _exec_template\n callable_(context, *args, **kwargs)\n File "rhodecode_templates_email_templates_base_mako", line 63, in render_body\n File "rhodecode_templates_email_templates_exception_tracker_mako", line 43, in render_body\nAttributeError: \'str\' object has no attribute \'get\'\n',
98 'exc_type': 'AttributeError'
99 }
91 100 email_kwargs = {
92 101 'test': {},
93 102 'message': {
@@ -97,6 +106,13 b' Check if we should use full-topic or min'
97 106 'user': user,
98 107 'date': datetime.datetime.now(),
99 108 },
109 'exception': {
110 'email_prefix': '[RHODECODE ERROR]',
111 'exc_id': exc_traceback['exc_id'],
112 'exc_url': 'http://server-url/{}'.format(exc_traceback['exc_id']),
113 'exc_type_name': 'NameError',
114 'exc_traceback': exc_traceback,
115 },
100 116 'password_reset': {
101 117 'password_reset_url': 'http://example.com/reset-rhodecode-password/token',
102 118
@@ -611,6 +611,14 b' def _sanitize_cache_settings(settings):'
611 611 settings,
612 612 'exception_tracker.store_path',
613 613 temp_store, lower=False, default_when_empty=True)
614 _bool_setting(
615 settings,
616 'exception_tracker.send_email',
617 'false')
618 _string_setting(
619 settings,
620 'exception_tracker.email_prefix',
621 '[RHODECODE ERROR]', lower=False, default_when_empty=True)
614 622
615 623 # cache_perms
616 624 _string_setting(
@@ -27,7 +27,6 b' import traceback'
27 27 import tempfile
28 28 import glob
29 29
30
31 30 log = logging.getLogger(__name__)
32 31
33 32 # NOTE: Any changes should be synced with exc_tracking at vcsserver.lib.exc_tracking
@@ -77,10 +76,11 b' def get_exc_store():'
77 76 return _exc_store_path
78 77
79 78
80 def _store_exception(exc_id, exc_type_name, exc_traceback, prefix):
79 def _store_exception(exc_id, exc_type_name, exc_traceback, prefix, send_email=None):
81 80 """
82 81 Low level function to store exception in the exception tracker
83 82 """
83 import rhodecode as app
84 84
85 85 exc_store_path = get_exc_store()
86 86 exc_data, org_data = exc_serialize(exc_id, exc_traceback, exc_type_name)
@@ -92,6 +92,50 b' def _store_exception(exc_id, exc_type_na'
92 92 f.write(exc_data)
93 93 log.debug('Stored generated exception %s as: %s', exc_id, stored_exc_path)
94 94
95 if send_email is None:
96 # NOTE(marcink): read app config unless we specify explicitly
97 send_email = app.CONFIG.get('exception_tracker.send_email', False)
98
99 if send_email:
100 try:
101 send_exc_email(exc_id, exc_type_name)
102 except Exception:
103 log.exception('Failed to send exception email')
104 pass
105
106
107 def send_exc_email(exc_id, exc_type_name):
108 import rhodecode as app
109 from pyramid.threadlocal import get_current_request
110 from rhodecode.apps._base import TemplateArgs
111 from rhodecode.lib.utils2 import aslist
112 from rhodecode.lib.celerylib import run_task, tasks
113 from rhodecode.lib.base import attach_context_attributes
114 from rhodecode.model.notification import EmailNotificationModel
115
116 request = get_current_request()
117
118 recipients = aslist(app.CONFIG.get('exception_tracker.send_email_recipients', ''))
119 log.debug('Sending Email exception to: `%s`', recipients or 'all super admins')
120
121 # NOTE(marcink): needed for email template rendering
122 attach_context_attributes(TemplateArgs(), request, request.user.user_id)
123
124 email_kwargs = {
125 'email_prefix': app.CONFIG.get('exception_tracker.email_prefix', '') or '[RHODECODE ERROR]',
126 'exc_url': request.route_url('admin_settings_exception_tracker_show', exception_id=exc_id),
127 'exc_id': exc_id,
128 'exc_type_name': exc_type_name,
129 'exc_traceback': read_exception(exc_id, prefix=None),
130 }
131
132 (subject, headers, email_body,
133 email_body_plaintext) = EmailNotificationModel().render_email(
134 EmailNotificationModel.TYPE_EMAIL_EXCEPTION, **email_kwargs)
135
136 run_task(tasks.send_email, recipients, subject,
137 email_body_plaintext, email_body)
138
95 139
96 140 def _prepare_exception(exc_info):
97 141 exc_type, exc_value, exc_traceback = exc_info
@@ -304,6 +304,7 b' class EmailNotificationModel(BaseModel):'
304 304 TYPE_PASSWORD_RESET = 'password_reset'
305 305 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
306 306 TYPE_EMAIL_TEST = 'email_test'
307 TYPE_EMAIL_EXCEPTION = 'exception'
307 308 TYPE_TEST = 'test'
308 309
309 310 email_types = {
@@ -311,6 +312,8 b' class EmailNotificationModel(BaseModel):'
311 312 'rhodecode:templates/email_templates/main.mako',
312 313 TYPE_TEST:
313 314 'rhodecode:templates/email_templates/test.mako',
315 TYPE_EMAIL_EXCEPTION:
316 'rhodecode:templates/email_templates/exception_tracker.mako',
314 317 TYPE_EMAIL_TEST:
315 318 'rhodecode:templates/email_templates/email_test.mako',
316 319 TYPE_REGISTRATION:
General Comments 0
You need to be logged in to leave comments. Login now