log_sense 1.6.1 → 1.7.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.
@@ -1,10 +1,10 @@
1
1
  <ul class="stats-list">
2
2
  <li>
3
- <%= data[:first_day_in_analysis].strftime("%b %d, %Y") %>
3
+ <%= data[:first_day_in_analysis]&.strftime("%b %d, %Y") %>
4
4
  <span class="stats-list-label">From</span>
5
5
  </li>
6
6
  <li>
7
- <%= data[:last_day_in_analysis].strftime("%b %d, %Y") %>
7
+ <%= data[:last_day_in_analysis]&.strftime("%b %d, %Y") %>
8
8
  <span class="stats-list-label">To</span>
9
9
  </li>
10
10
  <li class="stats-list-positive">
@@ -65,6 +65,7 @@
65
65
  <%= report[:vega_spec].to_json %>,
66
66
  { "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
67
67
  width: "container",
68
+ height: 400,
68
69
  description: "<%= report[:title] %>",
69
70
  data: {
70
71
  values: data_<%= index %>
@@ -1,3 +1,3 @@
1
1
  module LogSense
2
- VERSION = "1.6.1"
2
+ VERSION = "1.7.0"
3
3
  end
data/lib/log_sense.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require "log_sense/version"
2
2
 
3
- require "log_sense/options_parser"
4
- require "log_sense/options_checker"
3
+ require "log_sense/options/parser"
4
+ require "log_sense/options/checker"
5
5
 
6
- require "log_sense/apache_log_parser"
7
- require "log_sense/rails_log_parser"
6
+ require "log_sense/apache/log_parser"
7
+ require "log_sense/rails/log_parser"
8
8
 
9
9
  require "log_sense/aggregator"
10
10
  require "log_sense/apache_aggregator"
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.6.1
4
+ version: 1.7.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: 2023-11-04 00:00:00.000000000 Z
11
+ date: 2024-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: browser
@@ -130,16 +130,16 @@ files:
130
130
  - ip_locations/dbip-country-lite.sqlite3
131
131
  - lib/log_sense.rb
132
132
  - lib/log_sense/aggregator.rb
133
+ - lib/log_sense/apache/log_line_parser.rb
134
+ - lib/log_sense/apache/log_parser.rb
133
135
  - lib/log_sense/apache_aggregator.rb
134
- - lib/log_sense/apache_log_line_parser.rb
135
- - lib/log_sense/apache_log_parser.rb
136
136
  - lib/log_sense/apache_report_shaper.rb
137
137
  - lib/log_sense/emitter.rb
138
138
  - lib/log_sense/ip_locator.rb
139
- - lib/log_sense/options_checker.rb
140
- - lib/log_sense/options_parser.rb
139
+ - lib/log_sense/options/checker.rb
140
+ - lib/log_sense/options/parser.rb
141
+ - lib/log_sense/rails/log_parser.rb
141
142
  - lib/log_sense/rails_aggregator.rb
142
- - lib/log_sense/rails_log_parser.rb
143
143
  - lib/log_sense/rails_report_shaper.rb
144
144
  - lib/log_sense/report_shaper.rb
145
145
  - lib/log_sense/templates/_cdn_links.html.erb
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
188
  - !ruby/object:Gem::Version
189
189
  version: '0'
190
190
  requirements: []
191
- rubygems_version: 3.4.21
191
+ rubygems_version: 3.3.26
192
192
  signing_key:
193
193
  specification_version: 4
194
194
  summary: Generate analytics for Apache and Rails log file.
@@ -1,57 +0,0 @@
1
- module LogSense
2
- # parses a log line and returns a hash
3
- # LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
4
- #
5
- # %h: IP
6
- # %l: ident or -
7
- # %u: userid or -
8
- # %t: [10/Oct/2000:13:55:36 -0700]
9
- # day = 2*digit
10
- # month = 3*letter
11
- # year = 4*digit
12
- # hour = 2*digit
13
- # minute = 2*digit
14
- # second = 2*digit
15
- # zone = (`+' | `-') 4*digit
16
- # %r: GET /apache_pb.gif HTTP/1.0
17
- # %{User-agent}: "
18
- #
19
- # Example
20
- # 116.179.32.16 - - [19/Dec/2021:22:35:11 +0100] "GET / HTTP/1.1" 200 135 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
21
- #
22
- class ApacheLogLineParser
23
- DAY = /[0-9]{2}/
24
- MONTH = /[A-Za-z]{3}/
25
- YEAR = /[0-9]{4}/
26
- TIMEC = /[0-9]{2}/
27
- TIMEZONE = /(\+|-)[0-9]{4}/
28
-
29
- IP = /(?<ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|::1)/
30
- IDENT = /(?<ident>[^ ]+|-)/
31
- USERID = /(?<userid>[^ ]+|-)/
32
-
33
- TIMESTAMP = /(?<date>#{DAY}\/#{MONTH}\/#{YEAR}):(?<time>#{TIMEC}:#{TIMEC}:#{TIMEC} #{TIMEZONE})/
34
-
35
- HTTP_METHODS = /GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH/
36
- WEBDAV_METHODS = /COPY|LOCK|MKCOL|MOVE|PROPFIND|PROPPATCH|UNLOCK/
37
- OTHER_METHODS = /SEARCH|REPORT|PRI|HEAD\/robots.txt/
38
- METHOD = /(?<method>#{HTTP_METHODS}|#{WEBDAV_METHODS}|#{OTHER_METHODS})/
39
- PROTOCOL = /(?<protocol>HTTP\/[0-9]\.[0-9]|-|.*)/
40
- URL = /(?<url>[^ ]+)/
41
- REFERER = /(?<referer>[^"]*)/
42
- RETURN_CODE = /(?<status>[1-5][0-9][0-9])/
43
- SIZE = /(?<size>[0-9]+|-)/
44
- USER_AGENT = /(?<user_agent>[^"]*)/
45
-
46
- attr_reader :format
47
-
48
- def initialize
49
- @format = /#{IP} #{IDENT} #{USERID} \[#{TIMESTAMP}\] "(#{METHOD} #{URL} #{PROTOCOL}|-|.+)" #{RETURN_CODE} #{SIZE} "#{REFERER}" "#{USER_AGENT}"/
50
- end
51
-
52
- def parse(line)
53
- @format.match(line) ||
54
- raise("Apache LogLine Parser Error: Could not parse #{line}")
55
- end
56
- end
57
- end
@@ -1,100 +0,0 @@
1
- require "sqlite3"
2
- require "browser"
3
- require "log_sense/apache_log_line_parser"
4
-
5
- module LogSense
6
- #
7
- # parse an Apache log file and return a SQLite3 DB
8
- #
9
- class ApacheLogParser
10
- def parse(streams, options = {})
11
- db = SQLite3::Database.new ":memory:"
12
-
13
- db.execute "CREATE TABLE IF NOT EXISTS LogLine(
14
- id INTEGER PRIMARY KEY AUTOINCREMENT,
15
- datetime TEXT,
16
- ip TEXT,
17
- user TEXT,
18
- unique_visitor TEXT,
19
- method TEXT,
20
- path TEXT,
21
- extension TEXT,
22
- status TEXT,
23
- size INTEGER,
24
- referer TEXT,
25
- user_agent TEXT,
26
- bot INTEGER,
27
- browser TEXT,
28
- browser_version TEXT,
29
- platform TEXT,
30
- platform_version TEXT,
31
- source_file TEXT,
32
- line_number INTEGER
33
- )"
34
-
35
- ins = db.prepare("insert into LogLine (
36
- datetime,
37
- ip,
38
- user,
39
- unique_visitor,
40
- method,
41
- path,
42
- extension,
43
- status,
44
- size,
45
- referer,
46
- user_agent,
47
- bot,
48
- browser,
49
- browser_version,
50
- platform,
51
- platform_version,
52
- source_file,
53
- line_number
54
- )
55
- values (#{Array.new(18, '?').join(', ')})")
56
-
57
- parser = ApacheLogLineParser.new
58
-
59
- streams.each do |stream|
60
- stream.readlines.each_with_index do |line, line_number|
61
- begin
62
- hash = parser.parse line
63
- ua = Browser.new(hash[:user_agent], accept_language: 'en-us')
64
- ins.execute(
65
- DateTime.parse("#{hash[:date]}T#{hash[:time]}").iso8601,
66
- hash[:ip],
67
- hash[:userid],
68
- unique_visitor_id(hash),
69
- hash[:method],
70
- hash[:url],
71
- (hash[:url] ? File.extname(hash[:url]) : ''),
72
- hash[:status],
73
- hash[:size].to_i,
74
- hash[:referer],
75
- hash[:user_agent],
76
- ua.bot? ? 1 : 0,
77
- (ua.name || ''),
78
- (ua.version || ''),
79
- (ua.platform.name || ''),
80
- (ua.platform.version || ''),
81
- stream == $stdin ? "stdin" : stream.path,
82
- line_number
83
- )
84
- rescue StandardError => e
85
- warn e.message
86
- end
87
- end
88
- end
89
-
90
- db
91
- end
92
-
93
- private
94
-
95
- def unique_visitor_id hash
96
- "#{hash[:date]} #{hash[:ip]} #{hash[:user_agent]}"
97
- end
98
- end
99
- end
100
-
@@ -1,24 +0,0 @@
1
- module LogSense
2
- #
3
- # Check options and return appropriate error if
4
- # command arguments are wrong
5
- #
6
- module OptionsChecker
7
- SUPPORTED_CHAINS = {
8
- rails: %i[txt html sqlite3 ufw],
9
- apache: %i[txt html sqlite3 ufw]
10
- }.freeze
11
-
12
- def self.compatible?(iformat, oformat)
13
- (SUPPORTED_CHAINS[iformat.to_sym] || []).include? oformat.to_sym
14
- end
15
-
16
- def self.chains_to_s
17
- string = ""
18
- SUPPORTED_CHAINS.each do |iformat, oformat|
19
- string << "- #{iformat}: #{oformat.join(", ")}\n"
20
- end
21
- string
22
- end
23
- end
24
- end
@@ -1,147 +0,0 @@
1
- require "optparse"
2
- require "optparse/date"
3
- require "log_sense/version"
4
- require "log_sense/options_checker"
5
-
6
- module LogSense
7
- module OptionsParser
8
- #
9
- # parse command line options
10
- #
11
- def self.parse(options)
12
- limit = 100
13
- args = {}
14
-
15
- opt_parser = OptionParser.new do |opts|
16
- opts.banner = "Usage: log_sense [options] [logfile ...]"
17
-
18
- opts.on("-tTITLE", "--title=TITLE",
19
- String,
20
- "Title to use in the report") do |optval|
21
- args[:title] = optval
22
- end
23
-
24
- opts.on("-fFORMAT", "--input-format=FORMAT",
25
- String,
26
- "Input format (either rails or apache)") do |optval|
27
- args[:input_format] = optval
28
- end
29
-
30
- opts.on("-iFORMAT", "--input-files=file,file,",
31
- Array,
32
- "Input files (can also be passed directly)") do |optval|
33
- args[:input_filenames] = optval
34
- end
35
-
36
- opts.on("-tFORMAT", "--output-format=FORMAT",
37
- String,
38
- "Output format: html, org, txt, sqlite.") do |optval|
39
- args[:output_format] = optval
40
- end
41
-
42
- opts.on("-oOUTPUT_FILE", "--output-file=OUTPUT_FILE",
43
- String,
44
- "Output file") do |n|
45
- args[:output_filename] = n
46
- end
47
-
48
- opts.on("-bDATE", "--begin=DATE",
49
- Date,
50
- "Consider entries after or on DATE") do |optval|
51
- args[:from_date] = optval
52
- end
53
-
54
- opts.on("-eDATE", "--end=DATE",
55
- Date,
56
- "Consider entries before or on DATE") do |optval|
57
- args[:to_date] = optval
58
- end
59
-
60
- opts.on("-lN", "--limit=N",
61
- Integer,
62
- "Limit to the N most requested resources (defaults to #{limit})") do |optval|
63
- args[:limit] = optval
64
- end
65
-
66
- opts.on("-wWIDTH", "--width=WIDTH",
67
- Integer,
68
- "Maximum width of long columns in textual reports") do |optval|
69
- args[:width] = optval
70
- end
71
-
72
- opts.on("-rROWS", "--rows=ROWS",
73
- Integer,
74
- "Maximum number of rows for columns with multiple entries in textual reports") do |optval|
75
- args[:inner_rows] = optval
76
- end
77
-
78
- opts.on("-pPATTERN", "--pattern=PATTERN",
79
- String,
80
- "Pattern to use with ufw report to decide IP to blacklist") do |optval|
81
- args[:pattern] = optval
82
- end
83
-
84
- opts.on("-cPOLICY", "--crawlers=POLICY",
85
- String,
86
- "Decide what to do with crawlers (applies to Apache Logs)") do |optval|
87
- case optval
88
- when "only"
89
- args[:only_crawlers] = true
90
- when "ignore"
91
- args[:ignore_crawlers] = true
92
- end
93
- end
94
-
95
- opts.on("-ns", "--no-selfpoll",
96
- "Ignore self poll entries (requests from ::1; applies to Apache Logs)") do
97
- args[:no_selfpoll] = true
98
- end
99
-
100
- opts.on("-ng", "--no-geo",
101
- "Do not geolocate entries") do
102
- args[:geolocation] = false
103
- end
104
-
105
- opts.on("--verbose", "Inform about progress (output to STDERR)") do
106
- args[:verbose] = true
107
- end
108
-
109
- opts.on("-v", "--version", "Prints version information") do
110
- puts "log_sense version #{LogSense::VERSION}"
111
- puts "Copyright (C) 2021 Shair.Tech"
112
- puts "Distributed under the terms of the MIT license"
113
- exit
114
- end
115
-
116
- opts.on("-h", "--help", "Prints this help") do
117
- puts opts
118
- puts
119
- puts "This is version #{LogSense::VERSION}"
120
-
121
- puts
122
- puts "Output formats:"
123
- puts
124
-
125
- puts OptionsChecker.chains_to_s
126
-
127
- exit 0
128
- end
129
- end
130
-
131
- opt_parser.parse!(options)
132
-
133
- args[:limit] ||= limit
134
- args[:input_filenames] ||= []
135
- args[:input_format] ||= "apache"
136
- args[:output_format] ||= "html"
137
- args[:ignore_crawlers] ||= false
138
- args[:only_crawlers] ||= false
139
- args[:no_selfpoll] ||= false
140
- args[:verbose] ||= false
141
- # if set to false leave, otherwise set to true
142
- args[:geolocation] = true unless args[:geolocation] == false
143
-
144
- args
145
- end
146
- end
147
- end