logster 2.20.1 → 3.0.0

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