log_sense 1.5.2 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.org +27 -0
- data/Gemfile.lock +6 -4
- data/README.org +108 -34
- data/Rakefile +6 -6
- data/exe/log_sense +110 -39
- data/ip_locations/dbip-country-lite.sqlite3 +0 -0
- data/lib/log_sense/aggregator.rb +191 -0
- data/lib/log_sense/apache_aggregator.rb +122 -0
- data/lib/log_sense/apache_log_line_parser.rb +23 -21
- data/lib/log_sense/apache_log_parser.rb +15 -12
- data/lib/log_sense/apache_report_shaper.rb +309 -0
- data/lib/log_sense/emitter.rb +55 -553
- data/lib/log_sense/ip_locator.rb +24 -12
- data/lib/log_sense/options_checker.rb +24 -0
- data/lib/log_sense/options_parser.rb +81 -51
- data/lib/log_sense/rails_aggregator.rb +69 -0
- data/lib/log_sense/rails_log_parser.rb +82 -68
- data/lib/log_sense/rails_report_shaper.rb +183 -0
- data/lib/log_sense/report_shaper.rb +105 -0
- data/lib/log_sense/templates/_cdn_links.html.erb +11 -0
- data/lib/log_sense/templates/_command_invocation.html.erb +4 -0
- data/lib/log_sense/templates/_log_structure.html.erb +7 -1
- data/lib/log_sense/templates/_output_table.html.erb +6 -2
- data/lib/log_sense/templates/_rails.css.erb +7 -0
- data/lib/log_sense/templates/_summary.html.erb +9 -7
- data/lib/log_sense/templates/_summary.txt.erb +2 -2
- data/lib/log_sense/templates/{rails.html.erb → report_html.erb} +19 -37
- data/lib/log_sense/templates/{apache.txt.erb → report_txt.erb} +1 -1
- data/lib/log_sense/version.rb +1 -1
- data/lib/log_sense.rb +19 -9
- data/log_sense.gemspec +1 -1
- data/{apache-screenshot.png → screenshots/apache-screenshot.png} +0 -0
- data/screenshots/rails-screenshot.png +0 -0
- metadata +17 -11
- data/lib/log_sense/apache_data_cruncher.rb +0 -147
- data/lib/log_sense/rails_data_cruncher.rb +0 -141
- data/lib/log_sense/templates/apache.html.erb +0 -115
- data/lib/log_sense/templates/rails.txt.erb +0 -22
@@ -0,0 +1,183 @@
|
|
1
|
+
module LogSense
|
2
|
+
class RailsReportShaper < ReportShaper
|
3
|
+
def shape(data)
|
4
|
+
[
|
5
|
+
{
|
6
|
+
title: "Daily Distribution",
|
7
|
+
header: %w[Day DOW Hits],
|
8
|
+
column_alignment: %i[left left right],
|
9
|
+
rows: data[:daily_distribution],
|
10
|
+
vega_spec: {
|
11
|
+
"encoding": {
|
12
|
+
"x": {"field": "Day", "type": "temporal"},
|
13
|
+
"y": {"field": "Hits", "type": "quantitative"}
|
14
|
+
},
|
15
|
+
"layer": [
|
16
|
+
{
|
17
|
+
"mark": {
|
18
|
+
"type": "line",
|
19
|
+
"point": {
|
20
|
+
"filled": false,
|
21
|
+
"fill": "white"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"mark": {
|
27
|
+
"type": "text",
|
28
|
+
"align": "left",
|
29
|
+
"baseline": "middle",
|
30
|
+
"dx": 5
|
31
|
+
},
|
32
|
+
"encoding": {
|
33
|
+
"text": {"field": "Hits", "type": "quantitative"}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
]
|
37
|
+
}
|
38
|
+
},
|
39
|
+
{
|
40
|
+
title: "Time Distribution",
|
41
|
+
header: %w[Hour Hits],
|
42
|
+
column_alignment: %i[left right],
|
43
|
+
rows: data[:time_distribution],
|
44
|
+
vega_spec: {
|
45
|
+
"layer": [
|
46
|
+
{
|
47
|
+
"mark": "bar",
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"mark": {
|
51
|
+
"type": "text",
|
52
|
+
"align": "middle",
|
53
|
+
"baseline": "top",
|
54
|
+
"dx": -10,
|
55
|
+
"yOffset": -15
|
56
|
+
},
|
57
|
+
"encoding": {
|
58
|
+
"text": {"field": "Hits", "type": "quantitative"}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
],
|
62
|
+
"encoding": {
|
63
|
+
"x": {"field": "Hour", "type": "nominal"},
|
64
|
+
"y": {"field": "Hits", "type": "quantitative"}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
},
|
68
|
+
{
|
69
|
+
title: "Statuses",
|
70
|
+
header: %w[Status Count],
|
71
|
+
column_alignment: %i[left right],
|
72
|
+
rows: data[:statuses],
|
73
|
+
vega_spec: {
|
74
|
+
"layer": [
|
75
|
+
{
|
76
|
+
"mark": "bar"
|
77
|
+
},
|
78
|
+
{
|
79
|
+
"mark": {
|
80
|
+
"type": "text",
|
81
|
+
"align": "left",
|
82
|
+
"baseline": "top",
|
83
|
+
"dx": -10,
|
84
|
+
"yOffset": -20
|
85
|
+
},
|
86
|
+
"encoding": {
|
87
|
+
"text": {"field": "Count", "type": "quantitative"}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
],
|
91
|
+
"encoding": {
|
92
|
+
"x": {"field": "Status", "type": "nominal"},
|
93
|
+
"y": {"field": "Count", "type": "quantitative"}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
},
|
97
|
+
{
|
98
|
+
title: "Rails Performance",
|
99
|
+
header: %w[Controller Hits Min Avg Max],
|
100
|
+
column_alignment: %i[left right right right right],
|
101
|
+
rows: data[:performance],
|
102
|
+
vega_spec: {
|
103
|
+
"layer": [
|
104
|
+
{
|
105
|
+
"mark": { "type": "point",
|
106
|
+
"name": "data_points"
|
107
|
+
}
|
108
|
+
},
|
109
|
+
{
|
110
|
+
"mark": { "name": "label",
|
111
|
+
"type": "text",
|
112
|
+
"align": "left",
|
113
|
+
"baseline": "middle",
|
114
|
+
"dx": 5,
|
115
|
+
"yOffset": 0
|
116
|
+
},
|
117
|
+
"encoding": { "text": {"field": "Controller"},
|
118
|
+
"fontSize": {"value": 8}
|
119
|
+
},
|
120
|
+
},
|
121
|
+
],
|
122
|
+
"encoding": { "x": { "field": "Avg",
|
123
|
+
"type": "quantitative"
|
124
|
+
},
|
125
|
+
"y": { "field": "Hits",
|
126
|
+
"type": "quantitative"
|
127
|
+
}
|
128
|
+
},
|
129
|
+
}
|
130
|
+
},
|
131
|
+
{
|
132
|
+
title: "Fatal Events",
|
133
|
+
header: %w[Date IP URL Description Log ID],
|
134
|
+
column_alignment: %i[left left left left left],
|
135
|
+
rows: data[:fatal],
|
136
|
+
col: "small-12 cell"
|
137
|
+
},
|
138
|
+
{
|
139
|
+
title: "Internal Server Errors",
|
140
|
+
header: %w[Date Status IP URL Description Log ID],
|
141
|
+
column_alignment: %i[left left left left left left],
|
142
|
+
rows: data[:internal_server_error],
|
143
|
+
col: "small-12 cell"
|
144
|
+
},
|
145
|
+
{
|
146
|
+
title: "Errors",
|
147
|
+
header: %w[Log ID Context Description Count],
|
148
|
+
column_alignment: %i[left left left left],
|
149
|
+
rows: data[:error],
|
150
|
+
col: "small-12 cell"
|
151
|
+
},
|
152
|
+
{
|
153
|
+
title: "IPs",
|
154
|
+
header: %w[IPs Hits Country],
|
155
|
+
column_alignment: %i[left right left],
|
156
|
+
rows: data[:ips]
|
157
|
+
},
|
158
|
+
{
|
159
|
+
title: "Countries",
|
160
|
+
header: ["Country", "Hits", "IPs", "IP List"],
|
161
|
+
column_alignment: %i[left right left],
|
162
|
+
rows: countries_table(data[:countries])
|
163
|
+
},
|
164
|
+
ip_per_hour_report_spec(ips_per_hour(data[:ips_per_hour])),
|
165
|
+
session_report_spec(ips_detailed(data[:ips_per_day_detailed]))
|
166
|
+
]
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
# { country => [[ip, visit, country], ...]
|
172
|
+
def countries_table(data)
|
173
|
+
data&.map { |k, v|
|
174
|
+
[
|
175
|
+
k,
|
176
|
+
v.map { |x| x[1] }.inject(&:+),
|
177
|
+
v.map { |x| x[0] }.uniq.size,
|
178
|
+
v.map { |x| x[0] }.join(WORDS_SEPARATOR)
|
179
|
+
]
|
180
|
+
}&.sort { |x, y| x[0] <=> y[0] }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module LogSense
|
2
|
+
class ReportShaper
|
3
|
+
WORDS_SEPARATOR = ' · '
|
4
|
+
|
5
|
+
# return { [ip,day] => { [ hits, list of urls ] } }
|
6
|
+
def ips_detailed(ips_per_day)
|
7
|
+
hash = pivot(ips_per_day, 0, 1, lambda { |array| array.map { |x| x[2] } })
|
8
|
+
array = []
|
9
|
+
hash.keys.map do |ip|
|
10
|
+
array += hash[ip].keys.map do |date|
|
11
|
+
[
|
12
|
+
ip,
|
13
|
+
hash[ip].keys.size,
|
14
|
+
date,
|
15
|
+
hash[ip][date].size,
|
16
|
+
hash[ip][date].uniq.size,
|
17
|
+
hash[ip][date].uniq.size < 100 ? hash[ip][date].uniq.join(WORDS_SEPARATOR) : "[too many]"
|
18
|
+
]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
array
|
22
|
+
end
|
23
|
+
|
24
|
+
def ips_per_hour(ips_per_hour)
|
25
|
+
hash = pivot(ips_per_hour, 0, 1)
|
26
|
+
hash.keys.map do |ip|
|
27
|
+
[
|
28
|
+
ip,
|
29
|
+
(0..23).map { |hour| hash[ip][hour.to_s]&.to_i }
|
30
|
+
].flatten
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Shape an array of arrays into a hash of hashes (row, cols)
|
35
|
+
# Params:
|
36
|
+
# +input_data+:: array of array
|
37
|
+
# +row_key+:: index of the inner array or lambda, used to group data
|
38
|
+
# by rows
|
39
|
+
# +col_key+:: index of the inner array or lambda, will be used
|
40
|
+
# to group cols
|
41
|
+
# +cell+:: lambda to get the value of the cells to put in the hashes.
|
42
|
+
# Takes and array as input (that is, an array of all the
|
43
|
+
# elements resulting from grouping)
|
44
|
+
#
|
45
|
+
# Example
|
46
|
+
#
|
47
|
+
# input_array: [[IP, HOUR, VISITS], [...]],
|
48
|
+
# row_key: 0
|
49
|
+
# col_key: 1
|
50
|
+
# cell: lambda { |x| x[2] }
|
51
|
+
#
|
52
|
+
# Will output:
|
53
|
+
#
|
54
|
+
# { IP => { HOUR => VISITS, HOUR => VISITS }, ... }
|
55
|
+
#
|
56
|
+
def pivot(input_data,
|
57
|
+
row_key,
|
58
|
+
col_key,
|
59
|
+
cell_maker = lambda { |x| x[0].last })
|
60
|
+
# here we build:
|
61
|
+
# "95.108.213.66"=>{12=>1, 18=>2, 19=>1, 20=>1, 5=>3, 6=>2, 7=>2, 3=>1},
|
62
|
+
#
|
63
|
+
# first transform: IP => [ HOUR => [[IP,HOUR,T], [IP,HOUR,T]] ]
|
64
|
+
# second transform: [IP,HOUR,T] -> T
|
65
|
+
input_data.group_by { |entry|
|
66
|
+
if row_key.class == Integer
|
67
|
+
entry[row_key]
|
68
|
+
else
|
69
|
+
row_key.call(entry)
|
70
|
+
end
|
71
|
+
}.transform_values { |rows|
|
72
|
+
rows.group_by { |cols|
|
73
|
+
if col_key.class == Integer
|
74
|
+
cols[col_key]
|
75
|
+
else
|
76
|
+
col_key.call(cols)
|
77
|
+
end
|
78
|
+
}.transform_values { |array|
|
79
|
+
cell_maker.call(array)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def session_report_spec(data)
|
85
|
+
{
|
86
|
+
title: "Sessions",
|
87
|
+
report: :html,
|
88
|
+
header: ["IP", "Days", "Date", "Visits", "Distinct URL", "URL List"],
|
89
|
+
column_alignment: %i[left left right right right right],
|
90
|
+
rows: data,
|
91
|
+
col: "small-12 cell"
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def ip_per_hour_report_spec(data)
|
96
|
+
{
|
97
|
+
title: "IP per hour",
|
98
|
+
header: ["IP"] + (0..23).map { |hour| hour.to_s },
|
99
|
+
column_alignment: [:left] + [:right] * 24,
|
100
|
+
rows: data,
|
101
|
+
col: "small-12 cell"
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
2
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
3
|
+
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@300;700&display=swap" rel="stylesheet">
|
4
|
+
|
5
|
+
<% LogSense::Emitter::CDN_CSS.each do |link| %>
|
6
|
+
<link rel="stylesheet" type="text/css" href="<%= link %>">
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% LogSense::Emitter::CDN_JS.each do |link| %>
|
10
|
+
<script type="text/javascript" src="<%= link %>"></script>
|
11
|
+
<% end %>
|
@@ -11,17 +11,23 @@
|
|
11
11
|
<%= data[:total_days] %>
|
12
12
|
<span class="stats-list-label">Days in Log</span>
|
13
13
|
</li>
|
14
|
+
<% if data[:log_size] %>
|
14
15
|
<li class="stats-list-negative">
|
15
16
|
<%= data[:log_size] %>
|
16
17
|
<span class="stats-list-label">Total Entries</span>
|
17
18
|
</li>
|
19
|
+
<% end %>
|
20
|
+
<% if data[:selfpolls_size] %>
|
18
21
|
<li class="stats-list-negative">
|
19
22
|
<%= data[:selfpolls_size] %>
|
20
23
|
<span class="stats-list-label">Self Polls</span>
|
21
24
|
</li>
|
22
|
-
|
25
|
+
<% end %>
|
26
|
+
<% if data[:crawlers] %>
|
27
|
+
<li class="stats-list-negative">
|
23
28
|
<td><%= data[:crawlers_size] %></td>
|
24
29
|
<span class="stats-list-label">Crawlers</span>
|
30
|
+
<% end %>
|
25
31
|
</li>
|
26
32
|
</ul>
|
27
33
|
|
@@ -54,7 +54,7 @@
|
|
54
54
|
data: 'IP',
|
55
55
|
className: '<%= Emitter::slugify("IP") %>',
|
56
56
|
render: function(data, type, row) {
|
57
|
-
// If display or filter data is requested, format the
|
57
|
+
// If display or filter data is requested, format the data
|
58
58
|
if ( type === 'display' || type === 'filter' ) {
|
59
59
|
return "<a target=\"_blank\" href=\"https://db-ip.com/" + data + "\">" + data + "</a>";
|
60
60
|
}
|
@@ -63,7 +63,11 @@
|
|
63
63
|
}
|
64
64
|
},
|
65
65
|
<% else -%>
|
66
|
-
{
|
66
|
+
{
|
67
|
+
data: '<%= header %>',
|
68
|
+
className: '<%= Emitter::slugify(header) %>',
|
69
|
+
render: DataTable.render.text()
|
70
|
+
},
|
67
71
|
<% end -%>
|
68
72
|
<% end -%>
|
69
73
|
]
|
@@ -11,12 +11,14 @@
|
|
11
11
|
<%= data[:total_days_in_analysis] %>
|
12
12
|
<span class="stats-list-label">Days</span>
|
13
13
|
</li>
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
<% if data[:total_size] %>
|
15
|
+
<li class="stats-list-positive">
|
16
|
+
<%= data[:total_size] %>
|
17
|
+
<span class="stats-list-label">Data Transferred</span>
|
18
|
+
</li>
|
19
|
+
<% end %>
|
18
20
|
<li class="stats-list-negative">
|
19
|
-
<%= data[:
|
21
|
+
<%= data[:events] %>
|
20
22
|
<span class="stats-list-label">Hits</span>
|
21
23
|
</li>
|
22
24
|
<li class="stats-list-negative">
|
@@ -24,12 +26,12 @@
|
|
24
26
|
<span class="stats-list-label">Unique Visits</span>
|
25
27
|
</li>
|
26
28
|
<li class="stats-list-negative">
|
27
|
-
<% days = data[:
|
29
|
+
<% days = data[:total_days_in_analysis] %>
|
28
30
|
<%= days > 0 ? "%d" % (data[:total_unique_visits] / days) : "N/A" %>
|
29
31
|
<span class="stats-list-label">Unique Visits / Day</span>
|
30
32
|
</li>
|
31
33
|
<li class="stats-list-negative">
|
32
|
-
<%= data[:total_unique_visits] != 0 ? data[:
|
34
|
+
<%= data[:total_unique_visits] != 0 ? data[:events] / data[:total_unique_visits] : "N/A" %>
|
33
35
|
<span class="stats-list-label">Hits / Unique Visitor</span>
|
34
36
|
</li>
|
35
37
|
</ul>
|
@@ -3,10 +3,10 @@ table = Terminal::Table.new rows: [
|
|
3
3
|
["From", data[:first_day_in_analysis]],
|
4
4
|
["To", data[:last_day_in_analysis]],
|
5
5
|
["Days", data[:total_days_in_analysis]],
|
6
|
-
["Hits", data[:
|
6
|
+
["Hits", data[:events]],
|
7
7
|
["Unique Visits", data[:total_unique_visits]],
|
8
8
|
["Unique Visits / Day", data[:total_days_in_analysis] > 0 ? "%d" % (data[:total_unique_visits] / data[:total_days_in_analysis]) : "N/A"],
|
9
|
-
["Hits/Unique Visitor", data[:total_unique_visits] != 0 ? data[:
|
9
|
+
["Hits/Unique Visitor", data[:total_unique_visits] != 0 ? data[:events] / data[:total_unique_visits] : "N/A"]
|
10
10
|
]
|
11
11
|
table.style = { border_i: "|" }
|
12
12
|
table
|
@@ -1,42 +1,22 @@
|
|
1
1
|
<!doctype html>
|
2
2
|
<html class="no-js" lang="en">
|
3
3
|
<head>
|
4
|
-
<title>
|
5
|
-
<%= options[:title] || "Log Sense: #{data[:filenames].empty? ? "stdin" : data[:filenames].join(", ")}" %>
|
6
|
-
</title>
|
4
|
+
<title><%= @report_title %></title>
|
7
5
|
|
8
6
|
<meta charset="utf-8" />
|
9
7
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
10
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
11
9
|
|
12
10
|
<meta name="author" content="Shair.Tech">
|
13
|
-
<meta name="description"
|
11
|
+
<meta name="description"
|
12
|
+
content="Analysis of <%= @data[:filenames].join(', ') %>">
|
14
13
|
|
15
|
-
|
16
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
17
|
-
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@300;700&display=swap" rel="stylesheet">
|
18
|
-
|
19
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.min.css">
|
20
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.4/dist/css/foundation.min.css">
|
21
|
-
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/zf/dt-1.11.3/datatables.min.css"/>
|
22
|
-
|
23
|
-
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
24
|
-
<script type="text/javascript" src="https://cdn.datatables.net/v/zf/dt-1.11.3/datatables.min.js"></script>
|
25
|
-
|
26
|
-
<script src="https://cdn.jsdelivr.net/npm/vega@5.21.0"></script>
|
27
|
-
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5.2.0"></script>
|
28
|
-
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6.20.2"></script>
|
14
|
+
<%= render "cdn_links.html.erb" %>
|
29
15
|
|
30
16
|
<style>
|
31
17
|
<%= render "stylesheet.css" %>
|
32
|
-
|
33
|
-
|
34
|
-
#offCanvas {
|
35
|
-
background: #d30001 !important;
|
36
|
-
}
|
37
|
-
h2 {
|
38
|
-
background: #d30001 !important;
|
39
|
-
}
|
18
|
+
|
19
|
+
<%= render @format_specific_css %>
|
40
20
|
</style>
|
41
21
|
</head>
|
42
22
|
|
@@ -44,7 +24,7 @@
|
|
44
24
|
<div class="off-canvas-wrapper">
|
45
25
|
<div class="off-canvas position-left" id="offCanvas" data-off-canvas>
|
46
26
|
<%= render "navigation.html.erb",
|
47
|
-
menus:
|
27
|
+
menus: @reports.map { |x| x[:title] } %>
|
48
28
|
</div>
|
49
29
|
<div class="off-canvas-content" data-off-canvas-content>
|
50
30
|
<button id="toggle-button" type="button" data-toggle="offCanvas">
|
@@ -52,24 +32,29 @@
|
|
52
32
|
</button>
|
53
33
|
|
54
34
|
<section class="main-section grid-container fluid">
|
55
|
-
<h1><%= options[:title] || "Log Sense
|
35
|
+
<h1><%= options[:title] || "Log Sense #{@report_title} Log Report" %></h1>
|
56
36
|
|
57
|
-
<p
|
37
|
+
<p>
|
38
|
+
<b>Input File(s):</b>
|
39
|
+
<%= @data[:filenames].empty? ? "stdin" : @data[:filenames].join(", ") %>
|
40
|
+
</p>
|
58
41
|
|
59
42
|
<div class="grid-x grid-padding-x">
|
60
43
|
<article class="small-12 large-6 cell">
|
61
44
|
<h2 id="<%= Emitter::slugify "Summary" %>">Summary</h2>
|
62
|
-
<%= render "summary.html.erb", data: data %>
|
45
|
+
<%= render "summary.html.erb", data: @data %>
|
63
46
|
</article>
|
64
47
|
|
65
48
|
<article class="small-12 large-6 cell">
|
66
49
|
<h2 id="<%= Emitter::slugify "Summary" %>">Log Structure</h2>
|
67
|
-
<%= render "log_structure.html.erb", data: data %>
|
50
|
+
<%= render "log_structure.html.erb", data: @data %>
|
68
51
|
</article>
|
69
52
|
|
70
53
|
<% @reports.each_with_index do |report, index| %>
|
71
54
|
<article class="cell <%= report[:col] || "small-12 large-6" %>" >
|
72
|
-
<h2 id="<%= Emitter::slugify report[:title] %>"
|
55
|
+
<h2 id="<%= Emitter::slugify report[:title] %>">
|
56
|
+
<%= report[:title] %>
|
57
|
+
</h2>
|
73
58
|
|
74
59
|
<%= render "report_data.html.erb", report: report, index: index %>
|
75
60
|
<% if report[:vega_spec] %>
|
@@ -95,21 +80,18 @@
|
|
95
80
|
|
96
81
|
<article class="small-12 large-6 cell">
|
97
82
|
<h2 id="<%= Emitter::slugify "Command Invocation" %>">Command Invocation</h2>
|
98
|
-
<%= render "command_invocation.html.erb", data: data, options: options %>
|
83
|
+
<%= render "command_invocation.html.erb", data: @data, options: options %>
|
99
84
|
</article>
|
100
85
|
|
101
86
|
<article class="small-12 large-6 cell">
|
102
87
|
<h2 id="<%= Emitter::slugify "Performance" %>">Performance</h2>
|
103
|
-
<%= render "performance.html.erb", data: data %>
|
88
|
+
<%= render "performance.html.erb", data: @data %>
|
104
89
|
</article>
|
105
90
|
</div>
|
106
91
|
</section>
|
107
92
|
</div>
|
108
93
|
</div>
|
109
94
|
|
110
|
-
<script type="text/javascript" src="js/vendor/what-input.js"></script>
|
111
|
-
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
|
112
|
-
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.4/dist/js/foundation.min.js" crossorigin="anonymous"></script>
|
113
95
|
<script>
|
114
96
|
$(document).foundation();
|
115
97
|
|
data/lib/log_sense/version.rb
CHANGED
data/lib/log_sense.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
|
6
|
-
require
|
7
|
-
require
|
8
|
-
|
9
|
-
require
|
1
|
+
require "log_sense/version"
|
2
|
+
|
3
|
+
require "log_sense/options_parser"
|
4
|
+
require "log_sense/options_checker"
|
5
|
+
|
6
|
+
require "log_sense/apache_log_parser"
|
7
|
+
require "log_sense/rails_log_parser"
|
8
|
+
|
9
|
+
require "log_sense/aggregator"
|
10
|
+
require "log_sense/apache_aggregator"
|
11
|
+
require "log_sense/rails_aggregator"
|
12
|
+
|
13
|
+
require "log_sense/ip_locator"
|
14
|
+
|
15
|
+
require "log_sense/report_shaper"
|
16
|
+
require "log_sense/apache_report_shaper"
|
17
|
+
require "log_sense/rails_report_shaper"
|
18
|
+
|
19
|
+
require "log_sense/emitter"
|
data/log_sense.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
|
9
9
|
spec.summary = %q{Generate analytics for Apache and Rails log file.}
|
10
10
|
spec.description = %q{Generate analytics in HTML, txt, and SQLite format for Apache and Rails log files.}
|
11
|
-
spec.homepage = "https://github.com/shair-tech/log_sense/
|
11
|
+
spec.homepage = "https://github.com/shair-tech/log_sense/"
|
12
12
|
spec.license = "MIT"
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.9")
|
14
14
|
|
File without changes
|
Binary file
|