logviewer 1.0.0 → 1.4.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.
- checksums.yaml +4 -4
- data/README.md +16 -5
- data/lib/logviewer/version.rb +1 -1
- data/lib/logviewer.rb +60 -11
- 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: e840049796961dbaec340da1cd042cd84b6a6f03e460d3fe7f186654d69fe6de
|
4
|
+
data.tar.gz: d6a800844d7b1deda1c8f3cf890bbcffeca9d6e7c746b38bb535b8b922b707ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fc6f9364df619503be26dddfe2ca170a3446bf1f6e7b518cd52c305e3cf30f41f128f425de598f51bec005a21ddb3da260e347066338231a9cfa5de9145ec78
|
7
|
+
data.tar.gz: a05e13067b1ef5e3a97412a9ea7239bdcf5121f7c27b9c6033bce80e570aac2dc5fc2b68e186b21d11f422f7f5898eaf14d16d973f72d04b5be41e3069e4e364
|
data/README.md
CHANGED
@@ -6,8 +6,11 @@ A Ruby gem that converts NDJSON log files into a readable HTML format for easy v
|
|
6
6
|
|
7
7
|
- Converts NDJSON log files to HTML tables
|
8
8
|
- Filters logs by minimum level (trace, debug, info, warning, error, fatal)
|
9
|
-
- Displays key fields: level, text, file, and method
|
9
|
+
- Displays key fields: timestamp, level, tag, text, file, line, and method
|
10
|
+
- Human-readable timestamp formatting (MM/DD HH:MM:SS)
|
11
|
+
- Simplified file paths (shows only filename, not full path)
|
10
12
|
- Color-coded log levels for easy identification
|
13
|
+
- Large, readable fonts throughout the interface (18px base size)
|
11
14
|
- Responsive design that works well in any browser
|
12
15
|
- Automatically opens the generated HTML file in your default browser
|
13
16
|
|
@@ -67,25 +70,33 @@ logviewer --version
|
|
67
70
|
|
68
71
|
The tool expects NDJSON (newline-delimited JSON) files where each line contains a JSON object with these fields:
|
69
72
|
|
73
|
+
- `timestamp`: ISO 8601 timestamp (e.g., "2025-06-02T18:22:48.855-07:00")
|
70
74
|
- `level`: Log level (trace, debug, info, warning, error, fatal)
|
75
|
+
- `tag`: Category or module tag (e.g., "Play/manager")
|
71
76
|
- `text`: The log message
|
72
|
-
- `file`: Source file
|
77
|
+
- `file`: Source file path (displayed as filename only)
|
78
|
+
- `line`: Line number in the source file
|
73
79
|
- `method`: Function/method name
|
74
80
|
|
75
81
|
Example log entry:
|
76
82
|
```json
|
77
|
-
{"level":"info","text":"User logged in successfully","file":"auth.rb","method":"login"}
|
83
|
+
{"timestamp":"2025-06-02T18:22:48.855-07:00","level":"info","tag":"Auth/manager","text":"User logged in successfully","file":"auth.rb","line":42,"method":"login"}
|
78
84
|
```
|
79
85
|
|
80
86
|
## Output
|
81
87
|
|
82
88
|
The generated HTML file will be saved in `/tmp/` with a timestamp and automatically opened in your browser. The HTML includes:
|
83
89
|
|
84
|
-
- A responsive table layout
|
90
|
+
- A wide, responsive table layout (1800px max width) with timestamp, level, tag, text, file, line, and method columns
|
91
|
+
- Human-readable timestamps (MM/DD HH:MM:SS format)
|
85
92
|
- Color-coded log levels
|
86
93
|
- Sticky header for easy navigation
|
87
94
|
- Hover effects for better readability
|
88
|
-
-
|
95
|
+
- Large fonts (18px base size) for excellent readability
|
96
|
+
- Simplified file display (filename only, not full paths)
|
97
|
+
- Optimized column widths with expanded text area for log messages
|
98
|
+
- Timestamp, file, line, and method names in monospace font
|
99
|
+
- Color-coded tags for easy categorization
|
89
100
|
|
90
101
|
## Development
|
91
102
|
|
data/lib/logviewer/version.rb
CHANGED
data/lib/logviewer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'optparse'
|
3
3
|
require 'fileutils'
|
4
|
+
require 'time'
|
4
5
|
require_relative 'logviewer/version'
|
5
6
|
|
6
7
|
module LogViewer
|
@@ -74,9 +75,12 @@ module LogViewer
|
|
74
75
|
|
75
76
|
if should_include_log?(log_entry['level'])
|
76
77
|
logs << {
|
78
|
+
timestamp: log_entry['timestamp'] || '',
|
77
79
|
level: log_entry['level'] || 'unknown',
|
80
|
+
tag: log_entry['tag'] || '',
|
78
81
|
text: log_entry['text'] || '',
|
79
82
|
file: log_entry['file'] || '',
|
83
|
+
line: log_entry['line'],
|
80
84
|
method: log_entry['method'] || ''
|
81
85
|
}
|
82
86
|
end
|
@@ -107,6 +111,22 @@ module LogViewer
|
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
114
|
+
def format_timestamp(timestamp_str)
|
115
|
+
return '' if timestamp_str.nil? || timestamp_str.empty?
|
116
|
+
|
117
|
+
begin
|
118
|
+
time = Time.parse(timestamp_str)
|
119
|
+
time.strftime('%m/%d %H:%M:%S')
|
120
|
+
rescue => e
|
121
|
+
timestamp_str # fallback to original if parsing fails
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def extract_filename(file_path)
|
126
|
+
return '' if file_path.nil? || file_path.empty?
|
127
|
+
File.basename(file_path)
|
128
|
+
end
|
129
|
+
|
110
130
|
def generate_html(logs)
|
111
131
|
html = <<~HTML
|
112
132
|
<!DOCTYPE html>
|
@@ -123,7 +143,7 @@ module LogViewer
|
|
123
143
|
background-color: #f8f9fa;
|
124
144
|
}
|
125
145
|
.container {
|
126
|
-
max-width:
|
146
|
+
max-width: 1800px;
|
127
147
|
margin: 0 auto;
|
128
148
|
background: white;
|
129
149
|
border-radius: 8px;
|
@@ -150,11 +170,11 @@ module LogViewer
|
|
150
170
|
table {
|
151
171
|
width: 100%;
|
152
172
|
border-collapse: collapse;
|
153
|
-
font-size:
|
173
|
+
font-size: 18px;
|
154
174
|
}
|
155
175
|
th {
|
156
176
|
background: #e9ecef;
|
157
|
-
padding:
|
177
|
+
padding: 18px;
|
158
178
|
text-align: left;
|
159
179
|
font-weight: 600;
|
160
180
|
border-bottom: 2px solid #dee2e6;
|
@@ -162,7 +182,7 @@ module LogViewer
|
|
162
182
|
top: 0;
|
163
183
|
}
|
164
184
|
td {
|
165
|
-
padding:
|
185
|
+
padding: 15px 18px;
|
166
186
|
border-bottom: 1px solid #dee2e6;
|
167
187
|
vertical-align: top;
|
168
188
|
}
|
@@ -172,27 +192,45 @@ module LogViewer
|
|
172
192
|
.level {
|
173
193
|
font-weight: bold;
|
174
194
|
text-transform: uppercase;
|
175
|
-
font-size:
|
195
|
+
font-size: 16px;
|
176
196
|
white-space: nowrap;
|
177
197
|
}
|
178
198
|
.text {
|
179
|
-
|
199
|
+
min-width: 600px;
|
180
200
|
word-wrap: break-word;
|
181
201
|
white-space: pre-wrap;
|
182
202
|
}
|
183
203
|
.file {
|
184
204
|
font-family: 'Monaco', 'Menlo', monospace;
|
185
|
-
font-size:
|
205
|
+
font-size: 16px;
|
186
206
|
color: #666;
|
187
207
|
max-width: 200px;
|
188
208
|
word-wrap: break-word;
|
189
209
|
}
|
190
210
|
.method {
|
191
211
|
font-family: 'Monaco', 'Menlo', monospace;
|
192
|
-
font-size:
|
212
|
+
font-size: 16px;
|
193
213
|
color: #333;
|
194
214
|
font-weight: 500;
|
195
215
|
}
|
216
|
+
.timestamp {
|
217
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
218
|
+
font-size: 15px;
|
219
|
+
color: #666;
|
220
|
+
white-space: nowrap;
|
221
|
+
}
|
222
|
+
.tag {
|
223
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
224
|
+
font-size: 16px;
|
225
|
+
color: #007acc;
|
226
|
+
font-weight: 500;
|
227
|
+
}
|
228
|
+
.line {
|
229
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
230
|
+
font-size: 16px;
|
231
|
+
color: #999;
|
232
|
+
text-align: right;
|
233
|
+
}
|
196
234
|
.empty {
|
197
235
|
color: #999;
|
198
236
|
font-style: italic;
|
@@ -209,10 +247,13 @@ module LogViewer
|
|
209
247
|
<table>
|
210
248
|
<thead>
|
211
249
|
<tr>
|
250
|
+
<th style="width: 120px;">Timestamp</th>
|
212
251
|
<th style="width: 80px;">Level</th>
|
252
|
+
<th style="width: 120px;">Tag</th>
|
213
253
|
<th>Text</th>
|
214
|
-
<th style="width:
|
215
|
-
<th style="width:
|
254
|
+
<th style="width: 180px;">File</th>
|
255
|
+
<th style="width: 50px;">Line</th>
|
256
|
+
<th style="width: 100px;">Method</th>
|
216
257
|
</tr>
|
217
258
|
</thead>
|
218
259
|
<tbody>
|
@@ -220,15 +261,23 @@ module LogViewer
|
|
220
261
|
|
221
262
|
logs.each do |log|
|
222
263
|
level_style = "color: #{level_color(log[:level])}"
|
264
|
+
formatted_timestamp = format_timestamp(log[:timestamp])
|
265
|
+
timestamp_content = formatted_timestamp.empty? ? '<span class="empty">-</span>' : formatted_timestamp
|
266
|
+
tag_content = log[:tag].empty? ? '<span class="empty">-</span>' : log[:tag]
|
223
267
|
text_content = log[:text].empty? ? '<span class="empty">-</span>' : log[:text]
|
224
|
-
|
268
|
+
filename = extract_filename(log[:file])
|
269
|
+
file_content = filename.empty? ? '<span class="empty">-</span>' : filename
|
270
|
+
line_content = log[:line].nil? ? '<span class="empty">-</span>' : log[:line]
|
225
271
|
method_content = log[:method].empty? ? '<span class="empty">-</span>' : log[:method]
|
226
272
|
|
227
273
|
html += <<~HTML
|
228
274
|
<tr>
|
275
|
+
<td class="timestamp">#{timestamp_content}</td>
|
229
276
|
<td class="level" style="#{level_style}">#{log[:level]}</td>
|
277
|
+
<td class="tag">#{tag_content}</td>
|
230
278
|
<td class="text">#{text_content}</td>
|
231
279
|
<td class="file">#{file_content}</td>
|
280
|
+
<td class="line">#{line_content}</td>
|
232
281
|
<td class="method">#{method_content}</td>
|
233
282
|
</tr>
|
234
283
|
HTML
|