sentry_top_errors 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 451faf0b74e71cc7d9ab082b35427881ce43d99d1908246fb4d2a111a16fe7bc
4
- data.tar.gz: 9684d29db554a2fbd8a660124d1cef85b2500afc6037d1bc8a4234b46a894831
3
+ metadata.gz: 312ff43ff1b7e67a60e97d53ce62420fdcb1a7e0d661df6fed257ad1f2fddea5
4
+ data.tar.gz: 3b2a17b9ca30d78d2a27f26d9c05802c1af5fe410a92c49eb2a7abb49f40bcbe
5
5
  SHA512:
6
- metadata.gz: b3dc5a3f0d23d95570d8f6627cdbec58da0a4213ca5c14085a775be7ba2c55154e6d1581ebf8dc67fb18df141c07b582051d2ff08e8c2952df4a39751f9078f8
7
- data.tar.gz: 8f9eb1cf3e1170c894ac8360a30cc0a636865bc5627e51e6e97d79ce4f7ef1ec131203a727b623785130ceea36f9a92528cacd992729bb60297f4f5c5236c039
6
+ metadata.gz: 4729a76870723d4941e0687d74a0947c1301fb80449037ed51b89f671f211a209fac35a9893d579471789e0c67d59cfd7f416f662a56e186d2a09a9eb36b9ce7
7
+ data.tar.gz: 81976c7433fe881e4f805366423527a6966bd8b6cdc550250efef0bfc803bc51703fe130bc50ba18bffac05d15e3862eba8acd5af3bad208be4444587593edc6
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  sentry_cache
2
- index.html
2
+ /index.html
3
3
  Gemfile.lock
4
4
  try_sentry_checker.rb
5
+ sentry_top_errors-*.gem
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "sentry_top_errors"
3
- s.version = "0.1.0"
3
+ s.version = "0.1.1"
4
4
  s.summary = "Generate top errors report for sentry"
5
5
  s.description = ""
6
6
  s.author = "Pavel Evstigneev"
@@ -0,0 +1,358 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Sentry Errors</title>
7
+
8
+ <style>
9
+ body {
10
+ background: linear-gradient(0deg, rgba(252,217,182,1) 0%, rgba(160,206,219,1) 100%);
11
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
12
+ font-size: 14px;
13
+ }
14
+
15
+ .page-content {
16
+ height: 100%;
17
+ min-height: 400px;
18
+ width: 92%;
19
+ max-width: 1200px;
20
+ margin: 30px auto;
21
+ background: #fff;
22
+ padding: 25px;
23
+ border-radius: 12px;
24
+ opacity: 0.95;
25
+ }
26
+
27
+ h1 {
28
+ font-size: 1.5em;
29
+ background: #9d4f4f;
30
+ margin: -25px -25px 35px -25px;
31
+ padding: 12px 25px;
32
+ border-radius: 12px 12px 0 0;
33
+ color: white;
34
+ }
35
+
36
+ h1 a {
37
+ color: white;
38
+ text-decoration: none;
39
+ }
40
+
41
+ table.rows-table {
42
+ margin: 20px 0;
43
+ border-spacing: 0px;
44
+ border-collapse: collapse;
45
+ }
46
+
47
+ table.rows-table td {
48
+ vertical-align: top;
49
+ }
50
+
51
+ table.rows-table td a {
52
+ color: #000;
53
+ }
54
+
55
+ table.rows-table td, table.rows-table th {
56
+ padding: 3px 7px;
57
+ border: 1px solid #cfcfcf;
58
+ }
59
+
60
+ tr.is-non-prod-issue, tr.is-non-prod-issue td a {
61
+ color: #36487d;
62
+ background: #f5f5f5;
63
+ }
64
+
65
+ td.issue-count {
66
+ font-weight: bold;
67
+ }
68
+
69
+ td.issue-name {
70
+ /* word-break: break-all; */
71
+ }
72
+
73
+ td.issue-cause {
74
+ word-break: break-all;
75
+ max-width: 240px;
76
+ font-size: 80%;
77
+ }
78
+
79
+ td.project-name {
80
+ word-break: break-all;
81
+ max-width: 260px;
82
+ }
83
+
84
+ .full-width {
85
+ width: 100%;
86
+ max-width: 100%;
87
+ }
88
+ </style>
89
+ </head>
90
+ <body>
91
+ <div class='page-content'>
92
+ <h1>
93
+ <a href=''>Sentry Errors</a>
94
+ </h1>
95
+
96
+ <h2>Repeating Issues</h2>
97
+
98
+ <table class='rows-table full-width' id="issues-table">
99
+ <thead>
100
+ <tr>
101
+ <th>Count</th>
102
+ <th>Project</th>
103
+ <th>Issue</th>
104
+ <th>Cause</th>
105
+ </tr>
106
+ </thead>
107
+ <tbody></tbody>
108
+ </table>
109
+
110
+ <h2>New Issues</h2>
111
+
112
+ <table class='rows-table full-width' id="new-issues-table">
113
+ <thead>
114
+ <tr>
115
+ <th>Count</th>
116
+ <th>Project</th>
117
+ <th>Issue</th>
118
+ <th>Cause</th>
119
+ </tr>
120
+ </thead>
121
+ <tbody></tbody>
122
+ </table>
123
+ </div>
124
+
125
+ <script>
126
+ var ALL_ISSUE_COUNTS = ['ALL_ISSUE_COUNTS_PLACEHOLDER'];
127
+ var NEW_ISSUE_COUNTS = ['NEW_ISSUE_COUNTS_PLACEHOLDER'];
128
+ </script>
129
+ <script>
130
+
131
+ // Some sort of replacement for jquery
132
+ ///
133
+ // Usage:
134
+ // $(selector, paretn) - find an element
135
+ // $$(selector, paretn) - find elements, return as array
136
+ // $.element(html, {class: '', appendTo: '', html: '', text: '', hide: '', classes: ['']}) - create element
137
+ // $.ajax({url: '', method: 'GET', data: '', contentType: '', accepts: '', headers: '', before: fn, process: fn, uploadProgress: fn, complete: fn, error: fn, })
138
+ // $.ready - $(document).ready
139
+ // $.matches - polifill
140
+ // $.closest - same as jquery
141
+
142
+ var $ = function (selector, element) {
143
+ if (selector[0] == '<') {
144
+ return $.element(selector, element);
145
+ }
146
+ return (element || document).querySelector(selector);
147
+ };
148
+
149
+ var $$ = function (selector, element) {
150
+ return Array.from((element || document).querySelectorAll(selector));
151
+ };
152
+
153
+ $.element = function (html, attributes) {
154
+ if (!attributes) attributes = {};
155
+ var element;
156
+
157
+ if (html[0] == '<') {
158
+ var div = document.createElement('div');
159
+ div.innerHTML = html;
160
+ element = div.childNodes[0];
161
+ } else {
162
+ var element = document.createElement(html);
163
+ }
164
+
165
+ Object.keys(attributes).forEach(function (key) {
166
+ var value = attributes[key];
167
+
168
+ if (key == 'class') {
169
+ element.className = value;
170
+ } else if (key == 'classes') {
171
+ value.forEach(function (className) {
172
+ el.classList.add(className);
173
+ });
174
+ } else if (key == 'appendTo') {
175
+ value.appendChild(element);
176
+ } else if (key == 'html') {
177
+ element.innerHTML = value;
178
+ } else if (key == 'text') {
179
+ element.innerText = value;
180
+ } else if (key == 'hide') {
181
+ element.style.display = 'none';
182
+ } else {
183
+ element.setAttribute(key, value);
184
+ }
185
+ });
186
+
187
+ return element;
188
+ };
189
+
190
+ $.ajax = function (options) {
191
+ var request = new XMLHttpRequest();
192
+
193
+ if (options.query) {
194
+ var query = Object.keys(options.query).map(function (k) {
195
+ return encodeURIComponent(k) + '=' + encodeURIComponent(options.query[k]);
196
+ }).join('&');
197
+ options.url += (options.url.includes("?") ? "&" : "?") + query;
198
+ }
199
+
200
+ request.open(options.method || 'GET', options.url);
201
+
202
+ options.before && options.before(request);
203
+
204
+ if (options.contentType == 'json') {
205
+ request.setRequestHeader("Content-type", "application/json");
206
+ } else if (options.contentType) {
207
+ request.setRequestHeader("Content-type", options.contentType);
208
+ } else if (options.data && !(options.data instanceof FormData)) {
209
+ request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
210
+ }
211
+
212
+ request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
213
+ if (options.accepts) {
214
+ request.setRequestHeader('Accept', '*/*;q=0.5, ' + options.accepts);
215
+ }
216
+
217
+ if (options.headers) {
218
+ Object.keys(options.headers).forEach(function (key) {
219
+ request.setRequestHeader(key, options.headers[key]);
220
+ });
221
+ }
222
+
223
+ if (options.process) {
224
+ request.addEventListener("progress", function (event) {
225
+ options.process(request, event);
226
+ });
227
+ }
228
+ if (options.uploadProgress) {
229
+ request.upload.addEventListener("progress", function (event) {
230
+ options.uploadProgress(request, event);
231
+ });
232
+ }
233
+
234
+ request.addEventListener("load", function (event) {
235
+ //console.log('Request Status', request.status, request, event);
236
+ try {
237
+ var data;
238
+ var contentType = request.getResponseHeader('Content-type') || "";
239
+ if (contentType == "application/json" || contentType.match(/^application\/json/)) {
240
+ try {
241
+ data = JSON.parse(request.responseText);
242
+ request.responseJSON = data;
243
+ } catch (e) {
244
+ console.error(e);
245
+ }
246
+ }
247
+ if (request.status < 400) {
248
+ options.success && options.success(request, data, event);
249
+ } else {
250
+ options.error && options.error(request, event);
251
+ }
252
+ } catch (e) {
253
+ console.error(e);
254
+ }
255
+ options.complete && options.complete(request, event);
256
+ });
257
+
258
+ ['error', 'abort'].map(function (event) {
259
+ request.addEventListener(event, function (event) {
260
+ try {
261
+ options.error && options.error(request, event);
262
+ } catch (e) {
263
+ console.error(e);
264
+ }
265
+ options.complete && options.complete(request, event);
266
+ });
267
+ });
268
+
269
+ request.send(options.data);
270
+ };
271
+
272
+ $.ready = function (fn) {
273
+ if (document.readyState != 'loading') {
274
+ fn();
275
+ } else {
276
+ document.addEventListener('DOMContentLoaded', fn);
277
+ }
278
+ };
279
+
280
+ $.matches = function (el, selector) {
281
+ var p = Element.prototype;
282
+ var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
283
+ return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
284
+ };
285
+ return f.call(el, selector);
286
+ };
287
+
288
+ $.closest = function (element, selector) {
289
+ var parent = element;
290
+ while (parent && !$.matches(parent, selector)) {
291
+ parent = parent.parentNode;
292
+ if (parent instanceof HTMLDocument) {
293
+ return null;
294
+ }
295
+ }
296
+
297
+ return parent;
298
+ };
299
+
300
+ $.onClickOutside = function (element, optoins, callback) {
301
+ if (!optoins) optoins = {};
302
+
303
+ document.addEventListener('click', function cb(event) {
304
+ var parent = event.target;
305
+ while (!(parent instanceof HTMLDocument)) {
306
+ if (parent == element) {
307
+ //console.log('click inside');
308
+ return;
309
+ }
310
+ parent = parent.parentNode;
311
+ }
312
+
313
+ //console.log('click outside');
314
+ callback(event);
315
+
316
+ if (optoins.once) {
317
+ // for browsers that don't support "once: true"
318
+ event.currentTarget.removeEventListener(event.type, cb);
319
+ }
320
+ }, {once: optoins.once});
321
+ };
322
+ </script>
323
+
324
+ <script>
325
+ var issuesTable = $('#issues-table tbody');
326
+
327
+ ALL_ISSUE_COUNTS.forEach(issue => {
328
+ var tr = $.element('tr', {
329
+ appendTo: issuesTable,
330
+ class: issue.is_production ? 'is-prod-issue' : 'is-non-prod-issue',
331
+ });
332
+
333
+ $.element('td', {text: issue.issue_count, appendTo: tr, class: 'issue-count'});
334
+ var projectCell = $.element('td', {appendTo: tr, class: 'project-name'});
335
+ $.element('a', {href: issue.project_url, text: issue.project_name, target: '_blank', appendTo: projectCell})
336
+ var issueCell = $.element('td', {appendTo: tr, class: 'issue-name'});
337
+ $.element('a', {href: issue.issue_link, text: issue.issue, target: '_blank', appendTo: issueCell})
338
+ $.element('td', {text: issue.culprit, appendTo: tr, class: 'issue-cause'});
339
+ });
340
+
341
+ var issuesTable = $('#new-issues-table tbody');
342
+
343
+ NEW_ISSUE_COUNTS.forEach(issue => {
344
+ var tr = $.element('tr', {
345
+ appendTo: issuesTable,
346
+ class: issue.is_production ? 'is-prod-issue' : 'is-non-prod-issue',
347
+ });
348
+
349
+ $.element('td', {text: issue.issue_count, appendTo: tr, class: 'issue-count'});
350
+ var projectCell = $.element('td', {appendTo: tr, class: 'project-name'});
351
+ $.element('a', {href: issue.project_url, text: issue.project_name, target: '_blank', appendTo: projectCell})
352
+ var issueCell = $.element('td', {appendTo: tr, class: 'issue-name'});
353
+ $.element('a', {href: issue.issue_link, text: issue.issue, target: '_blank', appendTo: issueCell})
354
+ $.element('td', {text: issue.culprit, appendTo: tr, class: 'issue-cause'});
355
+ });
356
+ </script>
357
+ </body>
358
+ </html>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry_top_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Evstigneev
@@ -60,6 +60,7 @@ files:
60
60
  - lib/sentry_top_errors/reporter.rb
61
61
  - lib/sentry_top_errors/sentry_client.rb
62
62
  - senrty_top_errors.gemspec
63
+ - templates/index.html
63
64
  homepage: http://github.com/Paxa/sentry_top_errors
64
65
  licenses:
65
66
  - MIT