apache_log_report 1.1.2 → 1.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07ad311b79b7ad4888250d690af4857cc620b07a4fdc7206bbc40adf5b2fd00b
4
- data.tar.gz: 1ed81f7bd6324af49a24ad6d8abe9add71710813c051537f254f80d9c9ac6739
3
+ metadata.gz: 742584032338664834cd5c1b669289980e083e68d172827f6517ce040543aa4d
4
+ data.tar.gz: 1bf08e255feb434ded62589d5c70ea5a6eb83dc1f6a69e60a31cb520eea6b48f
5
5
  SHA512:
6
- metadata.gz: db323468d20cb50f870ac0dbe62cbfd42feb10e69da02d9d892dd206bcf9e5d1c3c5ad91a542f4f888bc04a9a6df3514ba186d67cc60b32e7647df6ff183e5d5
7
- data.tar.gz: cf33e4665e31a6f18fc346c80b6f8b7cae8456b0c9dbf2d8c658a383b3711e754f795d08963d5c3c5109bd34360c5bc00bb17c93b15e4c551a7a9a1b5f619023
6
+ metadata.gz: 955dbe90321c68f5694aaa892cae97926172ca47b684a0eee1b9f7644dc26a13f853b3b3d20e35cf06872b29db0c06bc16c4c86e69c740ea86fe8768ae92b2a1
7
+ data.tar.gz: e6d9ebc88435442bfb77faa3cb2eccb94a355e9ca7af44548a7b443531c9fae923e41f5d97201044f71414f2d9894162b593cd15170e255030ab49bd9992e3f0
data/README.org CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  * Introduction
6
6
 
7
+ ApacheLogReport is an Apache log analyzer.
8
+
7
9
  * Installation
8
10
 
9
11
  * Usage
@@ -14,8 +16,12 @@ See the [[file:CHANGELOG.org][CHANGELOG]] file.
14
16
 
15
17
  * Todo
16
18
 
19
+ ** TODO Referers should only include the hostname?
17
20
  ** TODO Graphs in HTML output
18
21
  ** TODO Countries
22
+ ** TODO Light and Dark Theme
23
+ ** TODO Embed CSS
24
+ ** TODO Declare datatypes in table outputs, so that we can format data
19
25
 
20
26
  * Compatibility
21
27
 
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Adolfo Villafiorita"]
7
7
  spec.email = ["adolfo.villafiorita@ict4g.net"]
8
8
 
9
- spec.summary = %q{Generate a request report in OrgMode format from an Apache log file.}
10
- spec.description = %q{Generate a request report in OrgMode format from an Apache log file.}
9
+ spec.summary = %q{Generate analytics from an Apache log file.}
10
+ spec.description = %q{Generate requests reports in HTML, OrgMode, and SQLite format from an Apache log file.}
11
11
  spec.homepage = "https://www.ict4g.net/gitea/adolfo/apache_log_report"
12
12
  spec.license = "MIT"
13
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
@@ -1,17 +1,41 @@
1
+
1
2
  module ApacheLogReport
2
3
  module DataCruncher
3
4
 
4
5
  #
5
6
  # take a sqlite3 database and analyze data
6
7
  #
8
+ # @ variables are automatically put in the returned data
9
+ #
7
10
 
8
11
  def self.crunch db, options = {}
9
- @first_day = db.execute "SELECT datetime from LogLine order by datetime limit 1"
10
- @last_day = db.execute "SELECT datetime from LogLine order by datetime desc limit 1"
12
+ first_day_s = db.execute "SELECT datetime from LogLine order by datetime limit 1"
13
+ last_day_s = db.execute "SELECT datetime from LogLine order by datetime desc limit 1"
14
+
15
+ # make first and last day into dates or nil
16
+ @first_day = first_day_s.empty? ? nil : Date.parse(first_day_s[0][0])
17
+ @last_day = last_day_s.empty? ? nil : Date.parse(last_day_s[0][0])
18
+
19
+ @total_days = 0
20
+ if @first_day and @last_day
21
+ @total_days = (@last_day - @first_day).to_i
22
+ end
23
+
11
24
  @log_size = db.execute "SELECT count(datetime) from LogLine"
12
25
  @crawlers_size = db.execute "SELECT count(datetime) from LogLine where bot == 1"
13
26
  @selfpolls_size = db.execute "SELECT count(datetime) from LogLine where ip == '::1'"
14
27
 
28
+ @first_day_requested = options[:from_date]
29
+ @last_day_requested = options[:to_date]
30
+
31
+ @first_day_in_analysis = date_intersect options[:from_date], @first_day, :max
32
+ @last_day_in_analysis = date_intersect options[:to_date], @last_day, :min
33
+
34
+ @total_days_in_analysis = 0
35
+ if @first_day_in_analysis and @last_day_in_analysis
36
+ @total_days_in_analysis = (@last_day_in_analysis - @first_day_in_analysis).to_i
37
+ end
38
+
15
39
  #
16
40
  # generate the where clause corresponding to the command line options to filter data
17
41
  #
@@ -39,12 +63,23 @@ module ApacheLogReport
39
63
  END AS size
40
64
  EOS
41
65
 
66
+ human_readable_day = <<-EOS
67
+ case cast (strftime('%w', datetime) as integer)
68
+ when 0 then 'Sunday'
69
+ when 1 then 'Monday'
70
+ when 2 then 'Tuesday'
71
+ when 3 then 'Wednesday'
72
+ when 4 then 'Thursday'
73
+ when 5 then 'Friday'
74
+ else 'Saturday'
75
+ end as dow
76
+ EOS
77
+
42
78
  @total_hits = db.execute "SELECT count(datetime) from LogLine where #{filter}"
43
79
  @total_unique_visitors = db.execute "SELECT count(distinct(unique_visitor)) from LogLine where #{filter}"
44
80
  @total_size = db.execute "SELECT #{human_readable_size} from LogLine where #{filter}"
45
- @total_days = (Date.parse(@last_day[0][0]) - Date.parse(@first_day[0][0])).to_i
46
81
 
47
- @daily_distribution = db.execute "SELECT date(datetime), count(datetime), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by date(datetime)"
82
+ @daily_distribution = db.execute "SELECT date(datetime), #{human_readable_day}, count(datetime), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by date(datetime)"
48
83
  @time_distribution = db.execute "SELECT strftime('%H', datetime), count(datetime), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by strftime('%H', datetime)"
49
84
  @most_requested_pages = db.execute "SELECT path, count(path), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where extension == '.html' and #{filter} group by path order by count(path) desc limit #{options[:limit]}"
50
85
  @most_requested_resources = db.execute "SELECT path, count(path), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by path order by count(path) desc limit #{options[:limit]}"
@@ -80,7 +115,20 @@ module ApacheLogReport
80
115
  end
81
116
  data
82
117
  end
83
- end
84
118
 
119
+ private
120
+
121
+ def self.date_intersect date1, date2, method
122
+ if date1 and date2
123
+ [date1, date2].send(method)
124
+ elsif date1
125
+ date1
126
+ else
127
+ date2
128
+ end
129
+ end
130
+
131
+
132
+ end
85
133
  end
86
134
 
@@ -18,11 +18,11 @@ module ApacheLogReport
18
18
  args[:limit] = n
19
19
  end
20
20
 
21
- opts.on("-bDATE", "--begin=DATE", DateTime, "Consider entries after or on DATE") do |n|
21
+ opts.on("-bDATE", "--begin=DATE", Date, "Consider entries after or on DATE") do |n|
22
22
  args[:from_date] = n
23
23
  end
24
24
 
25
- opts.on("-eDATE", "--end=DATE", DateTime, "Consider entries before or on DATE") do |n|
25
+ opts.on("-eDATE", "--end=DATE", Date, "Consider entries before or on DATE") do |n|
26
26
  args[:to_date] = n
27
27
  end
28
28
 
@@ -4,7 +4,7 @@ def slugify string
4
4
  end
5
5
  %>
6
6
 
7
- <table id="<%= slugify(title || "") %>" class="<%= slugify(title || "") %>">
7
+ <table id="<%= slugify(title || "") %>" class="table <%= slugify(title || "") %>">
8
8
  <thead>
9
9
  <tr>
10
10
  <% header.each do |heading| %>
@@ -4,194 +4,271 @@
4
4
  <meta name="author" content="apache_log_report">
5
5
 
6
6
  <link rel="stylesheet" href="alr-styles.css"></style>
7
+
8
+ <link rel="stylesheet" href="https://unpkg.com/spectre.css/dist/spectre.min.css">
9
+ <link rel="stylesheet" href="https://unpkg.com/spectre.css/dist/spectre-exp.min.css">
10
+ <link rel="stylesheet" href="https://unpkg.com/spectre.css/dist/spectre-icons.min.css">
7
11
  </head>
8
12
 
9
13
  <body>
10
- <section>
11
- <h1>Apache Log Analysis: <%= data[:log_file] || "stdin" %></h1>
12
-
13
- <article>
14
- <h2>Summary</h2>
15
-
16
- <table class="pure-table summary">
17
- <tr>
18
- <th class="hits">Hits</th>
19
- <td class="hits"><%= data[:total_hits][0][0] %></td>
20
- </tr>
21
- <tr>
22
- <th class="unique-visitors">Unique Visitors</th>
23
- <td class="unique-visitors"><%= data[:total_unique_visitors][0][0] %></td>
24
- </tr>
25
- <tr>
26
- <th class="tx">Tx</th>
27
- <td class="tx"><%= data[:total_size][0][0] %></td>
28
- </tr>
29
- <tr>
30
- <th class="period">Period</th>
31
- <td class="period">
32
- <%= data[:first_day][0][0] %>
33
- --
34
- <%= data[:last_day][0][0] %>
35
- </td>
36
- </tr>
37
- <tr>
38
- <th class="days">Days </th>
39
- <td class="days"><%= data[:total_days] %></td>
40
- </tr>
41
- </table>
42
- </article>
43
-
44
- <% @reports = [
45
- { title: "Daily Distribution", header: ["Day", "Hits", "Visits", "Size"], rows: data[:daily_distribution] },
46
- { title: "Time Distribution", header: ["Hour", "Hits", "Visits", "Size"], rows: data[:time_distribution] },
47
- { title: "Most Requested Pages", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_pages] },
48
- { title: "Most Requested Resources", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_resources] },
49
- { title: "404 on HTML Files", header: ["Path", "Hits", "Visitors"], rows: data[:missed_pages] },
50
- { title: "404 on other Resources", header: ["Path", "Hits", "Visitors"], rows: data[:missed_resources] },
51
- { title: "Attacks", header: ["Path", "Hits", "Visitors"], rows: data[:attacks] },
52
- { title: "Statuses", header: ["Status", "Count"], rows: data[:statuses] },
53
- { title: "Daily Statuses", header: ["Status", "2xx", "3xx", "4xx"], rows: data[:statuses_by_day] },
54
- { title: "Browsers", header: ["Browser", "Hits", "Visitors", "Size"], rows: data[:browsers] },
55
- { title: "Platforms", header: ["Platform", "Hits", "Visitors", "Size"], rows: data[:platforms] },
56
- { title: "IPs", header: ["IPs", "Hits", "Visitors", "Size"], rows: data[:ips] },
57
- { title: "Referers", header: ["Referers", "Hits", "Visitors", "Size"], rows: data[:referers] },
58
- ]
59
- %>
60
- <% @reports.each do |report| %>
61
- <article>
62
- <h2><%= report[:title] %></h2>
63
- <%= render "output_table", report %>
64
- </article>
65
- <% end %>
66
-
67
- <article>
68
- <h2>Streaks</h2>
69
-
70
- <table class="streaks">
71
- <thead>
72
- <tr>
73
- <th>IP</th>
74
- <th>Day</th>
75
- <th>URL</th>
76
- </tr>
77
- </thead>
78
- <tbody>
79
- <% data[:streaks].group_by(&:first).each do |ip, date_urls| %>
14
+ <div class="container">
15
+ <nav>
16
+ <ul class="nav">
17
+ <li class="nav-item active">
18
+ <a href="#">Navigation</a>
19
+ <ul class="nav">
20
+ <% [ "Summary",
21
+ "Log Structure",
22
+ "Daily Distribution",
23
+ "Time Distribution",
24
+ "Most Requested Pages",
25
+ "Most Requested Resources",
26
+ "404 on HTML Files",
27
+ "404 on other Resources",
28
+ "Attacks",
29
+ "Statuses",
30
+ "Daily Statuses",
31
+ "Browsers",
32
+ "Platforms",
33
+ "Referers",
34
+ "IPs",
35
+ "Command Invocation",
36
+ "Performance"
37
+ ].each do |item| %>
38
+ <li class="nav-item">
39
+ <a href="#<%= item.downcase.gsub(' ', '-') %>"><%= item %></a>
40
+ </li>
41
+ <% end %>
42
+ </ul>
43
+ </li>
44
+ </ul>
45
+ <p>
46
+ Generated by<br />
47
+ <a href="https://www.ict4g.net/gitea/adolfo/apache_log_report">
48
+ Apache Log Report
49
+ </a> <br />
50
+ on <%= DateTime.now.strftime("%Y-%m-%d %H:%M") %>.<br />
51
+ The lean log analyzer.
52
+ </p>
53
+ </nav>
54
+
55
+ <section>
56
+ <h1>Apache Log Analysis: <%= data[:log_file] || "stdin" %></h1>
57
+
58
+ <div class="columns">
59
+ <article class="col-6 column">
60
+ <h2 id="summary">Summary</h2>
61
+
62
+ <table class="table summary">
80
63
  <tr>
81
- <td class="ip"><%= ip %></td>
82
- <td class="streaks">
83
- <% date_urls.group_by(&:first).each do |date, urls| %>
84
- <% urls.each do |url| %>
85
- <b><%= url[1] %>:</b> <%= url[2] %> <br />
86
- <% end %>
87
- <% end %>
64
+ <th>Input file</th>
65
+ <td><b><%= (data[:log_file] || "stdin") %></b></td>
66
+ </tr>
67
+ <tr>
68
+ <th class="period">Period Analyzed</th>
69
+ <td class="period">
70
+ <%= data[:first_day_in_analysis] %>
71
+ --
72
+ <%= data[:last_day_in_analysis] %>
88
73
  </td>
89
74
  </tr>
90
- <% end %>
91
- </tbody>
92
- </table>
93
- </article>
94
-
95
- <article>
96
- <h2>Command Invocation and Performance</h2>
97
-
98
- <h3>Command Invocation</h3>
99
-
100
- <code>
101
- </code>
102
-
103
- <table class="pure-table command-invocation">
104
- <tbody>
105
- <tr>
106
- <th>CLI Command</th>
107
- <td><pre><%= data[:command] %></pre></td>
108
- </tr>
109
- <tr>
110
- <th>Input file</th>
111
- <td><code><%= (data[:log_file] || "stdin") %></code></td>
112
- </tr>
113
- <tr>
114
- <th>Ignore crawlers</th>
115
- <td><code><%= options[:ignore_crawlers] %></code></td></tr>
116
- <tr>
117
- <th>Only crawlers</th>
118
- <td><code><%= options[:only_crawlers] %></code></td>
119
- </tr>
120
- <tr>
121
- <th>No selfpoll</th>
122
- <td><code><%= options[:no_selfpoll] %></code></td>
123
- </tr>
124
- <tr>
125
- <th>Filter by date</th>
126
- <td>
127
- <code><%= (options[:from_date] != nil or options[:to_date] != nil) %></code>
128
- </td>
129
- </tr>
130
- <tr>
131
- <th>Prefix</th>
132
- <td><code><%= @prefix %></code></td>
133
- </tr>
134
- <tr>
135
- <th>Suffix</th>
136
- <td><code><%= @suffix %></code></td>
137
- </tr>
138
- </tbody>
139
- </table>
140
-
141
- <h3> Log Structure</h3>
142
-
143
- <table class="pure-table log-structure">
144
- <tbody>
145
- <tr>
146
- <th>Log size</th>
147
- <td><%= data[:log_size][0][0] %></td>
148
- </tr>
149
- <tr>
150
- <th>Self poll entries</th>
151
- <td><%= data[:selfpolls_size][0][0] %></td>
152
- </tr>
153
- <tr>
154
- <th>Crawlers</th>
155
- <td><%= data[:crawlers_size][0][0] %></td>
156
- </tr>
157
- <tr>
158
- <th>Entries considered</th>
159
- <td><%= data[:total_hits][0][0] %></td>
160
- </tr>
161
- </tbody>
162
- </table>
163
-
164
- <h3> Performance</h3>
165
-
166
- <table class="pure-table performance">
167
- <tbody>
168
- <tr>
169
- <th>Analysis started at</th>
170
- <td><%= data[:started_at].to_s %></td>
171
- </tr>
172
- <tr>
173
- <th>Analysis ended at</th>
174
- <td><%= data[:ended_at].to_s %></td>
175
- </tr>
176
- <tr>
177
- <th>Duration (sec)</th>
178
- <td><%= "%.1f" % data[:duration] %></td>
179
- </tr>
180
- <tr>
181
- <th>Duration (min)</th>
182
- <td><%= "%d" % (data[:duration] / 60 ) %></td>
183
- </tr>
184
- <tr>
185
- <th>Log size</th>
186
- <td><%= data[:log_size][0][0] %></td>
187
- </tr>
188
- <tr>
189
- <th>Lines/sec</th>
190
- <td><%= "%.2f" % (data[:log_size][0][0] / data[:duration]) %></td></tr>
191
- </tbody>
192
- </table>
193
- </article>
194
- </section>
75
+ <tr>
76
+ <th class="days">Days </th>
77
+ <td class="days"><%= data[:total_days_in_analysis] %></td>
78
+ </tr>
79
+ <tr>
80
+ <th class="hits">Hits</th>
81
+ <td class="hits"><%= data[:total_hits][0][0] %></td>
82
+ </tr>
83
+ <tr>
84
+ <th class="unique-visitors">Unique Visitors</th>
85
+ <td class="unique-visitors"><%= data[:total_unique_visitors][0][0] %></td>
86
+ </tr>
87
+ <tr>
88
+ <th class="tx">Tx</th>
89
+ <td class="tx"><%= data[:total_size][0][0] %></td>
90
+ </tr>
91
+ </table>
92
+ </article>
93
+ <article class="column col-6">
94
+ <h2 id="log-structure">Log Structure</h2>
95
+
96
+ <table class="table log-structure">
97
+ <tbody>
98
+ <tr>
99
+ <th>Input file</th>
100
+ <td><b><%= (data[:log_file] || "stdin") %></b></td>
101
+ </tr>
102
+ <tr>
103
+ <th>Period in Log</th>
104
+ <td><%= data[:first_day] %> -- <%= data[:last_day] %></td>
105
+ </tr>
106
+ <tr>
107
+ <th>Total days</th>
108
+ <td><%= data[:total_days] %></td>
109
+ </tr>
110
+ <tr>
111
+ <th>Log size</th>
112
+ <td><%= data[:log_size][0][0] %></td>
113
+ </tr>
114
+ <tr>
115
+ <th>Self poll entries</th>
116
+ <td><%= data[:selfpolls_size][0][0] %></td>
117
+ </tr>
118
+ <tr>
119
+ <th>Crawlers</th>
120
+ <td><%= data[:crawlers_size][0][0] %></td>
121
+ </tr>
122
+ <tr>
123
+ <th>Entries considered</th>
124
+ <td><%= data[:total_hits][0][0] %></td>
125
+ </tr>
126
+ </tbody>
127
+ </table>
128
+ </article>
129
+ </div>
130
+
131
+ <% @reports = [
132
+ { title: "Daily Distribution", header: ["Day", "DOW", "Hits", "Visits", "Size"], rows: data[:daily_distribution] },
133
+ { title: "Time Distribution", header: ["Hour", "Hits", "Visits", "Size"], rows: data[:time_distribution] },
134
+ { title: "Most Requested Pages", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_pages] },
135
+ { title: "Most Requested Resources", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_resources] },
136
+ { title: "404 on HTML Files", header: ["Path", "Hits", "Visitors"], rows: data[:missed_pages] },
137
+ { title: "404 on other Resources", header: ["Path", "Hits", "Visitors"], rows: data[:missed_resources] },
138
+ { title: "Attacks", header: ["Path", "Hits", "Visitors"], rows: data[:attacks] },
139
+ { },
140
+ { title: "Statuses", header: ["Status", "Count"], rows: data[:statuses] },
141
+ { title: "Daily Statuses", header: ["Status", "2xx", "3xx", "4xx"], rows: data[:statuses_by_day] },
142
+ { title: "Browsers", header: ["Browser", "Hits", "Visitors", "Size"], rows: data[:browsers] },
143
+ { title: "Platforms", header: ["Platform", "Hits", "Visitors", "Size"], rows: data[:platforms] },
144
+ { title: "Referers", header: ["Referers", "Hits", "Visitors", "Size"], rows: data[:referers], col: "col-12" },
145
+ { title: "IPs", header: ["IPs", "Hits", "Visitors", "Size"], rows: data[:ips] },
146
+ { },
147
+ ]
148
+ %>
149
+ <div class="columns">
150
+ <% @reports.each do |report| %>
151
+ <div class="column <%= report[:col] || "col-6" %>">
152
+ <article>
153
+ <% if report[:title] != nil %>
154
+ <h2 id="<%= report[:title].downcase.gsub(/ +/, '-') %>">
155
+ <%= report[:title] %>
156
+ </h2>
157
+ <%= render "output_table", report %>
158
+ <% end %>
159
+ </article>
160
+ </div>
161
+ <% end %>
162
+ </div>
163
+
164
+ <article>
165
+ <h2 id="streaks">Streaks</h2>
166
+
167
+ <table class="table streaks">
168
+ <thead>
169
+ <tr>
170
+ <th>IP</th>
171
+ <th>Day and URL</th>
172
+ </tr>
173
+ </thead>
174
+ <tbody>
175
+ <% data[:streaks].group_by(&:first).each do |ip, date_urls| %>
176
+ <tr>
177
+ <td class="ip"><%= ip %></td>
178
+ <td class="streaks">
179
+ <% date_urls.group_by(&:first).each do |date, urls| %>
180
+ <% urls.each do |url| %>
181
+ <b><%= url[1] %>:</b> <%= url[2] %> <br />
182
+ <% end %>
183
+ <% end %>
184
+ </td>
185
+ </tr>
186
+ <% end %>
187
+ </tbody>
188
+ </table>
189
+ </article>
190
+
191
+ <div class="columns">
192
+ <div class="column col-6">
193
+ <article>
194
+ <h2 id="command-invocation">Command Invocation</h2>
195
+
196
+ <table class="table command-invocation">
197
+ <tbody>
198
+ <tr>
199
+ <th>CLI Command</th>
200
+ <td><code><%= data[:command] %></code></td>
201
+ </tr>
202
+ <tr>
203
+ <th>Input file</th>
204
+ <td><code><%= (data[:log_file] || "stdin") %></code></td>
205
+ </tr>
206
+ <tr>
207
+ <th>Ignore crawlers</th>
208
+ <td><code><%= options[:ignore_crawlers] %></code></td></tr>
209
+ <tr>
210
+ <th>Only crawlers</th>
211
+ <td><code><%= options[:only_crawlers] %></code></td>
212
+ </tr>
213
+ <tr>
214
+ <th>No selfpoll</th>
215
+ <td><code><%= options[:no_selfpoll] %></code></td>
216
+ </tr>
217
+ <tr>
218
+ <th>Filter by date</th>
219
+ <td>
220
+ <code><%= (options[:from_date] != nil or options[:to_date] != nil) %></code>
221
+ </td>
222
+ </tr>
223
+ <tr>
224
+ <th>Prefix</th>
225
+ <td><code><%= @prefix %></code></td>
226
+ </tr>
227
+ <tr>
228
+ <th>Suffix</th>
229
+ <td><code><%= @suffix %></code></td>
230
+ </tr>
231
+ </tbody>
232
+ </table>
233
+ </article>
234
+ </div>
235
+
236
+ <div class="column col-6">
237
+ <article>
238
+ <h2 id="performance"> Performance</h2>
239
+
240
+ <table class="table performance">
241
+ <tbody>
242
+ <tr>
243
+ <th>Analysis started at</th>
244
+ <td><%= data[:started_at].to_s %></td>
245
+ </tr>
246
+ <tr>
247
+ <th>Analysis ended at</th>
248
+ <td><%= data[:ended_at].to_s %></td>
249
+ </tr>
250
+ <tr>
251
+ <th>Duration (sec)</th>
252
+ <td><%= "%.1f" % data[:duration] %></td>
253
+ </tr>
254
+ <tr>
255
+ <th>Duration (min)</th>
256
+ <td><%= "%d" % (data[:duration] / 60 ) %></td>
257
+ </tr>
258
+ <tr>
259
+ <th>Log size</th>
260
+ <td><%= data[:log_size][0][0] %></td>
261
+ </tr>
262
+ <tr>
263
+ <th>Lines/sec</th>
264
+ <td><%= "%.2f" % (data[:log_size][0][0] / data[:duration]) %></td></tr>
265
+ </tbody>
266
+ </table>
267
+ </article>
268
+ </div>
269
+ </div>
270
+ </section>
271
+ </div>
195
272
  </body>
196
273
  </html>
197
274
 
@@ -10,7 +10,11 @@
10
10
  | Hits | <%= "%10d" % data[:total_hits][0][0] %> |
11
11
  | Unique Visitors | <%= "%10d" % data[:total_unique_visitors][0][0] %> |
12
12
  | Tx | <%= "%10s" % data[:total_size][0][0] %> |
13
- | Days | <%= "%10d" % data[:total_days][0][0] %> |
13
+ | Logged Period | <%= data[:first_day] %> -- <%= data[:last_day] %> |
14
+ | Days | <%= "%10d" % data[:total_days] %> |
15
+ | Period Requested | <%= data[:first_day_requested] %> -- <%= data[:last_day_requested] %> |
16
+ | Period Analyzed | <%= data[:first_day_in_analysis] %> -- <%= data[:last_day_in_analysis] %> |
17
+ | Days in Analysis | <%= data[:total_days_in_analysis] %> |
14
18
 
15
19
  * Daily Distribution
16
20
 
@@ -1,3 +1,3 @@
1
1
  module ApacheLogReport
2
- VERSION = "1.1.2"
2
+ VERSION = "1.1.6"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apache_log_report
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.6
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-10-31 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: apache_log-parser
@@ -66,7 +66,8 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: Generate a request report in OrgMode format from an Apache log file.
69
+ description: Generate requests reports in HTML, OrgMode, and SQLite format from an
70
+ Apache log file.
70
71
  email:
71
72
  - adolfo.villafiorita@ict4g.net
72
73
  executables:
@@ -121,5 +122,5 @@ requirements: []
121
122
  rubygems_version: 3.2.22
122
123
  signing_key:
123
124
  specification_version: 4
124
- summary: Generate a request report in OrgMode format from an Apache log file.
125
+ summary: Generate analytics from an Apache log file.
125
126
  test_files: []