apache_log_report 1.1.1 → 1.1.5

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: a00134ccecff45a5213565360c91ff2b87c40af4b47bcdda18327ed556dfea86
4
- data.tar.gz: 6244d502e63bf9e699f2ad1f7188f17669d645125e15a7aa591815fa091f51b2
3
+ metadata.gz: c4cd01d24bc31eb2fe1107781a94578b43210fdc7d63dd65190643e637dc8da1
4
+ data.tar.gz: f1889cc37617847862274bd3d65fab82662d5c8e988129a227ed80b1fe4b7887
5
5
  SHA512:
6
- metadata.gz: 3775358b99f42896eae739abf20898588c55026a64d5bac188ac9007a73767fc59c2f608d5a45fb05765bea3f3a2cdb8ae938a07d278232334edb85ba1ce2b5b
7
- data.tar.gz: 82c92ff76df83a14deb79443d8b19eb46b5b5e50e81cfb469c5eeac21e66d2b79ad91a51b1ecec6ac3aafa4dc33ebf2137d5dc1ce3ff988131f2c869b787ad35
6
+ metadata.gz: 520c9648ccd15f9a3bc0b1761989bb091bc81cf7f16eac6cf5bc5bb73c0aef3e47a03eafd85f468c08834dbf93163c4b750ef31d61b63d277f546afcd21082b2
7
+ data.tar.gz: a1833663a335da90513d1054117b9ca39b2f9802c021f7f75dda929312c00e32e7a3725901454c3a3f583839d0addbf511f08e421117f2317892fe1fe1f93628
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- apache_log_report (1.1.0)
4
+ apache_log_report (1.1.2)
5
5
  apache_log-parser
6
6
  browser
7
7
  sqlite3
data/README.org CHANGED
@@ -14,10 +14,8 @@ See the [[file:CHANGELOG.org][CHANGELOG]] file.
14
14
 
15
15
  * Todo
16
16
 
17
- ** TODO Version information from command line and in reports
18
- ** TODO Refactor code from one giant class to more manageable chunkes
19
- ** TODO Move performance stats var to class (to isolate vars)
20
- ** TODO Check total number of days (which is not working, now)
17
+ ** TODO Graphs in HTML output
18
+ ** TODO Countries
21
19
 
22
20
  * Compatibility
23
21
 
@@ -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")
@@ -23,21 +23,28 @@ end
23
23
  @started_at = Time.now
24
24
 
25
25
  @db = ApacheLogReport::LogParser.parse @log_file
26
- @data = ApacheLogReport::DataCruncher.crunch @db, @options
27
26
 
28
- @ended_at = Time.now
29
- @duration = @ended_at - @started_at
30
-
31
- @data = @data.merge({
32
- command: @command,
33
- log_file: @log_file,
34
- started_at: @started_at,
35
- ended_at: @ended_at,
36
- duration: @duration
37
- })
38
-
39
- #
40
- # Emit Output
41
- #
42
-
43
- puts ApacheLogReport::Emitter.emit @data, @options
27
+ if @options[:output_format] == "sqlite"
28
+ ddb = SQLite3::Database.new('db.sqlite3')
29
+ b = SQLite3::Backup.new(ddb, 'main', @db, 'main')
30
+ b.step(-1) #=> DONE
31
+ b.finish
32
+ else
33
+ @data = ApacheLogReport::DataCruncher.crunch @db, @options
34
+
35
+ @ended_at = Time.now
36
+ @duration = @ended_at - @started_at
37
+
38
+ @data = @data.merge({
39
+ command: @command,
40
+ log_file: @log_file,
41
+ started_at: @started_at,
42
+ ended_at: @ended_at,
43
+ duration: @duration
44
+ })
45
+
46
+ #
47
+ # Emit Output
48
+ #
49
+ puts ApacheLogReport::Emitter.emit @data, @options
50
+ end
@@ -39,12 +39,24 @@ module ApacheLogReport
39
39
  END AS size
40
40
  EOS
41
41
 
42
+ human_readable_day = <<-EOS
43
+ case cast (strftime('%w', datetime) as integer)
44
+ when 0 then 'Sunday'
45
+ when 1 then 'Monday'
46
+ when 2 then 'Tuesday'
47
+ when 3 then 'Wednesday'
48
+ when 4 then 'Thursday'
49
+ when 5 then 'Friday'
50
+ else 'Saturday'
51
+ end as dow
52
+ EOS
53
+
42
54
  @total_hits = db.execute "SELECT count(datetime) from LogLine where #{filter}"
43
55
  @total_unique_visitors = db.execute "SELECT count(distinct(unique_visitor)) from LogLine where #{filter}"
44
56
  @total_size = db.execute "SELECT #{human_readable_size} from LogLine where #{filter}"
45
57
  @total_days = (Date.parse(@last_day[0][0]) - Date.parse(@first_day[0][0])).to_i
46
58
 
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)"
59
+ @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
60
  @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
61
  @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
62
  @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]}"
@@ -71,6 +83,8 @@ module ApacheLogReport
71
83
  @ips = db.execute "SELECT ip, count(ip), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by ip order by count(ip) desc limit #{options[:limit]}"
72
84
  @referers = db.execute "SELECT referer, count(referer), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by referer order by count(referer) desc limit #{options[:limit]}"
73
85
 
86
+ @streaks = db.execute "SELECT ip, substr(datetime, 1, 10), path from LogLine order by ip, datetime"
87
+
74
88
  data = {}
75
89
  self.instance_variables.each do |variable|
76
90
  var_as_symbol = variable.to_s[1..-1].to_sym
@@ -50,7 +50,7 @@ module ApacheLogReport
50
50
  args[:code_export] = n
51
51
  end
52
52
 
53
- opts.on("-fFORMAT", "--format=FORMAT", String, "Output format: html, org. Defaults to org mode") do |n|
53
+ opts.on("-fFORMAT", "--format=FORMAT", String, "Output format: html, org, sqlite. Defaults to org mode") do |n|
54
54
  args[:output_format] = n
55
55
  end
56
56
 
@@ -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,158 +4,249 @@
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="days">Days </th>
31
- <td class="days"><%= data[:total_days][0][0] %></td>
32
- </tr>
33
- </table>
34
- </article>
35
-
36
- <% @reports = [
37
- { title: "Daily Distribution", header: ["Day", "Hits", "Visits", "Size"], rows: data[:daily_distribution] },
38
- { title: "Time Distribution", header: ["Hour", "Hits", "Visits", "Size"], rows: data[:time_distribution] },
39
- { title: "Most Requested Pages", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_pages] },
40
- { title: "Most Requested Resources", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_resources] },
41
- { title: "404 on HTML Files", header: ["Path", "Hits", "Visitors"], rows: data[:missed_pages] },
42
- { title: "404 on other Resources", header: ["Path", "Hits", "Visitors"], rows: data[:missed_resources] },
43
- { title: "Attacks", header: ["Path", "Hits", "Visitors"], rows: data[:attacks] },
44
- { title: "Statuses", header: ["Status", "Count"], rows: data[:statuses] },
45
- { title: "Daily Statuses", header: ["Status", "2xx", "3xx", "4xx"], rows: data[:statuses_by_day] },
46
- { title: "Browsers", header: ["Browser", "Hits", "Visitors", "Size"], rows: data[:browsers] },
47
- { title: "Platforms", header: ["Platform", "Hits", "Visitors", "Size"], rows: data[:platforms] },
48
- { title: "IPs", header: ["IPs", "Hits", "Visitors", "Size"], rows: data[:ips] },
49
- { title: "Referers", header: ["Referers", "Hits", "Visitors", "Size"], rows: data[:referers] },
50
- ]
51
- %>
52
- <% @reports.each do |report| %>
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
+ ].each do |item| %>
36
+ <li class="nav-item">
37
+ <a href="#<%= item.downcase.gsub(' ', '-') %>"><%= item %></a>
38
+ </li>
39
+ <% end %>
40
+ </ul>
41
+ </li>
42
+ </ul>
43
+ </nav>
44
+
45
+ <section>
46
+ <h1>Apache Log Analysis: <%= data[:log_file] || "stdin" %></h1>
47
+
48
+ <div class="columns">
49
+ <article class="col-6 column">
50
+ <h2 id="summary">Summary</h2>
51
+
52
+ <table class="table summary">
53
+ <tr>
54
+ <th class="hits">Hits</th>
55
+ <td class="hits"><%= data[:total_hits][0][0] %></td>
56
+ </tr>
57
+ <tr>
58
+ <th class="unique-visitors">Unique Visitors</th>
59
+ <td class="unique-visitors"><%= data[:total_unique_visitors][0][0] %></td>
60
+ </tr>
61
+ <tr>
62
+ <th class="tx">Tx</th>
63
+ <td class="tx"><%= data[:total_size][0][0] %></td>
64
+ </tr>
65
+ <tr>
66
+ <th class="period">Period</th>
67
+ <td class="period">
68
+ <%= data[:first_day][0][0] %>
69
+ --
70
+ <%= data[:last_day][0][0] %>
71
+ </td>
72
+ </tr>
73
+ <tr>
74
+ <th class="days">Days </th>
75
+ <td class="days"><%= data[:total_days] %></td>
76
+ </tr>
77
+ </table>
78
+ </article>
79
+ <article class="column col-6">
80
+ <h2 id="log-structure">Log Structure</h2>
81
+
82
+ <table class="table log-structure">
83
+ <tbody>
84
+ <tr>
85
+ <th>Input file</th>
86
+ <td><b><%= (data[:log_file] || "stdin") %></b></td>
87
+ </tr>
88
+ <tr>
89
+ <th>Log size</th>
90
+ <td><%= data[:log_size][0][0] %></td>
91
+ </tr>
92
+ <tr>
93
+ <th>Self poll entries</th>
94
+ <td><%= data[:selfpolls_size][0][0] %></td>
95
+ </tr>
96
+ <tr>
97
+ <th>Crawlers</th>
98
+ <td><%= data[:crawlers_size][0][0] %></td>
99
+ </tr>
100
+ <tr>
101
+ <th>Entries considered</th>
102
+ <td><%= data[:total_hits][0][0] %></td>
103
+ </tr>
104
+ </tbody>
105
+ </table>
106
+ </article>
107
+ </div>
108
+
109
+ <% @reports = [
110
+ { title: "Daily Distribution", header: ["Day", "DOW", "Hits", "Visits", "Size"], rows: data[:daily_distribution] },
111
+ { title: "Time Distribution", header: ["Hour", "Hits", "Visits", "Size"], rows: data[:time_distribution] },
112
+ { title: "Most Requested Pages", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_pages] },
113
+ { title: "Most Requested Resources", header: ["Path", "Hits", "Visits", "Size"], rows: data[:most_requested_resources] },
114
+ { title: "404 on HTML Files", header: ["Path", "Hits", "Visitors"], rows: data[:missed_pages] },
115
+ { title: "404 on other Resources", header: ["Path", "Hits", "Visitors"], rows: data[:missed_resources] },
116
+ { title: "Attacks", header: ["Path", "Hits", "Visitors"], rows: data[:attacks] },
117
+ { },
118
+ { title: "Statuses", header: ["Status", "Count"], rows: data[:statuses] },
119
+ { title: "Daily Statuses", header: ["Status", "2xx", "3xx", "4xx"], rows: data[:statuses_by_day] },
120
+ { title: "Browsers", header: ["Browser", "Hits", "Visitors", "Size"], rows: data[:browsers] },
121
+ { title: "Platforms", header: ["Platform", "Hits", "Visitors", "Size"], rows: data[:platforms] },
122
+ { title: "Referers", header: ["Referers", "Hits", "Visitors", "Size"], rows: data[:referers], col: "col-12" },
123
+ { title: "IPs", header: ["IPs", "Hits", "Visitors", "Size"], rows: data[:ips] },
124
+ { },
125
+ ]
126
+ %>
127
+ <div class="columns">
128
+ <% @reports.each do |report| %>
129
+ <div class="column <%= report[:col] || "col-6" %>">
130
+ <article>
131
+ <% if report[:title] != nil %>
132
+ <h2 id="<%= report[:title].downcase.gsub(/ +/, '-') %>">
133
+ <%= report[:title] %>
134
+ </h2>
135
+ <%= render "output_table", report %>
136
+ <% end %>
137
+ </article>
138
+ </div>
139
+ <% end %>
140
+ </div>
141
+
53
142
  <article>
54
- <h2><%= report[:title] %></h2>
55
- <%= render "output_table", report %>
143
+ <h2 id="streaks">Streaks</h2>
144
+
145
+ <table class="table streaks">
146
+ <thead>
147
+ <tr>
148
+ <th>IP</th>
149
+ <th>Day and URL</th>
150
+ </tr>
151
+ </thead>
152
+ <tbody>
153
+ <% data[:streaks].group_by(&:first).each do |ip, date_urls| %>
154
+ <tr>
155
+ <td class="ip"><%= ip %></td>
156
+ <td class="streaks">
157
+ <% date_urls.group_by(&:first).each do |date, urls| %>
158
+ <% urls.each do |url| %>
159
+ <b><%= url[1] %>:</b> <%= url[2] %> <br />
160
+ <% end %>
161
+ <% end %>
162
+ </td>
163
+ </tr>
164
+ <% end %>
165
+ </tbody>
166
+ </table>
56
167
  </article>
57
- <% end %>
58
-
59
- <article>
60
- <h2>Command Invocation and Performance</h2>
61
-
62
- <h3>Command Invocation</h3>
63
-
64
- <code>
65
- </code>
66
-
67
- <table class="pure-table command-invocation">
68
- <tbody>
69
- <tr>
70
- <th>CLI Command</th>
71
- <td><pre><%= data[:command] %></pre></td>
72
- </tr>
73
- <tr>
74
- <th>Input file</th>
75
- <td><code><%= (data[:log_file] || "stdin") %></code></td>
76
- </tr>
77
- <tr>
78
- <th>Ignore crawlers</th>
79
- <td><code><%= options[:ignore_crawlers] %></code></td></tr>
80
- <tr>
81
- <th>Only crawlers</th>
82
- <td><code><%= options[:only_crawlers] %></code></td>
83
- </tr>
84
- <tr>
85
- <th>No selfpoll</th>
86
- <td><code><%= options[:no_selfpoll] %></code></td>
87
- </tr>
88
- <tr>
89
- <th>Filter by date</th>
90
- <td>
91
- <code><%= (options[:from_date] != nil or options[:to_date] != nil) %></code>
92
- </td>
93
- </tr>
94
- <tr>
95
- <th>Prefix</th>
96
- <td><code><%= @prefix %></code></td>
97
- </tr>
98
- <tr>
99
- <th>Suffix</th>
100
- <td><code><%= @suffix %></code></td>
101
- </tr>
102
- </tbody>
103
- </table>
104
-
105
- <h3> Log Structure</h3>
106
-
107
- <table class="pure-table log-structure">
108
- <tbody>
109
- <tr>
110
- <th>Log size</th>
111
- <td><%= data[:log_size][0][0] %></td>
112
- </tr>
113
- <tr>
114
- <th>Self poll entries</th>
115
- <td><%= data[:selfpolls_size][0][0] %></td>
116
- </tr>
117
- <tr>
118
- <th>Crawlers</th>
119
- <td><%= data[:crawlers_size][0][0] %></td>
120
- </tr>
121
- <tr>
122
- <th>Entries considered</th>
123
- <td><%= data[:total_hits][0][0] %></td>
124
- </tr>
125
- </tbody>
126
- </table>
127
-
128
- <h3> Performance</h3>
129
-
130
- <table class="pure-table performance">
131
- <tbody>
132
- <tr>
133
- <th>Analysis started at</th>
134
- <td><%= data[:started_at].to_s %></td>
135
- </tr>
136
- <tr>
137
- <th>Analysis ended at</th>
138
- <td><%= data[:ended_at].to_s %></td>
139
- </tr>
140
- <tr>
141
- <th>Duration (sec)</th>
142
- <td><%= "%.1f" % data[:duration] %></td>
143
- </tr>
144
- <tr>
145
- <th>Duration (min)</th>
146
- <td><%= "%d" % (data[:duration] / 60 ) %></td>
147
- </tr>
148
- <tr>
149
- <th>Log size</th>
150
- <td><%= data[:log_size][0][0] %></td>
151
- </tr>
152
- <tr>
153
- <th>Lines/sec</th>
154
- <td><%= "%.2f" % (data[:log_size][0][0] / data[:duration]) %></td></tr>
155
- </tbody>
156
- </table>
157
- </article>
158
- </section>
168
+
169
+ <div class="columns">
170
+ <div class="column col-6">
171
+ <article>
172
+ <h2 id="command-invocation">Command Invocation</h2>
173
+
174
+ <table class="table command-invocation">
175
+ <tbody>
176
+ <tr>
177
+ <th>CLI Command</th>
178
+ <td><pre><%= data[:command] %></pre></td>
179
+ </tr>
180
+ <tr>
181
+ <th>Input file</th>
182
+ <td><code><%= (data[:log_file] || "stdin") %></code></td>
183
+ </tr>
184
+ <tr>
185
+ <th>Ignore crawlers</th>
186
+ <td><code><%= options[:ignore_crawlers] %></code></td></tr>
187
+ <tr>
188
+ <th>Only crawlers</th>
189
+ <td><code><%= options[:only_crawlers] %></code></td>
190
+ </tr>
191
+ <tr>
192
+ <th>No selfpoll</th>
193
+ <td><code><%= options[:no_selfpoll] %></code></td>
194
+ </tr>
195
+ <tr>
196
+ <th>Filter by date</th>
197
+ <td>
198
+ <code><%= (options[:from_date] != nil or options[:to_date] != nil) %></code>
199
+ </td>
200
+ </tr>
201
+ <tr>
202
+ <th>Prefix</th>
203
+ <td><code><%= @prefix %></code></td>
204
+ </tr>
205
+ <tr>
206
+ <th>Suffix</th>
207
+ <td><code><%= @suffix %></code></td>
208
+ </tr>
209
+ </tbody>
210
+ </table>
211
+ </article>
212
+ </div>
213
+
214
+ <div class="column col-6">
215
+ <article>
216
+ <h2 id="performance"> Performance</h2>
217
+
218
+ <table class="table performance">
219
+ <tbody>
220
+ <tr>
221
+ <th>Analysis started at</th>
222
+ <td><%= data[:started_at].to_s %></td>
223
+ </tr>
224
+ <tr>
225
+ <th>Analysis ended at</th>
226
+ <td><%= data[:ended_at].to_s %></td>
227
+ </tr>
228
+ <tr>
229
+ <th>Duration (sec)</th>
230
+ <td><%= "%.1f" % data[:duration] %></td>
231
+ </tr>
232
+ <tr>
233
+ <th>Duration (min)</th>
234
+ <td><%= "%d" % (data[:duration] / 60 ) %></td>
235
+ </tr>
236
+ <tr>
237
+ <th>Log size</th>
238
+ <td><%= data[:log_size][0][0] %></td>
239
+ </tr>
240
+ <tr>
241
+ <th>Lines/sec</th>
242
+ <td><%= "%.2f" % (data[:log_size][0][0] / data[:duration]) %></td></tr>
243
+ </tbody>
244
+ </table>
245
+ </article>
246
+ </div>
247
+ </div>
248
+ </section>
249
+ </div>
159
250
  </body>
160
251
  </html>
161
252
 
@@ -1,3 +1,3 @@
1
1
  module ApacheLogReport
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.5"
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.1
4
+ version: 1.1.5
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:
@@ -118,8 +119,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
119
  - !ruby/object:Gem::Version
119
120
  version: '0'
120
121
  requirements: []
121
- rubygems_version: 3.0.3
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: []