##// END OF EJS Templates
exc_store: add filter for display and deletion.
marcink -
r3669:d393e493 default
parent child Browse files
Show More
@@ -1,160 +1,174 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2018-2019 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 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20 import os
21 21 import logging
22 22
23 23 from pyramid.httpexceptions import HTTPFound
24 24 from pyramid.view import view_config
25 25
26 26 from rhodecode.apps._base import BaseAppView
27 27 from rhodecode.apps._base.navigation import navigation_list
28 28 from rhodecode.lib import helpers as h
29 29 from rhodecode.lib.auth import (
30 30 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
31 31 from rhodecode.lib.utils2 import time_to_utcdatetime, safe_int
32 32 from rhodecode.lib import exc_tracking
33 33
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 37 class ExceptionsTrackerView(BaseAppView):
38 38 def load_default_context(self):
39 39 c = self._get_local_tmpl_context()
40 40 c.navlist = navigation_list(self.request)
41 41 return c
42 42
43 43 def count_all_exceptions(self):
44 44 exc_store_path = exc_tracking.get_exc_store()
45 45 count = 0
46 46 for fname in os.listdir(exc_store_path):
47 47 parts = fname.split('_', 2)
48 48 if not len(parts) == 3:
49 49 continue
50 50 count +=1
51 51 return count
52 52
53 def get_all_exceptions(self, read_metadata=False, limit=None):
53 def get_all_exceptions(self, read_metadata=False, limit=None, type_filter=None):
54 54 exc_store_path = exc_tracking.get_exc_store()
55 55 exception_list = []
56 56
57 57 def key_sorter(val):
58 58 try:
59 59 return val.split('_')[-1]
60 60 except Exception:
61 61 return 0
62 count = 0
62
63 63 for fname in reversed(sorted(os.listdir(exc_store_path), key=key_sorter)):
64 64
65 65 parts = fname.split('_', 2)
66 66 if not len(parts) == 3:
67 67 continue
68 68
69 69 exc_id, app_type, exc_timestamp = parts
70 70
71 71 exc = {'exc_id': exc_id, 'app_type': app_type, 'exc_type': 'unknown',
72 72 'exc_utc_date': '', 'exc_timestamp': exc_timestamp}
73 73
74 74 if read_metadata:
75 75 full_path = os.path.join(exc_store_path, fname)
76 76 if not os.path.isfile(full_path):
77 77 continue
78 78 try:
79 79 # we can read our metadata
80 80 with open(full_path, 'rb') as f:
81 81 exc_metadata = exc_tracking.exc_unserialize(f.read())
82 82 exc.update(exc_metadata)
83 83 except Exception:
84 84 log.exception('Failed to read exc data from:{}'.format(full_path))
85 85 pass
86
87 86 # convert our timestamp to a date obj, for nicer representation
88 87 exc['exc_utc_date'] = time_to_utcdatetime(exc['exc_timestamp'])
89 exception_list.append(exc)
90 88
91 count += 1
92 if limit and count >= limit:
89 type_present = exc.get('exc_type')
90 if type_filter:
91 if type_present and type_present == type_filter:
92 exception_list.append(exc)
93 else:
94 exception_list.append(exc)
95
96 if limit and len(exception_list) >= limit:
93 97 break
94 98 return exception_list
95 99
96 100 @LoginRequired()
97 101 @HasPermissionAllDecorator('hg.admin')
98 102 @view_config(
99 103 route_name='admin_settings_exception_tracker', request_method='GET',
100 104 renderer='rhodecode:templates/admin/settings/settings.mako')
101 105 def browse_exceptions(self):
102 106 _ = self.request.translate
103 107 c = self.load_default_context()
104 108 c.active = 'exceptions_browse'
105 109 c.limit = safe_int(self.request.GET.get('limit')) or 50
110 c.type_filter = self.request.GET.get('type_filter')
106 111 c.next_limit = c.limit + 50
107 c.exception_list = self.get_all_exceptions(read_metadata=True, limit=c.limit)
112 c.exception_list = self.get_all_exceptions(
113 read_metadata=True, limit=c.limit, type_filter=c.type_filter)
108 114 c.exception_list_count = self.count_all_exceptions()
109 115 c.exception_store_dir = exc_tracking.get_exc_store()
110 116 return self._get_template_context(c)
111 117
112 118 @LoginRequired()
113 119 @HasPermissionAllDecorator('hg.admin')
114 120 @view_config(
115 121 route_name='admin_settings_exception_tracker_show', request_method='GET',
116 122 renderer='rhodecode:templates/admin/settings/settings.mako')
117 123 def exception_show(self):
118 124 _ = self.request.translate
119 125 c = self.load_default_context()
120 126
121 127 c.active = 'exceptions'
122 128 c.exception_id = self.request.matchdict['exception_id']
123 129 c.traceback = exc_tracking.read_exception(c.exception_id, prefix=None)
124 130 return self._get_template_context(c)
125 131
126 132 @LoginRequired()
127 133 @HasPermissionAllDecorator('hg.admin')
128 134 @CSRFRequired()
129 135 @view_config(
130 136 route_name='admin_settings_exception_tracker_delete_all', request_method='POST',
131 137 renderer='rhodecode:templates/admin/settings/settings.mako')
132 138 def exception_delete_all(self):
133 139 _ = self.request.translate
134 140 c = self.load_default_context()
141 type_filter = self.request.POST.get('type_filter')
135 142
136 143 c.active = 'exceptions'
137 all_exc = self.get_all_exceptions()
138 exc_count = len(all_exc)
144 all_exc = self.get_all_exceptions(read_metadata=bool(type_filter), type_filter=type_filter)
145 exc_count = 0
146
139 147 for exc in all_exc:
140 exc_tracking.delete_exception(exc['exc_id'], prefix=None)
148 if type_filter:
149 if exc.get('exc_type') == type_filter:
150 exc_tracking.delete_exception(exc['exc_id'], prefix=None)
151 exc_count += 1
152 else:
153 exc_tracking.delete_exception(exc['exc_id'], prefix=None)
154 exc_count += 1
141 155
142 156 h.flash(_('Removed {} Exceptions').format(exc_count), category='success')
143 157 raise HTTPFound(h.route_path('admin_settings_exception_tracker'))
144 158
145 159 @LoginRequired()
146 160 @HasPermissionAllDecorator('hg.admin')
147 161 @CSRFRequired()
148 162 @view_config(
149 163 route_name='admin_settings_exception_tracker_delete', request_method='POST',
150 164 renderer='rhodecode:templates/admin/settings/settings.mako')
151 165 def exception_delete(self):
152 166 _ = self.request.translate
153 167 c = self.load_default_context()
154 168
155 169 c.active = 'exceptions'
156 170 c.exception_id = self.request.matchdict['exception_id']
157 171 exc_tracking.delete_exception(c.exception_id, prefix=None)
158 172
159 173 h.flash(_('Removed Exception {}').format(c.exception_id), category='success')
160 174 raise HTTPFound(h.route_path('admin_settings_exception_tracker'))
@@ -1,57 +1,65 b''
1 1 <div class="panel panel-default">
2 2 <div class="panel-heading">
3 3 <h3 class="panel-title">${_('Exceptions Tracker ')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 6 % if c.exception_list_count == 1:
7 7 ${_('There is {} stored exception.').format(c.exception_list_count)}
8 8 % else:
9 ${_('There are {} stored exceptions.').format(c.exception_list_count)}
9 ${_('There are total {} stored exceptions.').format(c.exception_list_count)}
10 10 % endif
11 <br/>
11 12 ${_('Store directory')}: ${c.exception_store_dir}
12 13
13 14 ${h.secure_form(h.route_path('admin_settings_exception_tracker_delete_all'), request=request)}
14 15 <div style="margin: 0 0 20px 0" class="fake-space"></div>
15
16 <input type="hidden" name="type_filter", value="${c.type_filter}">
16 17 <div class="field">
17 18 <button class="btn btn-small btn-danger" type="submit"
18 19 onclick="return confirm('${_('Confirm to delete all exceptions')}');">
19 20 <i class="icon-remove-sign"></i>
20 ${_('Delete All')}
21 % if c.type_filter:
22 ${_('Delete All `{}`').format(c.type_filter)}
23 % else:
24 ${_('Delete All')}
25 % endif
26
21 27 </button>
22 28 </div>
23 29
24 30 ${h.end_form()}
25 31
26 32 </div>
27 33 </div>
28 34
29 35
30 36 <div class="panel panel-default">
31 37 <div class="panel-heading">
32 38 <h3 class="panel-title">${_('Exceptions Tracker - Showing the last {} Exceptions').format(c.limit)}.</h3>
33 39 <a class="panel-edit" href="${h.current_route_path(request, limit=c.next_limit)}">${_('Show more')}</a>
34 40 </div>
35 41 <div class="panel-body">
36 42 <table class="rctable">
37 43 <tr>
38 44 <th>#</th>
39 45 <th>Exception ID</th>
40 46 <th>Date</th>
41 47 <th>App Type</th>
42 48 <th>Exc Type</th>
43 49 </tr>
44 50 <% cnt = len(c.exception_list)%>
45 51 % for tb in c.exception_list:
46 52 <tr>
47 53 <td>${cnt}</td>
48 54 <td><a href="${h.route_path('admin_settings_exception_tracker_show', exception_id=tb['exc_id'])}"><code>${tb['exc_id']}</code></a></td>
49 55 <td>${h.format_date(tb['exc_utc_date'])}</td>
50 56 <td>${tb['app_type']}</td>
51 <td>${tb['exc_type']}</td>
57 <td>
58 <a href="${h.current_route_path(request, type_filter=tb['exc_type'])}">${tb['exc_type']}</a>
59 </td>
52 60 </tr>
53 61 <% cnt -=1 %>
54 62 % endfor
55 63 </table>
56 64 </div>
57 65 </div>
General Comments 0
You need to be logged in to leave comments. Login now