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.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/README.md +29 -14
  4. data/assets/javascript/main-C9t0S9He.js +1 -0
  5. data/assets/javascript/modules-4-12-BnbZfQQN.js +1 -0
  6. data/assets/javascript/vendor.js +11 -5260
  7. data/assets/logster-config.json +18 -0
  8. data/assets/manifest.json +23 -0
  9. data/assets/stylesheets/main-et5OPj6E.css +1 -0
  10. data/lib/logster/configuration.rb +1 -0
  11. data/lib/logster/middleware/reporter.rb +34 -3
  12. data/lib/logster/middleware/viewer.rb +204 -32
  13. data/lib/logster/rails/railtie.rb +4 -20
  14. data/lib/logster/redis_store.rb +0 -2
  15. data/lib/logster/version.rb +1 -1
  16. data/lib/logster.rb +1 -1
  17. metadata +17 -186
  18. data/.github/workflows/ci.yml +0 -140
  19. data/.gitignore +0 -3
  20. data/.rubocop.yml +0 -12
  21. data/.streerc +0 -2
  22. data/Gemfile +0 -10
  23. data/Guardfile +0 -10
  24. data/Rakefile +0 -24
  25. data/assets/javascript/.gitkeep +0 -0
  26. data/assets/javascript/chunk.524.b7d0b89d25457a72409c.js +0 -22
  27. data/assets/javascript/chunk.582.5a04ae4713e692cd335a.js +0 -22
  28. data/assets/javascript/chunk.747.a730c497582bb6742a6e.js +0 -579
  29. data/assets/javascript/chunk.761.64949d89942c829e5c1b.js +0 -1213
  30. data/assets/javascript/client-app.js +0 -1389
  31. data/assets/stylesheets/.gitkeep +0 -0
  32. data/assets/stylesheets/client-app.css +0 -1
  33. data/assets/stylesheets/vendor.css +0 -1
  34. data/build_client_app.sh +0 -10
  35. data/client-app/.editorconfig +0 -19
  36. data/client-app/.ember-cli +0 -9
  37. data/client-app/.eslintignore +0 -20
  38. data/client-app/.eslintrc +0 -10
  39. data/client-app/.gitignore +0 -23
  40. data/client-app/.prettierignore +0 -21
  41. data/client-app/.prettierrc +0 -1
  42. data/client-app/.template-lintrc.js +0 -10
  43. data/client-app/.watchmanconfig +0 -3
  44. data/client-app/README.md +0 -56
  45. data/client-app/app/app.js +0 -12
  46. data/client-app/app/components/actions-menu.js +0 -50
  47. data/client-app/app/components/back-to-site-link.js +0 -9
  48. data/client-app/app/components/back-trace.js +0 -153
  49. data/client-app/app/components/env-tab.js +0 -68
  50. data/client-app/app/components/message-info.js +0 -151
  51. data/client-app/app/components/message-row.js +0 -46
  52. data/client-app/app/components/page-nav.js +0 -42
  53. data/client-app/app/components/panel-resizer.js +0 -108
  54. data/client-app/app/components/patterns-list.js +0 -142
  55. data/client-app/app/components/tab-contents.js +0 -23
  56. data/client-app/app/components/tabbed-section.js +0 -45
  57. data/client-app/app/components/time-formatter.js +0 -36
  58. data/client-app/app/controllers/index.js +0 -288
  59. data/client-app/app/controllers/show.js +0 -39
  60. data/client-app/app/helpers/logster-url.js +0 -12
  61. data/client-app/app/helpers/or.js +0 -7
  62. data/client-app/app/index.html +0 -31
  63. data/client-app/app/initializers/app-init.js +0 -71
  64. data/client-app/app/lib/decorators.js +0 -13
  65. data/client-app/app/lib/preload.js +0 -43
  66. data/client-app/app/lib/utilities.js +0 -230
  67. data/client-app/app/models/group.js +0 -34
  68. data/client-app/app/models/message-collection.js +0 -303
  69. data/client-app/app/models/message.js +0 -128
  70. data/client-app/app/models/pattern-item.js +0 -32
  71. data/client-app/app/resolver.js +0 -3
  72. data/client-app/app/router.js +0 -13
  73. data/client-app/app/routes/index.js +0 -64
  74. data/client-app/app/routes/settings.js +0 -32
  75. data/client-app/app/routes/show.js +0 -16
  76. data/client-app/app/services/events.js +0 -4
  77. data/client-app/app/styles/app.css +0 -898
  78. data/client-app/app/templates/application.hbs +0 -1
  79. data/client-app/app/templates/components/actions-menu.hbs +0 -31
  80. data/client-app/app/templates/components/back-to-site-link.hbs +0 -8
  81. data/client-app/app/templates/components/back-trace.hbs +0 -15
  82. data/client-app/app/templates/components/env-tab.hbs +0 -10
  83. data/client-app/app/templates/components/message-info.hbs +0 -86
  84. data/client-app/app/templates/components/message-row.hbs +0 -32
  85. data/client-app/app/templates/components/page-nav.hbs +0 -37
  86. data/client-app/app/templates/components/panel-resizer.hbs +0 -3
  87. data/client-app/app/templates/components/patterns-list.hbs +0 -78
  88. data/client-app/app/templates/components/tabbed-section.hbs +0 -18
  89. data/client-app/app/templates/components/time-formatter.hbs +0 -1
  90. data/client-app/app/templates/index.hbs +0 -192
  91. data/client-app/app/templates/settings.hbs +0 -47
  92. data/client-app/app/templates/show.hbs +0 -13
  93. data/client-app/config/ember-cli-update.json +0 -18
  94. data/client-app/config/environment.js +0 -51
  95. data/client-app/config/icons.js +0 -28
  96. data/client-app/config/optional-features.json +0 -6
  97. data/client-app/config/targets.js +0 -26
  98. data/client-app/ember-cli-build.js +0 -34
  99. data/client-app/package.json +0 -76
  100. data/client-app/preload-json-manager.rb +0 -35
  101. data/client-app/public/assets/images/icon_144x144.png +0 -0
  102. data/client-app/public/assets/images/icon_64x64.png +0 -0
  103. data/client-app/testem.js +0 -23
  104. data/client-app/tests/index.html +0 -41
  105. data/client-app/tests/integration/components/back-to-site-link-test.js +0 -20
  106. data/client-app/tests/integration/components/back-trace-test.js +0 -138
  107. data/client-app/tests/integration/components/env-tab-test.js +0 -220
  108. data/client-app/tests/integration/components/message-info-test.js +0 -122
  109. data/client-app/tests/integration/components/patterns-list-test.js +0 -76
  110. data/client-app/tests/test-helper.js +0 -12
  111. data/client-app/tests/unit/controllers/index-test.js +0 -77
  112. data/client-app/tests/unit/controllers/show-test.js +0 -12
  113. data/client-app/tests/unit/routes/index-test.js +0 -11
  114. data/client-app/tests/unit/routes/show-test.js +0 -11
  115. data/client-app/yarn.lock +0 -9905
  116. data/gemfiles/rails_6.1.gemfile +0 -12
  117. data/gemfiles/rails_7.0.gemfile +0 -12
  118. data/gemfiles/rails_7.1.gemfile +0 -9
  119. data/gemfiles/rails_7.2.gemfile +0 -9
  120. data/logster.gemspec +0 -43
  121. data/test/dummy/config/application.rb +0 -31
  122. data/test/dummy/config/boot.rb +0 -6
  123. data/test/dummy/config/environment.rb +0 -6
  124. data/test/examples/test_sidekiq_reporter_example.rb +0 -47
  125. data/test/fake_data/Gemfile +0 -6
  126. data/test/fake_data/generate.rb +0 -23
  127. data/test/logster/middleware/test_reporter.rb +0 -84
  128. data/test/logster/middleware/test_viewer.rb +0 -495
  129. data/test/logster/test_base_store.rb +0 -224
  130. data/test/logster/test_cache.rb +0 -39
  131. data/test/logster/test_defer_logger.rb +0 -36
  132. data/test/logster/test_group.rb +0 -92
  133. data/test/logster/test_ignore_pattern.rb +0 -42
  134. data/test/logster/test_logger.rb +0 -177
  135. data/test/logster/test_message.rb +0 -269
  136. data/test/logster/test_pattern.rb +0 -144
  137. data/test/logster/test_railtie.rb +0 -21
  138. data/test/logster/test_redis_rate_limiter.rb +0 -246
  139. data/test/logster/test_redis_store.rb +0 -1165
  140. 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
- "<": "&lt;",
6
- ">": "&gt;",
7
- '"': "&quot;",
8
- "'": "&#39;",
9
- "/": "&#x2F;",
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
- }