##// 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 ; This is used to store exception from RhodeCode in shared directory
350 ; This is used to store exception from RhodeCode in shared directory
351 #exception_tracker.store_path =
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 ; File store configuration. This is used to store and serve uploaded files
364 ; File store configuration. This is used to store and serve uploaded files
354 file_store.enabled = true
365 file_store.enabled = true
355
366
@@ -301,6 +301,17 b' labs_settings_active = true'
301 ; This is used to store exception from RhodeCode in shared directory
301 ; This is used to store exception from RhodeCode in shared directory
302 #exception_tracker.store_path =
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 ; File store configuration. This is used to store and serve uploaded files
315 ; File store configuration. This is used to store and serve uploaded files
305 file_store.enabled = true
316 file_store.enabled = true
306
317
@@ -88,6 +88,15 b' Check if we should use full-topic or min'
88 'modified': ['b/modified_file.rst'],
88 'modified': ['b/modified_file.rst'],
89 'removed': ['.idea'],
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 email_kwargs = {
100 email_kwargs = {
92 'test': {},
101 'test': {},
93 'message': {
102 'message': {
@@ -97,6 +106,13 b' Check if we should use full-topic or min'
97 'user': user,
106 'user': user,
98 'date': datetime.datetime.now(),
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 'password_reset': {
116 'password_reset': {
101 'password_reset_url': 'http://example.com/reset-rhodecode-password/token',
117 'password_reset_url': 'http://example.com/reset-rhodecode-password/token',
102
118
@@ -611,6 +611,14 b' def _sanitize_cache_settings(settings):'
611 settings,
611 settings,
612 'exception_tracker.store_path',
612 'exception_tracker.store_path',
613 temp_store, lower=False, default_when_empty=True)
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 # cache_perms
623 # cache_perms
616 _string_setting(
624 _string_setting(
@@ -27,7 +27,6 b' import traceback'
27 import tempfile
27 import tempfile
28 import glob
28 import glob
29
29
30
31 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
32
31
33 # NOTE: Any changes should be synced with exc_tracking at vcsserver.lib.exc_tracking
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 return _exc_store_path
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 Low level function to store exception in the exception tracker
81 Low level function to store exception in the exception tracker
83 """
82 """
83 import rhodecode as app
84
84
85 exc_store_path = get_exc_store()
85 exc_store_path = get_exc_store()
86 exc_data, org_data = exc_serialize(exc_id, exc_traceback, exc_type_name)
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 f.write(exc_data)
92 f.write(exc_data)
93 log.debug('Stored generated exception %s as: %s', exc_id, stored_exc_path)
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 def _prepare_exception(exc_info):
140 def _prepare_exception(exc_info):
97 exc_type, exc_value, exc_traceback = exc_info
141 exc_type, exc_value, exc_traceback = exc_info
@@ -304,6 +304,7 b' class EmailNotificationModel(BaseModel):'
304 TYPE_PASSWORD_RESET = 'password_reset'
304 TYPE_PASSWORD_RESET = 'password_reset'
305 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
305 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
306 TYPE_EMAIL_TEST = 'email_test'
306 TYPE_EMAIL_TEST = 'email_test'
307 TYPE_EMAIL_EXCEPTION = 'exception'
307 TYPE_TEST = 'test'
308 TYPE_TEST = 'test'
308
309
309 email_types = {
310 email_types = {
@@ -311,6 +312,8 b' class EmailNotificationModel(BaseModel):'
311 'rhodecode:templates/email_templates/main.mako',
312 'rhodecode:templates/email_templates/main.mako',
312 TYPE_TEST:
313 TYPE_TEST:
313 'rhodecode:templates/email_templates/test.mako',
314 'rhodecode:templates/email_templates/test.mako',
315 TYPE_EMAIL_EXCEPTION:
316 'rhodecode:templates/email_templates/exception_tracker.mako',
314 TYPE_EMAIL_TEST:
317 TYPE_EMAIL_TEST:
315 'rhodecode:templates/email_templates/email_test.mako',
318 'rhodecode:templates/email_templates/email_test.mako',
316 TYPE_REGISTRATION:
319 TYPE_REGISTRATION:
General Comments 0
You need to be logged in to leave comments. Login now