logster 2.21.0 → 3.0.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/CHANGELOG.md +24 -0
- data/README.md +29 -14
- data/assets/javascript/main-C9t0S9He.js +1 -0
- data/assets/javascript/modules-4-12-BnbZfQQN.js +1 -0
- data/assets/javascript/vendor.js +11 -5260
- data/assets/logster-config.json +18 -0
- data/assets/manifest.json +23 -0
- data/assets/stylesheets/main-et5OPj6E.css +1 -0
- data/lib/logster/configuration.rb +1 -0
- data/lib/logster/middleware/reporter.rb +34 -3
- data/lib/logster/middleware/viewer.rb +204 -32
- data/lib/logster/rails/railtie.rb +4 -20
- data/lib/logster/redis_store.rb +0 -2
- data/lib/logster/version.rb +1 -1
- data/lib/logster.rb +1 -1
- metadata +17 -186
- data/.github/workflows/ci.yml +0 -140
- data/.gitignore +0 -3
- data/.rubocop.yml +0 -12
- data/.streerc +0 -2
- data/Gemfile +0 -10
- data/Guardfile +0 -10
- data/Rakefile +0 -24
- data/assets/javascript/.gitkeep +0 -0
- data/assets/javascript/chunk.524.b7d0b89d25457a72409c.js +0 -22
- data/assets/javascript/chunk.582.5a04ae4713e692cd335a.js +0 -22
- data/assets/javascript/chunk.747.a730c497582bb6742a6e.js +0 -579
- data/assets/javascript/chunk.761.64949d89942c829e5c1b.js +0 -1213
- data/assets/javascript/client-app.js +0 -1389
- data/assets/stylesheets/.gitkeep +0 -0
- data/assets/stylesheets/client-app.css +0 -1
- data/assets/stylesheets/vendor.css +0 -1
- data/build_client_app.sh +0 -10
- data/client-app/.editorconfig +0 -19
- data/client-app/.ember-cli +0 -9
- data/client-app/.eslintignore +0 -20
- data/client-app/.eslintrc +0 -10
- data/client-app/.gitignore +0 -23
- data/client-app/.prettierignore +0 -21
- data/client-app/.prettierrc +0 -1
- data/client-app/.template-lintrc.js +0 -10
- data/client-app/.watchmanconfig +0 -3
- data/client-app/README.md +0 -56
- data/client-app/app/app.js +0 -12
- data/client-app/app/components/actions-menu.js +0 -50
- data/client-app/app/components/back-to-site-link.js +0 -9
- data/client-app/app/components/back-trace.js +0 -153
- data/client-app/app/components/env-tab.js +0 -68
- data/client-app/app/components/message-info.js +0 -151
- data/client-app/app/components/message-row.js +0 -46
- data/client-app/app/components/page-nav.js +0 -42
- data/client-app/app/components/panel-resizer.js +0 -108
- data/client-app/app/components/patterns-list.js +0 -142
- data/client-app/app/components/tab-contents.js +0 -23
- data/client-app/app/components/tabbed-section.js +0 -45
- data/client-app/app/components/time-formatter.js +0 -36
- data/client-app/app/controllers/index.js +0 -288
- data/client-app/app/controllers/show.js +0 -39
- data/client-app/app/helpers/logster-url.js +0 -12
- data/client-app/app/helpers/or.js +0 -7
- data/client-app/app/index.html +0 -31
- data/client-app/app/initializers/app-init.js +0 -71
- data/client-app/app/lib/decorators.js +0 -13
- data/client-app/app/lib/preload.js +0 -43
- data/client-app/app/lib/utilities.js +0 -230
- data/client-app/app/models/group.js +0 -34
- data/client-app/app/models/message-collection.js +0 -303
- data/client-app/app/models/message.js +0 -128
- data/client-app/app/models/pattern-item.js +0 -32
- data/client-app/app/resolver.js +0 -3
- data/client-app/app/router.js +0 -13
- data/client-app/app/routes/index.js +0 -64
- data/client-app/app/routes/settings.js +0 -32
- data/client-app/app/routes/show.js +0 -16
- data/client-app/app/services/events.js +0 -4
- data/client-app/app/styles/app.css +0 -898
- data/client-app/app/templates/application.hbs +0 -1
- data/client-app/app/templates/components/actions-menu.hbs +0 -31
- data/client-app/app/templates/components/back-to-site-link.hbs +0 -8
- data/client-app/app/templates/components/back-trace.hbs +0 -15
- data/client-app/app/templates/components/env-tab.hbs +0 -10
- data/client-app/app/templates/components/message-info.hbs +0 -86
- data/client-app/app/templates/components/message-row.hbs +0 -32
- data/client-app/app/templates/components/page-nav.hbs +0 -37
- data/client-app/app/templates/components/panel-resizer.hbs +0 -3
- data/client-app/app/templates/components/patterns-list.hbs +0 -78
- data/client-app/app/templates/components/tabbed-section.hbs +0 -18
- data/client-app/app/templates/components/time-formatter.hbs +0 -1
- data/client-app/app/templates/index.hbs +0 -192
- data/client-app/app/templates/settings.hbs +0 -47
- data/client-app/app/templates/show.hbs +0 -13
- data/client-app/config/ember-cli-update.json +0 -18
- data/client-app/config/environment.js +0 -51
- data/client-app/config/icons.js +0 -28
- data/client-app/config/optional-features.json +0 -6
- data/client-app/config/targets.js +0 -26
- data/client-app/ember-cli-build.js +0 -34
- data/client-app/package.json +0 -76
- data/client-app/preload-json-manager.rb +0 -35
- data/client-app/public/assets/images/icon_144x144.png +0 -0
- data/client-app/public/assets/images/icon_64x64.png +0 -0
- data/client-app/testem.js +0 -23
- data/client-app/tests/index.html +0 -41
- data/client-app/tests/integration/components/back-to-site-link-test.js +0 -20
- data/client-app/tests/integration/components/back-trace-test.js +0 -138
- data/client-app/tests/integration/components/env-tab-test.js +0 -220
- data/client-app/tests/integration/components/message-info-test.js +0 -122
- data/client-app/tests/integration/components/patterns-list-test.js +0 -76
- data/client-app/tests/test-helper.js +0 -12
- data/client-app/tests/unit/controllers/index-test.js +0 -77
- data/client-app/tests/unit/controllers/show-test.js +0 -12
- data/client-app/tests/unit/routes/index-test.js +0 -11
- data/client-app/tests/unit/routes/show-test.js +0 -11
- data/client-app/yarn.lock +0 -9905
- data/gemfiles/rails_6.1.gemfile +0 -12
- data/gemfiles/rails_7.0.gemfile +0 -12
- data/gemfiles/rails_7.1.gemfile +0 -9
- data/gemfiles/rails_7.2.gemfile +0 -9
- data/logster.gemspec +0 -43
- data/test/dummy/config/application.rb +0 -31
- data/test/dummy/config/boot.rb +0 -6
- data/test/dummy/config/environment.rb +0 -6
- data/test/examples/test_sidekiq_reporter_example.rb +0 -47
- data/test/fake_data/Gemfile +0 -6
- data/test/fake_data/generate.rb +0 -23
- data/test/logster/middleware/test_reporter.rb +0 -84
- data/test/logster/middleware/test_viewer.rb +0 -495
- data/test/logster/test_base_store.rb +0 -224
- data/test/logster/test_cache.rb +0 -39
- data/test/logster/test_defer_logger.rb +0 -36
- data/test/logster/test_group.rb +0 -92
- data/test/logster/test_ignore_pattern.rb +0 -42
- data/test/logster/test_logger.rb +0 -177
- data/test/logster/test_message.rb +0 -269
- data/test/logster/test_pattern.rb +0 -144
- data/test/logster/test_railtie.rb +0 -21
- data/test/logster/test_redis_rate_limiter.rb +0 -246
- data/test/logster/test_redis_store.rb +0 -1165
- data/test/test_helper.rb +0 -66
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import Preload, { getRootPath } from "client-app/lib/preload";
|
|
2
|
-
|
|
3
|
-
const entityMap = {
|
|
4
|
-
"&": "&",
|
|
5
|
-
"<": "<",
|
|
6
|
-
">": ">",
|
|
7
|
-
'"': """,
|
|
8
|
-
"'": "'",
|
|
9
|
-
"/": "/",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export function escapeHtml(string) {
|
|
13
|
-
return String(string).replace(/[&<>"'/]/g, (s) => entityMap[s]);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function ajax(url, settings) {
|
|
17
|
-
// eslint-disable-next-line no-restricted-globals
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
settings ||= {};
|
|
20
|
-
const xhr = new XMLHttpRequest();
|
|
21
|
-
url = getRootPath() + url;
|
|
22
|
-
|
|
23
|
-
if (settings.data) {
|
|
24
|
-
for (const [param, value] of Object.entries(settings.data)) {
|
|
25
|
-
url += url.includes("?") ? "&" : "?";
|
|
26
|
-
url += `${param}=${encodeURIComponent(value)}`;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
xhr.open(settings.method || settings.type || "GET", url);
|
|
31
|
-
xhr.setRequestHeader("X-SILENCE-LOGGER", true);
|
|
32
|
-
|
|
33
|
-
if (settings.headers) {
|
|
34
|
-
for (const [header, value] of Object.entries(settings.headers)) {
|
|
35
|
-
xhr.setRequestHeader(header, value);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
xhr.onreadystatechange = () => {
|
|
40
|
-
if (xhr.readyState === 4) {
|
|
41
|
-
let status = xhr.status;
|
|
42
|
-
if ((status >= 200 && status < 300) || status === 304) {
|
|
43
|
-
const type = xhr.getResponseHeader("Content-Type");
|
|
44
|
-
let data = xhr.responseText;
|
|
45
|
-
if (/\bjson\b/.test(type)) {
|
|
46
|
-
data = JSON.parse(data);
|
|
47
|
-
}
|
|
48
|
-
resolve(data);
|
|
49
|
-
} else {
|
|
50
|
-
reject(xhr);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
xhr.send();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export async function preloadOrAjax(url, settings) {
|
|
60
|
-
const preloaded = Preload.get(url.replace(".json", ""));
|
|
61
|
-
if (preloaded) {
|
|
62
|
-
return preloaded;
|
|
63
|
-
} else {
|
|
64
|
-
return await ajax(url, settings);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let HIDDEN_PROPERTY;
|
|
69
|
-
let TITLE;
|
|
70
|
-
let TITLE_COUNT;
|
|
71
|
-
|
|
72
|
-
export function updateHiddenProperty(property) {
|
|
73
|
-
HIDDEN_PROPERTY = property;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function isHidden() {
|
|
77
|
-
if (HIDDEN_PROPERTY !== undefined) {
|
|
78
|
-
return document[HIDDEN_PROPERTY];
|
|
79
|
-
} else {
|
|
80
|
-
return !document.hasFocus;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function increaseTitleCount(increment) {
|
|
85
|
-
if (!isHidden()) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
TITLE ||= document.title;
|
|
90
|
-
TITLE_COUNT ||= 0;
|
|
91
|
-
TITLE_COUNT += increment;
|
|
92
|
-
document.title = `${TITLE} (${TITLE_COUNT})`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function resetTitleCount() {
|
|
96
|
-
TITLE_COUNT = 0;
|
|
97
|
-
document.title = TITLE || document.title;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function formatTime(timestamp) {
|
|
101
|
-
const time = moment(timestamp);
|
|
102
|
-
const now = moment();
|
|
103
|
-
|
|
104
|
-
if (time.diff(now.startOf("day")) > 0) {
|
|
105
|
-
return time.format("h:mm a");
|
|
106
|
-
} else if (time.diff(now.startOf("week")) > 0) {
|
|
107
|
-
return time.format("dd h:mm a");
|
|
108
|
-
} else if (time.diff(now.startOf("year")) > 0) {
|
|
109
|
-
return time.format("D MMM h:mm a");
|
|
110
|
-
} else {
|
|
111
|
-
return time.format("D MMM YY");
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function buildArrayString(array) {
|
|
116
|
-
const buffer = array.map((v) => {
|
|
117
|
-
if (v === null) {
|
|
118
|
-
return "null";
|
|
119
|
-
} else if (Array.isArray(v)) {
|
|
120
|
-
return buildArrayString(v);
|
|
121
|
-
} else {
|
|
122
|
-
return escapeHtml(v.toString());
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return "[" + buffer.join(", ") + "]";
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function buildHashString(hash, recurse, expanded = []) {
|
|
130
|
-
if (!hash) {
|
|
131
|
-
return "";
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const buffer = [];
|
|
135
|
-
const hashes = [];
|
|
136
|
-
const expandableKeys = Preload.get("env_expandable_keys") || [];
|
|
137
|
-
|
|
138
|
-
for (const [k, v] of Object.entries(hash)) {
|
|
139
|
-
if (v === null) {
|
|
140
|
-
buffer.push("null");
|
|
141
|
-
} else if (Object.prototype.toString.call(v) === "[object Array]") {
|
|
142
|
-
let valueHtml = "";
|
|
143
|
-
if (
|
|
144
|
-
expandableKeys.includes(k) &&
|
|
145
|
-
!recurse &&
|
|
146
|
-
!expanded.includes(k) &&
|
|
147
|
-
v.length > 3
|
|
148
|
-
) {
|
|
149
|
-
valueHtml = `${escapeHtml(
|
|
150
|
-
v[0]
|
|
151
|
-
)}, <a class="expand-list" data-key=${k}>${v.length - 1} more</a>`;
|
|
152
|
-
} else {
|
|
153
|
-
valueHtml = `${escapeHtml(v[0])}, ${buildArrayString(
|
|
154
|
-
v.slice(1, v.length)
|
|
155
|
-
)}`;
|
|
156
|
-
}
|
|
157
|
-
buffer.push(`<tr><td>${escapeHtml(k)}</td><td>${valueHtml}</td></tr>`);
|
|
158
|
-
} else if (typeof v === "object") {
|
|
159
|
-
hashes.push(k);
|
|
160
|
-
} else {
|
|
161
|
-
if (k === "time" && typeof v === "number") {
|
|
162
|
-
const title = moment(v).format();
|
|
163
|
-
const time = formatTime(v);
|
|
164
|
-
buffer.push(`<tr title="${title}"><td>${k}</td><td>${time}</td></tr>`);
|
|
165
|
-
} else {
|
|
166
|
-
buffer.push(
|
|
167
|
-
`<tr><td>${escapeHtml(k)}</td><td>${escapeHtml(v)}</td></tr>`
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
for (const k1 of hashes) {
|
|
174
|
-
const v = hash[k1];
|
|
175
|
-
buffer.push("<tr><td></td><td><table>");
|
|
176
|
-
buffer.push(
|
|
177
|
-
`<td>${escapeHtml(k1)}</td><td>${buildHashString(v, true)}</td>`
|
|
178
|
-
);
|
|
179
|
-
buffer.push("</table></td></tr>");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const className = recurse ? "" : "env-table";
|
|
183
|
-
return `<table class='${className}'>${buffer.join("\n")}</table>`;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export function clone(object) {
|
|
187
|
-
// simple function to clone an object
|
|
188
|
-
// we don't need it fancier than this
|
|
189
|
-
const copy = {};
|
|
190
|
-
for (const [k, v] of Object.entries(object)) {
|
|
191
|
-
copy[k] = v;
|
|
192
|
-
}
|
|
193
|
-
return copy;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function setLocalStorage(key, value) {
|
|
197
|
-
try {
|
|
198
|
-
if (window.localStorage) {
|
|
199
|
-
key = "logster-" + key;
|
|
200
|
-
window.localStorage.setItem(key, value);
|
|
201
|
-
}
|
|
202
|
-
} catch {
|
|
203
|
-
/* do nothing */
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export function getLocalStorage(key, fallback) {
|
|
208
|
-
try {
|
|
209
|
-
if (window.localStorage) {
|
|
210
|
-
key = "logster-" + key;
|
|
211
|
-
const value = window.localStorage.getItem(key);
|
|
212
|
-
if (value === null) {
|
|
213
|
-
// key doesn't exist
|
|
214
|
-
return fallback;
|
|
215
|
-
}
|
|
216
|
-
if (value === "true") {
|
|
217
|
-
return true;
|
|
218
|
-
}
|
|
219
|
-
if (value === "false") {
|
|
220
|
-
return false;
|
|
221
|
-
}
|
|
222
|
-
// Add more cases here for numbers, null, undefined etc. as/when needed
|
|
223
|
-
return value;
|
|
224
|
-
} else {
|
|
225
|
-
return fallback;
|
|
226
|
-
}
|
|
227
|
-
} catch {
|
|
228
|
-
return fallback;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import classic from "ember-classic-decorator";
|
|
2
|
-
import { reads } from "@ember/object/computed";
|
|
3
|
-
import Message from "client-app/models/message";
|
|
4
|
-
import EmberObject, { computed } from "@ember/object";
|
|
5
|
-
import { ajax } from "client-app/lib/utilities";
|
|
6
|
-
|
|
7
|
-
@classic
|
|
8
|
-
export default class Group extends EmberObject {
|
|
9
|
-
selected = false;
|
|
10
|
-
showCount = true;
|
|
11
|
-
|
|
12
|
-
@reads("regex") key;
|
|
13
|
-
@reads("messages.firstObject.message") displayMessage;
|
|
14
|
-
|
|
15
|
-
init() {
|
|
16
|
-
super.init(...arguments);
|
|
17
|
-
const messages = this.messages.map((m) => Message.create(m));
|
|
18
|
-
this.set("messages", messages);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@computed
|
|
22
|
-
get glyph() {
|
|
23
|
-
return "clone";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
@computed
|
|
27
|
-
get prefix() {
|
|
28
|
-
return "far";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
solveAll() {
|
|
32
|
-
return ajax("/solve-group", { type: "POST", data: { regex: this.regex } });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import classic from "ember-classic-decorator";
|
|
2
|
-
import { ajax, increaseTitleCount } from "client-app/lib/utilities";
|
|
3
|
-
import Message from "client-app/models/message";
|
|
4
|
-
import Group from "client-app/models/group";
|
|
5
|
-
import { compare } from "@ember/utils";
|
|
6
|
-
import EmberObject, { computed } from "@ember/object";
|
|
7
|
-
import { A } from "@ember/array";
|
|
8
|
-
|
|
9
|
-
const BATCH_SIZE = 50;
|
|
10
|
-
export const SEVERITIES = ["Debug", "Info", "Warn", "Err", "Fatal"];
|
|
11
|
-
|
|
12
|
-
@classic
|
|
13
|
-
export default class MessageCollection extends EmberObject {
|
|
14
|
-
total = 0;
|
|
15
|
-
rows = A();
|
|
16
|
-
currentRow = null;
|
|
17
|
-
currentTab = null;
|
|
18
|
-
currentEnvPosition = 0;
|
|
19
|
-
currentGroupedMessagesPosition = 0;
|
|
20
|
-
search = "";
|
|
21
|
-
|
|
22
|
-
@computed(...SEVERITIES.map((s) => `show${s}`))
|
|
23
|
-
get filter() {
|
|
24
|
-
const filter = [];
|
|
25
|
-
SEVERITIES.forEach((severity, index) => {
|
|
26
|
-
if (this[`show${severity}`]) {
|
|
27
|
-
filter.push(index);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
filter.push(5); // always show unknown, rare
|
|
31
|
-
return filter;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@computed("currentRow", "currentGroupedMessagesPosition")
|
|
35
|
-
get currentMessage() {
|
|
36
|
-
const row = this.currentRow;
|
|
37
|
-
const position = this.currentGroupedMessagesPosition;
|
|
38
|
-
if (row && row.group) {
|
|
39
|
-
return row.messages[position];
|
|
40
|
-
} else {
|
|
41
|
-
return row;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@computed("filter", "search.length")
|
|
46
|
-
get hideCountInLoadMore() {
|
|
47
|
-
const filter = this.filter;
|
|
48
|
-
return (
|
|
49
|
-
(this.search && this.search.length > 0) || (filter && filter.length < 6)
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
@computed("rows.length", "canLoadMore")
|
|
54
|
-
get moreBefore() {
|
|
55
|
-
return this.rows.length >= BATCH_SIZE && this.canLoadMore;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
@computed("total", "rows.length")
|
|
59
|
-
get totalBefore() {
|
|
60
|
-
return this.total - this.rows.length;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
@computed("search")
|
|
64
|
-
get regexSearch() {
|
|
65
|
-
const search = this.search;
|
|
66
|
-
if (search && search.length > 2 && search[0] === "/") {
|
|
67
|
-
const match = search.match(/\/(.*)\/(.*)/);
|
|
68
|
-
if (match && match.length === 3) {
|
|
69
|
-
try {
|
|
70
|
-
return new RegExp(match[1], match[2]);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
// don't care
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async solve(message) {
|
|
80
|
-
await message.solve();
|
|
81
|
-
this.reload();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
selectRow(row, opts = {}) {
|
|
85
|
-
const old = this.currentRow;
|
|
86
|
-
if (old) {
|
|
87
|
-
old.set("selected", false);
|
|
88
|
-
}
|
|
89
|
-
row.set("selected", true);
|
|
90
|
-
const currentGroupedMessagesPosition = opts["messageIndex"] || 0;
|
|
91
|
-
const shouldRefresh =
|
|
92
|
-
currentGroupedMessagesPosition === this.currentGroupedMessagesPosition;
|
|
93
|
-
this.setProperties({
|
|
94
|
-
currentRow: row,
|
|
95
|
-
loadingEnv: false,
|
|
96
|
-
currentGroupedMessagesPosition,
|
|
97
|
-
currentEnvPosition: 0,
|
|
98
|
-
});
|
|
99
|
-
if (shouldRefresh) {
|
|
100
|
-
this.notifyPropertyChange("currentGroupedMessagesPosition");
|
|
101
|
-
}
|
|
102
|
-
const forceFetchEnv = this.currentMessage && !this.currentMessage.env;
|
|
103
|
-
this.fetchEnv({ force: forceFetchEnv });
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
tabChanged(newTab) {
|
|
107
|
-
this.setProperties({
|
|
108
|
-
currentTab: newTab,
|
|
109
|
-
loadingEnv: false,
|
|
110
|
-
});
|
|
111
|
-
this.fetchEnv();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
groupedMessageChanged(newPosition) {
|
|
115
|
-
this.setProperties({
|
|
116
|
-
currentGroupedMessagesPosition: newPosition,
|
|
117
|
-
currentEnvPosition: 0,
|
|
118
|
-
});
|
|
119
|
-
const forceFetchEnv = this.currentMessage && !this.currentMessage.env;
|
|
120
|
-
this.fetchEnv({ force: forceFetchEnv });
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
envChanged(newPosition) {
|
|
124
|
-
this.set("currentEnvPosition", newPosition);
|
|
125
|
-
this.fetchEnv();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
fetchEnv(opts = {}) {
|
|
129
|
-
const message = this.currentMessage;
|
|
130
|
-
if (
|
|
131
|
-
opts["force"] ||
|
|
132
|
-
(message && !message.env && this.currentTab === "env")
|
|
133
|
-
) {
|
|
134
|
-
this.set("loadingEnv", true);
|
|
135
|
-
return message.fetchEnv().finally(() => this.set("loadingEnv", false));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
findEquivalentMessageIndex(row) {
|
|
140
|
-
let messageIndex = 0;
|
|
141
|
-
if (
|
|
142
|
-
row?.group &&
|
|
143
|
-
this.currentRow?.group &&
|
|
144
|
-
row.key === this.currentRow.key
|
|
145
|
-
) {
|
|
146
|
-
messageIndex = row.messages.mapBy("key").indexOf(this.currentMessage.key);
|
|
147
|
-
messageIndex = Math.max(0, messageIndex);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return messageIndex;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
updateSelectedRow() {
|
|
154
|
-
const currentKey = this.currentRow?.key;
|
|
155
|
-
|
|
156
|
-
if (currentKey && this.rows) {
|
|
157
|
-
const match = this.rows.find((m) => m.key === currentKey);
|
|
158
|
-
if (match) {
|
|
159
|
-
const messageIndex = this.findEquivalentMessageIndex(match);
|
|
160
|
-
this.selectRow(match, { messageIndex });
|
|
161
|
-
} else {
|
|
162
|
-
this.setProperties({
|
|
163
|
-
currentRow: null,
|
|
164
|
-
currentEnvPosition: 0,
|
|
165
|
-
currentGroupedMessagesPosition: 0,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async load(opts) {
|
|
172
|
-
opts ||= {};
|
|
173
|
-
|
|
174
|
-
const data = {
|
|
175
|
-
filter: this.filter.join("_"),
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
if (this.search && this.search.length > 0) {
|
|
179
|
-
data.search = this.search;
|
|
180
|
-
const regexSearch = this.regexSearch;
|
|
181
|
-
if (regexSearch) {
|
|
182
|
-
data.regex_search = "true";
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (opts.before) {
|
|
187
|
-
data.before = opts.before;
|
|
188
|
-
if (opts.knownGroups) {
|
|
189
|
-
data.known_groups = opts.knownGroups;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (opts.after) {
|
|
194
|
-
data.after = opts.after;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
this.set("loading", true);
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const response = await ajax("/messages.json", {
|
|
201
|
-
data,
|
|
202
|
-
method: "POST",
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// guard against race: ensure the results we're trying to apply
|
|
206
|
-
// match the current search terms
|
|
207
|
-
if (compare(response.filter, this.filter) !== 0) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (compare(response.search, this.search) !== 0) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (response.messages.length > 0) {
|
|
216
|
-
const newRows = this.toObjects(response.messages);
|
|
217
|
-
|
|
218
|
-
if (opts.before) {
|
|
219
|
-
this.rows.unshiftObjects(newRows);
|
|
220
|
-
} else {
|
|
221
|
-
for (const newRow of newRows) {
|
|
222
|
-
for (const row of this.rows) {
|
|
223
|
-
if (row.key !== newRow.key) {
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
this.rows.removeObject(row);
|
|
228
|
-
|
|
229
|
-
if (this.currentRow === row) {
|
|
230
|
-
const messageIndex = this.findEquivalentMessageIndex(newRow);
|
|
231
|
-
this.selectRow(newRow, { messageIndex });
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
this.rows.addObjects(newRows);
|
|
237
|
-
|
|
238
|
-
if (newRows.length > 0) {
|
|
239
|
-
increaseTitleCount(newRows.length);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
this.set("total", response.total);
|
|
245
|
-
return response;
|
|
246
|
-
} finally {
|
|
247
|
-
this.set("loading", false);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
async reload() {
|
|
252
|
-
this.set("total", 0);
|
|
253
|
-
this.rows.clear();
|
|
254
|
-
|
|
255
|
-
const data = await this.load();
|
|
256
|
-
this.updateCanLoadMore(data);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
updateCanLoadMore(data) {
|
|
260
|
-
if (!data) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (data.messages.length < BATCH_SIZE) {
|
|
265
|
-
this.set("canLoadMore", false);
|
|
266
|
-
} else {
|
|
267
|
-
this.set("canLoadMore", true);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
loadMore() {
|
|
272
|
-
if (this.rows.length === 0) {
|
|
273
|
-
this.load({});
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const lastLog = this.rows[this.rows.length - 1];
|
|
278
|
-
const lastKey = lastLog.group ? lastLog.row_id : lastLog.key;
|
|
279
|
-
|
|
280
|
-
this.load({
|
|
281
|
-
after: lastKey,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async showMoreBefore() {
|
|
286
|
-
const firstLog = this.rows[0];
|
|
287
|
-
const firstKey = firstLog.group ? firstLog.row_id : firstLog.key;
|
|
288
|
-
const knownGroups = this.rows.filterBy("group").mapBy("regex");
|
|
289
|
-
|
|
290
|
-
const data = await this.load({
|
|
291
|
-
before: firstKey,
|
|
292
|
-
knownGroups,
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
this.updateCanLoadMore(data);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
toObjects(rows) {
|
|
299
|
-
return rows.map((m) => {
|
|
300
|
-
return m.group ? Group.create(m) : Message.create(m);
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import classic from "ember-classic-decorator";
|
|
2
|
-
import { gt } from "@ember/object/computed";
|
|
3
|
-
import EmberObject, { computed } from "@ember/object";
|
|
4
|
-
import { ajax } from "client-app/lib/utilities";
|
|
5
|
-
import { getRootPath } from "client-app/lib/preload";
|
|
6
|
-
|
|
7
|
-
@classic
|
|
8
|
-
export default class Message extends EmberObject {
|
|
9
|
-
MAX_LEN = 200;
|
|
10
|
-
|
|
11
|
-
@gt("count", 1) showCount;
|
|
12
|
-
|
|
13
|
-
@computed("MAX_LEN", "expanded", "message.length")
|
|
14
|
-
get hasMore() {
|
|
15
|
-
return !this.expanded && this.message.length > this.MAX_LEN;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
@computed("key")
|
|
19
|
-
get shareUrl() {
|
|
20
|
-
return `${getRootPath()}/show/${this.key}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@computed("MAX_LEN", "expanded", "message.length")
|
|
24
|
-
get displayMessage() {
|
|
25
|
-
let message = this.message;
|
|
26
|
-
|
|
27
|
-
if (!this.expanded && this.message.length > this.MAX_LEN) {
|
|
28
|
-
message = this.message.substr(0, this.MAX_LEN);
|
|
29
|
-
}
|
|
30
|
-
return message;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
@computed("backtrace.length", "env.{application_version,length}")
|
|
34
|
-
get canSolve() {
|
|
35
|
-
const appVersion = Array.isArray(this.env)
|
|
36
|
-
? this.env
|
|
37
|
-
.map((e) => e.application_version)
|
|
38
|
-
.compact()
|
|
39
|
-
.join("")
|
|
40
|
-
: this.env && this.env.application_version;
|
|
41
|
-
return appVersion && this.backtrace && this.backtrace.length > 0;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@computed("severity")
|
|
45
|
-
get rowClass() {
|
|
46
|
-
switch (this.severity) {
|
|
47
|
-
case 0:
|
|
48
|
-
return "debug";
|
|
49
|
-
case 1:
|
|
50
|
-
return "info";
|
|
51
|
-
case 2:
|
|
52
|
-
return "warn";
|
|
53
|
-
case 3:
|
|
54
|
-
return "error";
|
|
55
|
-
case 4:
|
|
56
|
-
return "fatal";
|
|
57
|
-
default:
|
|
58
|
-
return "unknown";
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
@computed("severity")
|
|
63
|
-
get glyph() {
|
|
64
|
-
switch (this.severity) {
|
|
65
|
-
case 0:
|
|
66
|
-
return "";
|
|
67
|
-
case 1:
|
|
68
|
-
return "";
|
|
69
|
-
case 2:
|
|
70
|
-
return "exclamation-circle";
|
|
71
|
-
case 3:
|
|
72
|
-
return "times-circle";
|
|
73
|
-
case 4:
|
|
74
|
-
return "times-circle";
|
|
75
|
-
default:
|
|
76
|
-
return "question-circle";
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
get prefix() {
|
|
81
|
-
return "fas";
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
@computed("severity")
|
|
85
|
-
get klass() {
|
|
86
|
-
switch (this.severity) {
|
|
87
|
-
case 0:
|
|
88
|
-
return "";
|
|
89
|
-
case 1:
|
|
90
|
-
return "";
|
|
91
|
-
case 2:
|
|
92
|
-
return "warning";
|
|
93
|
-
case 3:
|
|
94
|
-
return "error";
|
|
95
|
-
case 4:
|
|
96
|
-
return "fatal";
|
|
97
|
-
default:
|
|
98
|
-
return "unknown";
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async fetchEnv() {
|
|
103
|
-
const env = await ajax(`/fetch-env/${this.key}.json`);
|
|
104
|
-
this.set("env", env);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
expand() {
|
|
108
|
-
this.set("expanded", true);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
solve() {
|
|
112
|
-
return ajax(`/solve/${this.key}`, { type: "PUT" });
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
destroy() {
|
|
116
|
-
return ajax(`/message/${this.key}`, { type: "DELETE" });
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
protect() {
|
|
120
|
-
this.set("protected", true);
|
|
121
|
-
return ajax(`/protect/${this.key}`, { type: "PUT" });
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
unprotect() {
|
|
125
|
-
this.set("protected", false);
|
|
126
|
-
return ajax(`/unprotect/${this.key}`, { type: "DELETE" });
|
|
127
|
-
}
|
|
128
|
-
}
|