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