onlylogs 0.1.3 → 0.2.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/app/channels/onlylogs/logs_channel.rb +39 -29
- data/app/javascript/onlylogs/controllers/log_streamer_controller.js +9 -48
- data/app/models/onlylogs/batch_sender.rb +15 -3
- data/app/models/onlylogs/file.rb +20 -64
- data/app/models/onlylogs/grep.rb +8 -10
- data/app/views/onlylogs/shared/_log_container.html.erb +1 -1
- data/app/views/onlylogs/shared/_log_container_styles.html.erb +14 -5
- data/lib/onlylogs/engine.rb +0 -10
- data/lib/onlylogs/version.rb +1 -1
- metadata +1 -4
- data/app/models/onlylogs/application_record.rb +0 -5
- data/app/models/onlylogs/log_line.rb +0 -24
- data/lib/onlylogs/log_silencer_middleware.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: baff3b51025f63d5ba3537ebf50f48c75478e64287ea98e9634d19fe070a42f5
|
|
4
|
+
data.tar.gz: 47c2a4a23cfbfe44c25e0fbdbb96413e49aac96fe7ff6695c3440ec00aa0b08b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1676249dd2d66f2b9b4032473313fac9306c2f05283dfa927c229af55f5ace1f7a740456231d15de5a92b7de5b7fc56a54ecdc643e1adc33e53718ec5e2befce
|
|
7
|
+
data.tar.gz: 73d9f8296c302d3c84d5ae74748a0ca6601c26f00722b33a1fe067f1c1e62810b6e70fac8825e04763de0640759caa785092ba56f8df69f3dc8bee0373150056
|
|
@@ -68,7 +68,7 @@ module Onlylogs
|
|
|
68
68
|
|
|
69
69
|
def cleanup_existing_operations
|
|
70
70
|
if @batch_sender
|
|
71
|
-
@batch_sender.stop
|
|
71
|
+
@batch_sender.stop(send_remaining_lines: false)
|
|
72
72
|
@batch_sender = nil
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -102,10 +102,7 @@ module Onlylogs
|
|
|
102
102
|
# next
|
|
103
103
|
# end
|
|
104
104
|
|
|
105
|
-
lines_to_send <<
|
|
106
|
-
line_number: log_line.number,
|
|
107
|
-
html: render_log_line(log_line)
|
|
108
|
-
}
|
|
105
|
+
lines_to_send << render_log_line(log_line)
|
|
109
106
|
end
|
|
110
107
|
|
|
111
108
|
if lines_to_send.any?
|
|
@@ -129,10 +126,21 @@ module Onlylogs
|
|
|
129
126
|
|
|
130
127
|
@log_watcher_running = false
|
|
131
128
|
|
|
132
|
-
|
|
129
|
+
# Wait for graceful shutdown
|
|
130
|
+
if @log_watcher_thread&.alive?
|
|
131
|
+
@log_watcher_thread.join(3)
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
# If still alive after 3 seconds, force kill (but log it)
|
|
134
|
+
if @log_watcher_thread.alive?
|
|
135
|
+
Rails.logger.warn "Onlylogs: Force killing watcher thread after timeout"
|
|
136
|
+
@log_watcher_thread.kill
|
|
137
|
+
@log_watcher_thread.join(1)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Clear references to allow GC
|
|
142
|
+
@log_watcher_thread = nil
|
|
143
|
+
@log_file = nil
|
|
136
144
|
end
|
|
137
145
|
|
|
138
146
|
def read_entire_file_with_filter(file_path, filter = nil, regexp_mode = false, start_position = 0, end_position = nil)
|
|
@@ -146,36 +154,38 @@ module Onlylogs
|
|
|
146
154
|
|
|
147
155
|
line_count = 0
|
|
148
156
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
begin
|
|
158
|
+
Rails.logger.silence(Logger::ERROR) do
|
|
159
|
+
@log_file.grep(filter, regexp_mode: regexp_mode, start_position: start_position, end_position: end_position) do |log_line|
|
|
160
|
+
return if @batch_sender.nil?
|
|
152
161
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
line_number: log_line.number,
|
|
156
|
-
html: render_log_line(log_line)
|
|
157
|
-
})
|
|
162
|
+
# Add to batch buffer (sender thread will handle sending)
|
|
163
|
+
@batch_sender.add_line(render_log_line(log_line))
|
|
158
164
|
|
|
159
|
-
|
|
165
|
+
line_count += 1
|
|
166
|
+
end
|
|
160
167
|
end
|
|
161
|
-
end
|
|
162
168
|
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
# Stop batch sender and flush any remaining lines
|
|
170
|
+
@batch_sender.stop
|
|
165
171
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
# Send completion message
|
|
173
|
+
if line_count >= Onlylogs.max_line_matches
|
|
174
|
+
transmit({ action: "finish", content: "Search finished. Search results limit reached." })
|
|
175
|
+
else
|
|
176
|
+
transmit({ action: "finish", content: "Search finished." })
|
|
177
|
+
end
|
|
178
|
+
ensure
|
|
179
|
+
# Always cleanup even if interrupted or error occurs
|
|
180
|
+
@batch_sender&.stop
|
|
181
|
+
@batch_sender = nil
|
|
182
|
+
@log_file = nil
|
|
183
|
+
@log_watcher_running = false
|
|
171
184
|
end
|
|
172
|
-
|
|
173
|
-
@log_watcher_running = false
|
|
174
185
|
end
|
|
175
186
|
|
|
176
187
|
def render_log_line(log_line)
|
|
177
|
-
"<pre
|
|
178
|
-
"<span class=\"line-number\">#{log_line.parsed_number}</span>#{log_line.parsed_text}</pre>"
|
|
188
|
+
"<pre>#{FilePathParser.parse(AnsiColorParser.parse(ERB::Util.html_escape(log_line)))}</pre>"
|
|
179
189
|
end
|
|
180
190
|
end
|
|
181
191
|
end
|
|
@@ -5,7 +5,6 @@ export default class LogStreamerController extends Controller {
|
|
|
5
5
|
static values = {
|
|
6
6
|
filePath: { type: String },
|
|
7
7
|
cursorPosition: { type: Number, default: 0 },
|
|
8
|
-
lastLineNumber: { type: Number, default: 0 },
|
|
9
8
|
autoScroll: { type: Boolean, default: true },
|
|
10
9
|
autoStart: { type: Boolean, default: true },
|
|
11
10
|
filter: { type: String, default: '' },
|
|
@@ -13,7 +12,7 @@ export default class LogStreamerController extends Controller {
|
|
|
13
12
|
regexpMode: { type: Boolean, default: false }
|
|
14
13
|
};
|
|
15
14
|
|
|
16
|
-
static targets = ["logLines", "filterInput", "
|
|
15
|
+
static targets = ["logLines", "filterInput", "results", "liveMode", "message", "regexpMode", "websocketStatus", "stopButton", "clearButton"];
|
|
17
16
|
|
|
18
17
|
connect() {
|
|
19
18
|
this.consumer = createConsumer();
|
|
@@ -21,8 +20,6 @@ export default class LogStreamerController extends Controller {
|
|
|
21
20
|
this.subscription = null;
|
|
22
21
|
this.isRunning = false;
|
|
23
22
|
this.reconnectTimeout = null;
|
|
24
|
-
this.minLineNumber = null;
|
|
25
|
-
this.maxLineNumber = 0;
|
|
26
23
|
this.isSearchFinished = true;
|
|
27
24
|
|
|
28
25
|
// Initialize clusterize
|
|
@@ -83,12 +80,8 @@ export default class LogStreamerController extends Controller {
|
|
|
83
80
|
}
|
|
84
81
|
|
|
85
82
|
clear() {
|
|
86
|
-
this.minLineNumber = null;
|
|
87
|
-
this.maxLineNumber = 0;
|
|
88
|
-
|
|
89
83
|
this.clusterize.clear();
|
|
90
|
-
|
|
91
|
-
this.#updateLineRangeDisplay();
|
|
84
|
+
this.#updateResultsDisplay();
|
|
92
85
|
}
|
|
93
86
|
|
|
94
87
|
toggleAutoScroll() {
|
|
@@ -180,9 +173,8 @@ export default class LogStreamerController extends Controller {
|
|
|
180
173
|
}
|
|
181
174
|
|
|
182
175
|
stopSearch() {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
176
|
+
console.log("stop search");
|
|
177
|
+
this.subscription.perform('stop_watcher');
|
|
186
178
|
}
|
|
187
179
|
|
|
188
180
|
clearLogs() {
|
|
@@ -244,7 +236,6 @@ export default class LogStreamerController extends Controller {
|
|
|
244
236
|
#handleConnected() {
|
|
245
237
|
this.subscription.perform('initialize_watcher', {
|
|
246
238
|
cursor_position: this.cursorPositionValue,
|
|
247
|
-
last_line_number: this.lastLineNumberValue,
|
|
248
239
|
file_path: this.filePathValue,
|
|
249
240
|
filter: this.filterInputTarget.value,
|
|
250
241
|
mode: this.modeValue,
|
|
@@ -273,24 +264,10 @@ export default class LogStreamerController extends Controller {
|
|
|
273
264
|
|
|
274
265
|
#handleLogLines(lines) {
|
|
275
266
|
try {
|
|
276
|
-
const newLines = [];
|
|
277
|
-
|
|
278
|
-
lines.forEach(line => {
|
|
279
|
-
const { line_number, html } = line;
|
|
280
|
-
|
|
281
|
-
if (this.minLineNumber === null || line_number < this.minLineNumber) {
|
|
282
|
-
this.minLineNumber = line_number;
|
|
283
|
-
}
|
|
284
|
-
this.maxLineNumber = Math.max(this.maxLineNumber, line_number);
|
|
285
|
-
|
|
286
|
-
// Add to new lines array for clusterize
|
|
287
|
-
newLines.push(html);
|
|
288
|
-
});
|
|
289
|
-
|
|
290
267
|
// Append new lines to clusterize
|
|
291
|
-
if (
|
|
292
|
-
this.clusterize.append(
|
|
293
|
-
this.#
|
|
268
|
+
if (lines.length > 0) {
|
|
269
|
+
this.clusterize.append(lines);
|
|
270
|
+
this.#updateResultsDisplay();
|
|
294
271
|
this.scroll();
|
|
295
272
|
}
|
|
296
273
|
|
|
@@ -313,13 +290,8 @@ export default class LogStreamerController extends Controller {
|
|
|
313
290
|
}
|
|
314
291
|
|
|
315
292
|
#handleFinish(message) {
|
|
316
|
-
// Display the finish message without loading icon
|
|
317
293
|
this.messageTarget.innerHTML = message;
|
|
318
|
-
|
|
319
|
-
// Mark search as finished
|
|
320
294
|
this.isSearchFinished = true;
|
|
321
|
-
|
|
322
|
-
// Update stop button visibility (should hide it)
|
|
323
295
|
this.updateStopButtonVisibility();
|
|
324
296
|
}
|
|
325
297
|
|
|
@@ -341,19 +313,9 @@ export default class LogStreamerController extends Controller {
|
|
|
341
313
|
this.messageTarget.innerHTML = '';
|
|
342
314
|
}
|
|
343
315
|
|
|
344
|
-
#
|
|
316
|
+
#updateResultsDisplay() {
|
|
345
317
|
const resultsCount = this.clusterize.getRowsAmount();
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
if (this.minLineNumber === null || this.maxLineNumber === 0) {
|
|
349
|
-
lineRangeText = `No lines`;
|
|
350
|
-
} else if (this.minLineNumber === this.maxLineNumber) {
|
|
351
|
-
lineRangeText = `Line ${this.#formatNumber(this.minLineNumber)}`;
|
|
352
|
-
} else {
|
|
353
|
-
lineRangeText = `Lines ${this.#formatNumber(this.minLineNumber)} - ${this.#formatNumber(this.maxLineNumber)}`;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
this.lineRangeTarget.textContent = `${lineRangeText} | Results: ${this.#formatNumber(resultsCount)}`;
|
|
318
|
+
this.resultsTarget.textContent = `Results: ${this.#formatNumber(resultsCount)}`;
|
|
357
319
|
}
|
|
358
320
|
|
|
359
321
|
#formatNumber(number) {
|
|
@@ -393,7 +355,6 @@ export default class LogStreamerController extends Controller {
|
|
|
393
355
|
filePath: this.filePathValue,
|
|
394
356
|
cursorPosition: this.cursorPositionValue,
|
|
395
357
|
lineCount: this.clusterize.getRowsAmount(),
|
|
396
|
-
maxLineNumber: this.maxLineNumber,
|
|
397
358
|
connected: this.subscription && this.subscription.identifier
|
|
398
359
|
};
|
|
399
360
|
}
|
|
@@ -23,14 +23,26 @@ module Onlylogs
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def stop
|
|
26
|
+
def stop(send_remaining_lines: true)
|
|
27
27
|
return unless @running
|
|
28
28
|
|
|
29
29
|
@running = false
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
|
|
31
|
+
# Wait longer for graceful shutdown
|
|
32
|
+
if @sender_thread&.alive?
|
|
33
|
+
@sender_thread.join(0.5)
|
|
34
|
+
end
|
|
35
|
+
|
|
32
36
|
# Send any remaining lines
|
|
33
37
|
send_batch
|
|
38
|
+
if send_remaining_lines
|
|
39
|
+
send_batch
|
|
40
|
+
else
|
|
41
|
+
@mutex.synchronize { @buffer.clear }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Clear thread reference to allow GC
|
|
45
|
+
@sender_thread = nil
|
|
34
46
|
end
|
|
35
47
|
|
|
36
48
|
def add_line(line_data)
|
data/app/models/onlylogs/file.rb
CHANGED
|
@@ -2,12 +2,11 @@ module Onlylogs
|
|
|
2
2
|
class Error < StandardError; end
|
|
3
3
|
|
|
4
4
|
class File
|
|
5
|
-
attr_reader :path, :last_position
|
|
5
|
+
attr_reader :path, :last_position
|
|
6
6
|
|
|
7
7
|
def initialize(path, last_position: 0)
|
|
8
8
|
self.path = path
|
|
9
9
|
self.last_position = last_position
|
|
10
|
-
self.last_line_number = 0
|
|
11
10
|
validate!
|
|
12
11
|
end
|
|
13
12
|
|
|
@@ -15,7 +14,6 @@ module Onlylogs
|
|
|
15
14
|
return if position < 0
|
|
16
15
|
|
|
17
16
|
self.last_position = position
|
|
18
|
-
self.last_line_number = 0
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
def watch(&block)
|
|
@@ -58,14 +56,14 @@ module Onlylogs
|
|
|
58
56
|
end
|
|
59
57
|
|
|
60
58
|
def grep(filter, regexp_mode: false, start_position: 0, end_position: nil, &block)
|
|
61
|
-
Grep.grep(filter, path, regexp_mode: regexp_mode, start_position: start_position, end_position: end_position) do |
|
|
62
|
-
yield
|
|
59
|
+
Grep.grep(filter, path, regexp_mode: regexp_mode, start_position: start_position, end_position: end_position) do |content|
|
|
60
|
+
yield content
|
|
63
61
|
end
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
private
|
|
67
65
|
|
|
68
|
-
attr_writer :path, :last_position
|
|
66
|
+
attr_writer :path, :last_position
|
|
69
67
|
|
|
70
68
|
def read_new_lines
|
|
71
69
|
return [] unless exist?
|
|
@@ -73,74 +71,32 @@ module Onlylogs
|
|
|
73
71
|
current_size = ::File.size(path)
|
|
74
72
|
return [] if current_size <= last_position
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
lines = []
|
|
75
|
+
|
|
78
76
|
::File.open(path, "rb") do |file|
|
|
79
77
|
file.seek(last_position)
|
|
80
|
-
new_content = file.read
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
return [] if new_content.empty?
|
|
84
78
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# If we're not at the beginning of the file, check if we're at a line boundary
|
|
89
|
-
first_line_removed = false
|
|
90
|
-
if last_position > 0
|
|
91
|
-
# Read one character before to see if it was a newline
|
|
92
|
-
::File.open(path, "rb") do |file|
|
|
79
|
+
# Skip first line if we're mid-line (not at start or after newline)
|
|
80
|
+
if last_position > 0
|
|
93
81
|
file.seek(last_position - 1)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if
|
|
97
|
-
# Remove the first line as it's incomplete
|
|
98
|
-
lines.shift
|
|
99
|
-
first_line_removed = true
|
|
100
|
-
end
|
|
82
|
+
skip_first = (file.read(1) != "\n")
|
|
83
|
+
file.seek(last_position)
|
|
84
|
+
file.gets if skip_first # Consume incomplete line
|
|
101
85
|
end
|
|
102
|
-
end
|
|
103
86
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
# Find the position after the last complete line
|
|
114
|
-
::File.open(path, "rb") do |file|
|
|
115
|
-
file.seek(last_position)
|
|
116
|
-
# Read and count newlines to find where complete lines end
|
|
117
|
-
newline_count = 0
|
|
118
|
-
# If we removed the first line, we need to count one extra newline
|
|
119
|
-
# to account for the incomplete first line
|
|
120
|
-
target_newlines = lines.length + (first_line_removed ? 1 : 0)
|
|
121
|
-
while newline_count < target_newlines
|
|
122
|
-
char = file.read(1)
|
|
123
|
-
break unless char
|
|
124
|
-
|
|
125
|
-
newline_count += 1 if char == "\n"
|
|
87
|
+
# Read complete lines using gets (memory efficient, no buffer needed)
|
|
88
|
+
while (line = file.gets)
|
|
89
|
+
if line.end_with?("\n")
|
|
90
|
+
# Complete line - store as simple string
|
|
91
|
+
lines << line.chomp
|
|
92
|
+
self.last_position = file.pos
|
|
93
|
+
else
|
|
94
|
+
# Incomplete line at EOF - skip it
|
|
95
|
+
break
|
|
126
96
|
end
|
|
127
|
-
self.last_position = file.tell
|
|
128
97
|
end
|
|
129
|
-
elsif last_line_incomplete
|
|
130
|
-
# If we had lines but removed the last incomplete one,
|
|
131
|
-
# position should be at the start of the incomplete line
|
|
132
|
-
self.last_position = current_size - new_content.lines.last.length
|
|
133
|
-
elsif first_line_removed
|
|
134
|
-
# If we removed the first line but have no complete lines,
|
|
135
|
-
# position should be at the end of the file since we consumed all content
|
|
136
|
-
self.last_position = current_size
|
|
137
|
-
else
|
|
138
|
-
# No lines at all, position at end of file
|
|
139
|
-
self.last_position = current_size
|
|
140
98
|
end
|
|
141
99
|
|
|
142
|
-
lines = lines.map.with_index { |line, index| Onlylogs::LogLine.new(self.last_line_number + index, line) }
|
|
143
|
-
self.last_line_number += lines.length
|
|
144
100
|
lines
|
|
145
101
|
end
|
|
146
102
|
|
data/app/models/onlylogs/grep.rb
CHANGED
|
@@ -21,16 +21,14 @@ module Onlylogs
|
|
|
21
21
|
|
|
22
22
|
IO.popen(command_args, err: "/dev/null") do |io|
|
|
23
23
|
io.each_line do |line|
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
results << [ line_number, content ]
|
|
33
|
-
end
|
|
24
|
+
# Line numbers are no longer outputted by super_grep/super_ripgrep
|
|
25
|
+
# Use String.new to create a copy and prevent memory retention from IO buffers
|
|
26
|
+
content = String.new(line.chomp)
|
|
27
|
+
|
|
28
|
+
if block_given?
|
|
29
|
+
yield content
|
|
30
|
+
else
|
|
31
|
+
results << content
|
|
34
32
|
end
|
|
35
33
|
end
|
|
36
34
|
end
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
</button>
|
|
84
84
|
</div>
|
|
85
85
|
<div>
|
|
86
|
-
<span data-log-streamer-target="
|
|
86
|
+
<span data-log-streamer-target="results" style="color: #666;">Results: 0</span>
|
|
87
87
|
</div>
|
|
88
88
|
<div data-log-streamer-target="message"></div>
|
|
89
89
|
<% unless Onlylogs.ripgrep_enabled? %>
|
|
@@ -26,14 +26,23 @@
|
|
|
26
26
|
|
|
27
27
|
.clusterize-content {
|
|
28
28
|
outline: 0;
|
|
29
|
+
counter-reset: line-number;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
pre {
|
|
33
|
+
counter-increment: line-number;
|
|
34
|
+
|
|
35
|
+
&::before {
|
|
36
|
+
content: counter(line-number);
|
|
37
|
+
color: #aaa;
|
|
38
|
+
user-select: none;
|
|
39
|
+
margin-right: 0.5em;
|
|
40
|
+
display: inline-block;
|
|
41
|
+
text-align: right;
|
|
42
|
+
min-width: 3.5em;
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
|
-
|
|
45
|
+
|
|
37
46
|
.color-success {
|
|
38
47
|
color: green;
|
|
39
48
|
}
|
data/lib/onlylogs/engine.rb
CHANGED
|
@@ -25,15 +25,5 @@ module Onlylogs
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
|
-
|
|
29
|
-
# initializer "onlylogs.add_log_silencer" do |app|
|
|
30
|
-
# silenced_routes = ['/onlylogs']
|
|
31
|
-
#
|
|
32
|
-
# app.middleware.insert_before(
|
|
33
|
-
# Rails::Rack::Logger,
|
|
34
|
-
# Onlylogs::LogSilencerMiddleware,
|
|
35
|
-
# paths_to_silence: silenced_routes
|
|
36
|
-
# )
|
|
37
|
-
# end
|
|
38
28
|
end
|
|
39
29
|
end
|
data/lib/onlylogs/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: onlylogs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alessandro Rodi
|
|
@@ -56,12 +56,10 @@ files:
|
|
|
56
56
|
- app/javascript/onlylogs/controllers/text_selection_controller.js
|
|
57
57
|
- app/jobs/onlylogs/application_job.rb
|
|
58
58
|
- app/models/onlylogs/ansi_color_parser.rb
|
|
59
|
-
- app/models/onlylogs/application_record.rb
|
|
60
59
|
- app/models/onlylogs/batch_sender.rb
|
|
61
60
|
- app/models/onlylogs/file.rb
|
|
62
61
|
- app/models/onlylogs/file_path_parser.rb
|
|
63
62
|
- app/models/onlylogs/grep.rb
|
|
64
|
-
- app/models/onlylogs/log_line.rb
|
|
65
63
|
- app/models/onlylogs/secure_file_path.rb
|
|
66
64
|
- app/views/home/show.html.erb
|
|
67
65
|
- app/views/layouts/onlylogs/application.html.erb
|
|
@@ -76,7 +74,6 @@ files:
|
|
|
76
74
|
- lib/onlylogs/configuration.rb
|
|
77
75
|
- lib/onlylogs/engine.rb
|
|
78
76
|
- lib/onlylogs/formatter.rb
|
|
79
|
-
- lib/onlylogs/log_silencer_middleware.rb
|
|
80
77
|
- lib/onlylogs/logger.rb
|
|
81
78
|
- lib/onlylogs/socket_logger.rb
|
|
82
79
|
- lib/onlylogs/version.rb
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Onlylogs
|
|
4
|
-
class LogLine
|
|
5
|
-
attr_reader :number, :text
|
|
6
|
-
|
|
7
|
-
def initialize(number, text)
|
|
8
|
-
@number = number
|
|
9
|
-
@text = text
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def parsed_number
|
|
13
|
-
number.to_s.reverse.gsub(/(\d{3})(?=\d)/, "\\1'").reverse.rjust(7)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def parsed_text
|
|
17
|
-
FilePathParser.parse(AnsiColorParser.parse(ERB::Util.html_escape(text)))
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def to_a
|
|
21
|
-
[number, text]
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module Onlylogs
|
|
2
|
-
class LogSilencerMiddleware
|
|
3
|
-
def initialize(app, paths_to_silence:)
|
|
4
|
-
@app = app
|
|
5
|
-
# Ensure paths are an array for flexibility
|
|
6
|
-
@paths_to_silence = Array(paths_to_silence)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def call(env)
|
|
10
|
-
if silence_request?(env)
|
|
11
|
-
Rails.logger.silence do
|
|
12
|
-
@app.call(env)
|
|
13
|
-
end
|
|
14
|
-
else
|
|
15
|
-
@app.call(env)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def silence_request?(env)
|
|
22
|
-
request_path = env['PATH_INFO']
|
|
23
|
-
@paths_to_silence.any? { |path| request_path.start_with?(path) }
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|