log_sense 1.0.11 → 1.2.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/CHANGELOG.org +6 -19
- data/README.org +23 -20
- data/lib/log_sense/emitter.rb +1 -0
- data/lib/log_sense/options_parser.rb +4 -0
- data/lib/log_sense/rails_data_cruncher.rb +11 -2
- data/lib/log_sense/rails_log_parser.rb +54 -61
- data/lib/log_sense/templates/_log_structure.html.erb +24 -0
- data/lib/log_sense/templates/_performance.html.erb +21 -23
- data/lib/log_sense/templates/_summary.html.erb +23 -34
- data/lib/log_sense/templates/apache.html.erb +341 -95
- data/lib/log_sense/templates/rails.html.erb +351 -0
- data/lib/log_sense/templates/rails.txt.erb +21 -9
- data/lib/log_sense/version.rb +1 -1
- metadata +4 -3
- data/lib/log_sense/templates/_total_hits.html.erb +0 -32
@@ -0,0 +1,351 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html class="no-js" lang="en">
|
3
|
+
<head>
|
4
|
+
<title><%= options[:title] || "Log Sense: #{data[:log_file]}" %></title>
|
5
|
+
|
6
|
+
<meta charset="utf-8" />
|
7
|
+
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
9
|
+
<meta name="author" content="Log Sense">
|
10
|
+
<meta name="description" content="Analysis of <%= data[:log_file] %>">
|
11
|
+
|
12
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
13
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
14
|
+
<link href="https://fonts.googleapis.com/css2?family=PT+Sans&display=swap" rel="stylesheet">
|
15
|
+
|
16
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.min.css">
|
17
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.4/dist/css/foundation.min.css">
|
18
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/zf/dt-1.11.3/datatables.min.css"/>
|
19
|
+
|
20
|
+
|
21
|
+
<script src="https://cdn.jsdelivr.net/npm/vega@5.21.0"></script>
|
22
|
+
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5.2.0"></script>
|
23
|
+
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6.20.2"></script>
|
24
|
+
|
25
|
+
<style>
|
26
|
+
body {
|
27
|
+
font-family: 'PT Sans', sans-serif;
|
28
|
+
font-size: 80%;
|
29
|
+
}
|
30
|
+
|
31
|
+
#offCanvas {
|
32
|
+
color: white;
|
33
|
+
background: #0D0630;
|
34
|
+
border-right: none;
|
35
|
+
box-shadow: none;
|
36
|
+
padding: 0.5rem;
|
37
|
+
}
|
38
|
+
#offCanvas a {
|
39
|
+
color: #E6F9AF;
|
40
|
+
}
|
41
|
+
|
42
|
+
.contents-button {
|
43
|
+
font-size: xx-large;
|
44
|
+
}
|
45
|
+
|
46
|
+
.main-section {
|
47
|
+
margin-left: 45px;
|
48
|
+
}
|
49
|
+
|
50
|
+
h1 {
|
51
|
+
font-size: 1.8rem;
|
52
|
+
}
|
53
|
+
|
54
|
+
h2 {
|
55
|
+
font-size: 1.2rem;
|
56
|
+
}
|
57
|
+
|
58
|
+
th {
|
59
|
+
padding: 0.2rem 1.2rem 0.2rem 0.2rem !important
|
60
|
+
}
|
61
|
+
|
62
|
+
td {
|
63
|
+
padding: 0.2rem 1rem 0.2rem 0.2rem !important;
|
64
|
+
}
|
65
|
+
|
66
|
+
.hits, .visits, .size, .count, .s2xx, .s3xx, .so4xx, .total-hits, .total-visits {
|
67
|
+
text-align: right !important;
|
68
|
+
}
|
69
|
+
|
70
|
+
.card-divider {
|
71
|
+
padding: 0.2rem 0.4rem 0.2rem 0.4rem;
|
72
|
+
background: #D30001;
|
73
|
+
color: white;
|
74
|
+
}
|
75
|
+
|
76
|
+
input, select {
|
77
|
+
font-size: 0.8rem !important;
|
78
|
+
height: 1.5rem !important;
|
79
|
+
padding: 0.2rem 0.4rem 0.2rem 0.4rem !important;
|
80
|
+
}
|
81
|
+
|
82
|
+
.dataTables_info {
|
83
|
+
font-size: small;
|
84
|
+
color: rgb(202, 202, 202);
|
85
|
+
}
|
86
|
+
|
87
|
+
ul.pagination, li.paginate_button {
|
88
|
+
font-size: small;
|
89
|
+
margin-top: 0px !important;
|
90
|
+
margin-bottom: 0px !important;
|
91
|
+
padding-top: 0px !important;
|
92
|
+
padding-bottom: 0px !important;
|
93
|
+
}
|
94
|
+
|
95
|
+
.stats-list {
|
96
|
+
list-style-type: none;
|
97
|
+
clear: left;
|
98
|
+
margin: 0;
|
99
|
+
padding: 0;
|
100
|
+
text-align: center;
|
101
|
+
margin-bottom: 30px;
|
102
|
+
}
|
103
|
+
|
104
|
+
.stats-list .stats-list-positive {
|
105
|
+
color: #228b22;
|
106
|
+
}
|
107
|
+
|
108
|
+
.stats-list .stats-list-negative {
|
109
|
+
color: #a52a2a;
|
110
|
+
}
|
111
|
+
|
112
|
+
.stats-list > li {
|
113
|
+
display: inline-block;
|
114
|
+
margin-right: 10px;
|
115
|
+
padding-right: 10px;
|
116
|
+
border-right: 1px solid #cacaca;
|
117
|
+
text-align: center;
|
118
|
+
font-size: 1.1em;
|
119
|
+
font-weight: bold;
|
120
|
+
}
|
121
|
+
|
122
|
+
.stats-list > li:last-child {
|
123
|
+
border: none;
|
124
|
+
margin: 0;
|
125
|
+
padding: 0;
|
126
|
+
}
|
127
|
+
|
128
|
+
.stats-list > li .stats-list-label {
|
129
|
+
display: block;
|
130
|
+
margin-top: 2px;
|
131
|
+
font-size: 0.9em;
|
132
|
+
font-weight: normal;
|
133
|
+
}
|
134
|
+
|
135
|
+
#streaks-table .ip {
|
136
|
+
vertical-align: top;
|
137
|
+
}
|
138
|
+
#streaks-table .date {
|
139
|
+
font-weight: bold;
|
140
|
+
}
|
141
|
+
#streaks-table .res-title {
|
142
|
+
font-decoration: underline;
|
143
|
+
}
|
144
|
+
</style>
|
145
|
+
|
146
|
+
</head>
|
147
|
+
|
148
|
+
<body>
|
149
|
+
<div class="off-canvas-wrapper">
|
150
|
+
<div class="off-canvas position-left" id="offCanvas" data-off-canvas>
|
151
|
+
<nav>
|
152
|
+
<h2>Navigation</h2>
|
153
|
+
<ul class="no-bullet">
|
154
|
+
<% [
|
155
|
+
"Summary",
|
156
|
+
"Log Structure",
|
157
|
+
"Daily Distribution",
|
158
|
+
"Time Distribution",
|
159
|
+
"Statuses",
|
160
|
+
"Rails Performance",
|
161
|
+
"Fatal Events",
|
162
|
+
"IPs",
|
163
|
+
"Command Invocation",
|
164
|
+
"Performance"
|
165
|
+
].each do |item| %>
|
166
|
+
<li class="nav-item">
|
167
|
+
<a href="#<%= item.downcase.gsub(' ', '-') %>" data-close><%= item %></a>
|
168
|
+
</li>
|
169
|
+
<% end %>
|
170
|
+
</ul>
|
171
|
+
|
172
|
+
<p>
|
173
|
+
Generated by
|
174
|
+
<a href="https://github.com/avillafiorita/log_sense">LogSense</a> <br />
|
175
|
+
on <%= DateTime.now.strftime("%Y-%m-%d %H:%M") %>.<br />
|
176
|
+
<a href='https://db-ip.com'>IP Geolocation by DB-IP</a>
|
177
|
+
</p>
|
178
|
+
</nav>
|
179
|
+
</div>
|
180
|
+
<div class="off-canvas-content grid-container grid-x fluid" data-off-canvas-content>
|
181
|
+
<div data-sticky-container>
|
182
|
+
<div class="sticky" data-sticky data-margin-top="0">
|
183
|
+
<div class="contents-button">
|
184
|
+
<i id="hamburger" class="fi-list" data-toggle="offCanvas"></i>
|
185
|
+
</div>
|
186
|
+
</div>
|
187
|
+
</div>
|
188
|
+
|
189
|
+
<section class="main-section">
|
190
|
+
<h1><%= options[:title] || "Log Sense: #{data[:log_file]}" %></h1>
|
191
|
+
|
192
|
+
<p><b>Input File:</b> <%= (data[:log_file] || "stdin") %></p>
|
193
|
+
|
194
|
+
<div class="grid-x grid-margin-x">
|
195
|
+
<article class="card small-12 large-6 cell">
|
196
|
+
<div class="card-divider">
|
197
|
+
<h2 id="summary">Summary</h2>
|
198
|
+
</div>
|
199
|
+
<div class="card-section">
|
200
|
+
<%= render "summary.html.erb", data: data %>
|
201
|
+
</div>
|
202
|
+
</article>
|
203
|
+
|
204
|
+
<article class="card cell small-12 large-6">
|
205
|
+
<div class="card-divider">
|
206
|
+
<h2 id="log-structure">Log Structure</h2>
|
207
|
+
</div>
|
208
|
+
<div class="card-section">
|
209
|
+
<%= render "log_structure.html.erb", data: data %>
|
210
|
+
</div>
|
211
|
+
</article>
|
212
|
+
</div>
|
213
|
+
|
214
|
+
<% @reports = [
|
215
|
+
{ title: "Daily Distribution",
|
216
|
+
header: ["Day", "DOW", "Hits"],
|
217
|
+
rows: data[:daily_distribution],
|
218
|
+
vega_spec: {
|
219
|
+
"mark": {
|
220
|
+
"type": "line",
|
221
|
+
"point": {
|
222
|
+
"filled": false,
|
223
|
+
"fill": "white"
|
224
|
+
}
|
225
|
+
},
|
226
|
+
"encoding": {
|
227
|
+
"x": {"field": "Day", "type": "temporal"},
|
228
|
+
"y": {"field": "Hits", "type": "quantitative"}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
},
|
232
|
+
{ title: "Time Distribution",
|
233
|
+
header: ["Hour", "Hits"],
|
234
|
+
rows: data[:time_distribution],
|
235
|
+
vega_spec: {
|
236
|
+
"mark": "bar",
|
237
|
+
"encoding": {
|
238
|
+
"x": {"field": "Hour", "type": "nominal"},
|
239
|
+
"y": {"field": "Hits", "type": "quantitative"}
|
240
|
+
}
|
241
|
+
}
|
242
|
+
},
|
243
|
+
{ title: "Statuses",
|
244
|
+
header: ["Status", "Count"],
|
245
|
+
rows: data[:statuses],
|
246
|
+
vega_spec: {
|
247
|
+
"mark": "bar",
|
248
|
+
"encoding": {
|
249
|
+
"x": {"field": "Status", "type": "nominal"},
|
250
|
+
"y": {"field": "Count", "type": "quantitative"}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
},
|
254
|
+
{ title: "Rails Performance",
|
255
|
+
header: ['Controller', 'Hits', 'Min', 'Avg', 'Max'],
|
256
|
+
rows: @data[:performance]
|
257
|
+
},
|
258
|
+
{ title: "Fatal Events",
|
259
|
+
header: ['Date', 'IP', 'URL', 'Description', 'Log ID'], rows: @data[:fatal],
|
260
|
+
col: "small-12 cell"
|
261
|
+
},
|
262
|
+
{ title: "Internal Server Errors",
|
263
|
+
header: ['Date', 'Status', 'IP', 'URL', 'Description', 'Log ID'], rows: @data[:internal_server_error],
|
264
|
+
col: "small-12 cell"
|
265
|
+
},
|
266
|
+
{ title: "Errors",
|
267
|
+
header: ['Log ID', 'Context', 'Description', 'Count'], rows: @data[:error],
|
268
|
+
col: "small-12 cell"
|
269
|
+
},
|
270
|
+
{ title: "IPs",
|
271
|
+
header: ["IPs", "Hits", "Country"],
|
272
|
+
rows: data[:ips]
|
273
|
+
},
|
274
|
+
]
|
275
|
+
%>
|
276
|
+
<div class="grid-x grid-margin-x">
|
277
|
+
<% @reports.each_with_index do |report, index| %>
|
278
|
+
<article class="card cell <%= report[:col] || "small-12 large-6" %>" >
|
279
|
+
<div class="card-divider">
|
280
|
+
<h2>
|
281
|
+
<%= report[:title] %>
|
282
|
+
</h2>
|
283
|
+
</div>
|
284
|
+
|
285
|
+
<% if report[:vega_spec] %>
|
286
|
+
<div id="<%= "plot-#{index}" %>"></div>
|
287
|
+
<script>
|
288
|
+
plot_spec_<%= index %> = Object.assign(
|
289
|
+
<%= report[:vega_spec].to_json %>,
|
290
|
+
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
291
|
+
width: "container",
|
292
|
+
description: "<%= report[:title] %>",
|
293
|
+
data: {
|
294
|
+
values: [
|
295
|
+
<% report[:rows].each do |row| %>
|
296
|
+
{
|
297
|
+
<% report[:header].each_with_index do |h, i| %>
|
298
|
+
"<%= h %>": <%= (row[i].class == Integer or row[i].class == Float) ? row[i] : "\"#{row[i]}\"" %>,
|
299
|
+
<% end %>
|
300
|
+
},
|
301
|
+
<% end %>
|
302
|
+
]
|
303
|
+
},
|
304
|
+
});
|
305
|
+
vegaEmbed('#<%= "plot-#{index}"%>', plot_spec_<%= index %>);
|
306
|
+
</script>
|
307
|
+
<% end %>
|
308
|
+
<div class="card-section">
|
309
|
+
<%= render "output_table.html.erb", report %>
|
310
|
+
</div>
|
311
|
+
</article>
|
312
|
+
<% end %>
|
313
|
+
</div>
|
314
|
+
|
315
|
+
<div class="grid-x grid-margin-x">
|
316
|
+
<div class="cell small-12 large-6">
|
317
|
+
<article>
|
318
|
+
<h2 id="command-invocation">Command Invocation</h2>
|
319
|
+
|
320
|
+
<%= render "command_invocation.html.erb", data: data, options: options %>
|
321
|
+
</article>
|
322
|
+
</div>
|
323
|
+
|
324
|
+
<div class="small-12 large-6 cell">
|
325
|
+
<article>
|
326
|
+
<h2 id="performance"> Performance</h2>
|
327
|
+
|
328
|
+
<%= render "performance.html.erb", data: data %>
|
329
|
+
</article>
|
330
|
+
</div>
|
331
|
+
</div>
|
332
|
+
</section>
|
333
|
+
</div>
|
334
|
+
|
335
|
+
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
336
|
+
<script type="text/javascript" src="js/vendor/what-input.js"></script>
|
337
|
+
<script type="text/javascript" src="https://cdn.datatables.net/v/zf/dt-1.11.3/datatables.min.js"></script>
|
338
|
+
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
|
339
|
+
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.4/dist/js/foundation.min.js" crossorigin="anonymous"></script>
|
340
|
+
<script>
|
341
|
+
$(document).foundation();
|
342
|
+
|
343
|
+
$(document).ready(function () {
|
344
|
+
$('.data-table').each(function () {
|
345
|
+
$(this).DataTable();
|
346
|
+
});
|
347
|
+
});
|
348
|
+
</script>
|
349
|
+
</div>
|
350
|
+
</body>
|
351
|
+
</html>
|
@@ -26,14 +26,6 @@ table.align_column(2, :right)
|
|
26
26
|
table
|
27
27
|
%>
|
28
28
|
|
29
|
-
** IP and Country
|
30
|
-
|
31
|
-
<%=
|
32
|
-
table = Terminal::Table.new headings: ['IP', 'Events', 'Country'], rows: @data[:ips]
|
33
|
-
table.align_column(1, :right)
|
34
|
-
table
|
35
|
-
%>
|
36
|
-
|
37
29
|
** Rails Performance
|
38
30
|
|
39
31
|
<%= table = Terminal::Table.new headings: ['Controller', 'Hits', 'Min', 'Avg', 'Max'], rows: @data[:performance]
|
@@ -46,7 +38,27 @@ table
|
|
46
38
|
|
47
39
|
** Fatal Events
|
48
40
|
|
49
|
-
<%= table = Terminal::Table.new headings: ['Date', 'IP', 'URL', 'Log ID'], rows: @data[:fatal]
|
41
|
+
<%= table = Terminal::Table.new headings: ['Date', 'IP', 'URL', 'Description', 'Log ID'], rows: @data[:fatal]
|
42
|
+
table
|
43
|
+
%>
|
44
|
+
|
45
|
+
** Internal Server Errors
|
46
|
+
|
47
|
+
<%= table = Terminal::Table.new headings: ['Date', 'Status', 'IP', 'URL', 'Description', 'Log ID'], rows: @data[:internal_server_error]
|
48
|
+
table
|
49
|
+
%>
|
50
|
+
|
51
|
+
** Errors
|
52
|
+
|
53
|
+
<%= table = Terminal::Table.new headings: ['Log ID', 'Context', 'Description', 'Count'], rows: @data[:error]
|
54
|
+
table
|
55
|
+
%>
|
56
|
+
|
57
|
+
** IPs
|
58
|
+
|
59
|
+
<%=
|
60
|
+
table = Terminal::Table.new headings: ['IP', 'Hits', 'Country'], rows: @data[:ips]
|
61
|
+
table.align_column(1, :right)
|
50
62
|
table
|
51
63
|
%>
|
52
64
|
|
data/lib/log_sense/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: log_sense
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adolfo Villafiorita
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: apache_log-parser
|
@@ -152,13 +152,14 @@ files:
|
|
152
152
|
- lib/log_sense/rails_log_parser.rb
|
153
153
|
- lib/log_sense/templates/_command_invocation.html.erb
|
154
154
|
- lib/log_sense/templates/_command_invocation.txt.erb
|
155
|
+
- lib/log_sense/templates/_log_structure.html.erb
|
155
156
|
- lib/log_sense/templates/_output_table.html.erb
|
156
157
|
- lib/log_sense/templates/_performance.html.erb
|
157
158
|
- lib/log_sense/templates/_performance.txt.erb
|
158
159
|
- lib/log_sense/templates/_summary.html.erb
|
159
160
|
- lib/log_sense/templates/_summary.txt.erb
|
160
|
-
- lib/log_sense/templates/_total_hits.html.erb
|
161
161
|
- lib/log_sense/templates/apache.html.erb
|
162
|
+
- lib/log_sense/templates/rails.html.erb
|
162
163
|
- lib/log_sense/templates/rails.txt.erb
|
163
164
|
- lib/log_sense/version.rb
|
164
165
|
- log_sense.gemspec
|
@@ -1,32 +0,0 @@
|
|
1
|
-
<table class="table unstriped log-structure">
|
2
|
-
<tbody>
|
3
|
-
<tr>
|
4
|
-
<th>Input file</th>
|
5
|
-
<td><b><%= (data[:log_file] || "stdin") %></b></td>
|
6
|
-
</tr>
|
7
|
-
<tr>
|
8
|
-
<th>Period in Log</th>
|
9
|
-
<td><%= data[:first_day] %> -- <%= data[:last_day] %></td>
|
10
|
-
</tr>
|
11
|
-
<tr>
|
12
|
-
<th>Total days</th>
|
13
|
-
<td><%= data[:total_days] %></td>
|
14
|
-
</tr>
|
15
|
-
<tr>
|
16
|
-
<th>Log size</th>
|
17
|
-
<td><%= data[:log_size] %></td>
|
18
|
-
</tr>
|
19
|
-
<tr>
|
20
|
-
<th>Self poll entries</th>
|
21
|
-
<td><%= data[:selfpolls_size] %></td>
|
22
|
-
</tr>
|
23
|
-
<tr>
|
24
|
-
<th>Crawlers</th>
|
25
|
-
<td><%= data[:crawlers_size] %></td>
|
26
|
-
</tr>
|
27
|
-
<tr>
|
28
|
-
<th>Entries considered</th>
|
29
|
-
<td><%= data[:total_hits] %></td>
|
30
|
-
</tr>
|
31
|
-
</tbody>
|
32
|
-
</table>
|