logviewer 1.5.7 → 1.6.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/README.md +11 -1
- data/lib/logviewer/version.rb +1 -1
- data/lib/logviewer.rb +64 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b9106af1e9941238180f211dbbc156e1a0399bf5cca0e3f19923e4c7e6ad5d1
|
4
|
+
data.tar.gz: e6af770c419e32950450d7d65d85f43c1f85146d0a76c31615a4a2ed4ddd562b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc4e7bfb85ab4faa538250ac7eefde469ee1356c62bb320abfbb43416cc34821c7a586dd2ada1d0a4dfda2c034f8eb09702635b98ef2f6a891444154c1feba3c
|
7
|
+
data.tar.gz: e40ae9a7947dfa360abea65221a691990d893790ba58e572b7e78ecf7cf62060e524a5f7b92f71058e6767445313bd368b679c8ac9e3ea937927f91d894e7bf2
|
data/README.md
CHANGED
@@ -11,6 +11,7 @@ A Ruby gem that converts NDJSON log files into a readable HTML format for easy v
|
|
11
11
|
- Simplified file paths (shows only filename, not full path)
|
12
12
|
- Color-coded log levels for easy identification
|
13
13
|
- Large, readable fonts throughout the interface (18px base size)
|
14
|
+
- Interactive dynamic filtering by log level in the browser
|
14
15
|
- Responsive design that works well in any browser
|
15
16
|
- Automatically opens the generated HTML file in your default browser
|
16
17
|
|
@@ -46,7 +47,7 @@ This will:
|
|
46
47
|
logviewer --level info example.ndjson
|
47
48
|
```
|
48
49
|
|
49
|
-
Only
|
50
|
+
Only includes log entries with level "info" and above in the HTML file. You can then use the interactive dropdown in the browser to filter further.
|
50
51
|
|
51
52
|
### Auto-Detection of Log Files
|
52
53
|
|
@@ -104,6 +105,7 @@ Example log entry:
|
|
104
105
|
The generated HTML file will be saved in `/tmp/` with a timestamp and automatically opened in your browser. The HTML includes:
|
105
106
|
|
106
107
|
- A wide, responsive table layout (1800px max width) with columns in order: date, level, tag, file, function, text
|
108
|
+
- Interactive log level filtering dropdown for dynamic filtering in the browser
|
107
109
|
- Human-readable timestamps (MM/DD HH:MM:SS format)
|
108
110
|
- Color-coded log levels
|
109
111
|
- Sticky header for easy navigation
|
@@ -114,6 +116,14 @@ The generated HTML file will be saved in `/tmp/` with a timestamp and automatica
|
|
114
116
|
- Date, file, and function names in monospace font
|
115
117
|
- Color-coded tags for easy categorization
|
116
118
|
|
119
|
+
## Interactive Features
|
120
|
+
|
121
|
+
Once the HTML file opens in your browser, you can:
|
122
|
+
- Use the dropdown in the header to dynamically filter log entries by minimum level
|
123
|
+
- Filter changes are applied instantly without page reload
|
124
|
+
- Entry counts update automatically to show how many entries match the current filter
|
125
|
+
- Command line level acts as the initial data set - browser filtering works within those entries
|
126
|
+
|
117
127
|
## Development
|
118
128
|
|
119
129
|
After checking out the repo, run the following commands to set up development:
|
data/lib/logviewer/version.rb
CHANGED
data/lib/logviewer.rb
CHANGED
@@ -252,6 +252,24 @@ module LogViewer
|
|
252
252
|
<div class="header">
|
253
253
|
<h1>Log Viewer</h1>
|
254
254
|
<p>#{File.basename(@input_file)} • #{logs.length} entries • Level: #{@min_level.upcase}+</p>
|
255
|
+
<div style="margin-top: 15px;">
|
256
|
+
<label for="levelFilter" style="color: white; margin-right: 10px;">Filter by level:</label>
|
257
|
+
<select id="levelFilter" style="padding: 5px; font-size: 14px; border-radius: 4px; border: none;">
|
258
|
+
HTML
|
259
|
+
|
260
|
+
# Generate dropdown options only for levels >= command line minimum
|
261
|
+
min_level_num = LOG_LEVELS[@min_level]
|
262
|
+
LOG_LEVELS.each do |level, level_num|
|
263
|
+
if level_num >= min_level_num
|
264
|
+
html += <<~HTML
|
265
|
+
<option value="#{level}">#{level.upcase}+</option>
|
266
|
+
HTML
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
html += <<~HTML
|
271
|
+
</select>
|
272
|
+
</div>
|
255
273
|
</div>
|
256
274
|
<div class="table-container">
|
257
275
|
<table>
|
@@ -279,7 +297,7 @@ module LogViewer
|
|
279
297
|
method_content = log[:method].empty? ? '<span class="empty">-</span>' : log[:method]
|
280
298
|
|
281
299
|
html += <<~HTML
|
282
|
-
<tr>
|
300
|
+
<tr data-level="#{log[:level].downcase}" data-level-num="#{LOG_LEVELS[log[:level].downcase] || 0}">
|
283
301
|
<td class="timestamp">#{timestamp_content}</td>
|
284
302
|
<td class="level" style="#{level_style}">#{log[:level]}</td>
|
285
303
|
<td class="tag">#{tag_content}</td>
|
@@ -295,6 +313,51 @@ module LogViewer
|
|
295
313
|
</table>
|
296
314
|
</div>
|
297
315
|
</div>
|
316
|
+
|
317
|
+
<script>
|
318
|
+
const LOG_LEVELS = {
|
319
|
+
'trace': 0,
|
320
|
+
'debug': 1,
|
321
|
+
'info': 2,
|
322
|
+
'warning': 3,
|
323
|
+
'error': 4,
|
324
|
+
'fatal': 5
|
325
|
+
};
|
326
|
+
|
327
|
+
const levelFilter = document.getElementById('levelFilter');
|
328
|
+
const tableRows = document.querySelectorAll('tbody tr');
|
329
|
+
|
330
|
+
// Set initial filter to match command line parameter
|
331
|
+
levelFilter.value = '#{@min_level}';
|
332
|
+
|
333
|
+
function filterByLevel() {
|
334
|
+
const selectedLevel = levelFilter.value;
|
335
|
+
const selectedLevelNum = LOG_LEVELS[selectedLevel];
|
336
|
+
let visibleCount = 0;
|
337
|
+
|
338
|
+
tableRows.forEach(row => {
|
339
|
+
const rowLevelNum = parseInt(row.dataset.levelNum);
|
340
|
+
if (rowLevelNum >= selectedLevelNum) {
|
341
|
+
row.style.display = '';
|
342
|
+
visibleCount++;
|
343
|
+
} else {
|
344
|
+
row.style.display = 'none';
|
345
|
+
}
|
346
|
+
});
|
347
|
+
|
348
|
+
// Update the header count
|
349
|
+
const header = document.querySelector('.header p');
|
350
|
+
const originalText = header.textContent.split(' • ');
|
351
|
+
originalText[1] = visibleCount + ' entries';
|
352
|
+
originalText[2] = 'Level: ' + selectedLevel.toUpperCase() + '+';
|
353
|
+
header.textContent = originalText.join(' • ');
|
354
|
+
}
|
355
|
+
|
356
|
+
levelFilter.addEventListener('change', filterByLevel);
|
357
|
+
|
358
|
+
// Apply initial filter
|
359
|
+
filterByLevel();
|
360
|
+
</script>
|
298
361
|
</body>
|
299
362
|
</html>
|
300
363
|
HTML
|