sentry_top_errors 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/senrty_top_errors.gemspec +1 -1
- data/templates/index.html +358 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 312ff43ff1b7e67a60e97d53ce62420fdcb1a7e0d661df6fed257ad1f2fddea5
|
4
|
+
data.tar.gz: 3b2a17b9ca30d78d2a27f26d9c05802c1af5fe410a92c49eb2a7abb49f40bcbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4729a76870723d4941e0687d74a0947c1301fb80449037ed51b89f671f211a209fac35a9893d579471789e0c67d59cfd7f416f662a56e186d2a09a9eb36b9ce7
|
7
|
+
data.tar.gz: 81976c7433fe881e4f805366423527a6966bd8b6cdc550250efef0bfc803bc51703fe130bc50ba18bffac05d15e3862eba8acd5af3bad208be4444587593edc6
|
data/.gitignore
CHANGED
data/senrty_top_errors.gemspec
CHANGED
@@ -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.
|
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
|