log_sense 1.0.6 → 1.0.7

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: 646e45e06b2dd991574f0b7976d0e79e5e59c4230fb704650545aab1ad9304cd
4
- data.tar.gz: 95251d0aeade9cdcbebd382df2d816f12f139b07f658d8523591bdcc6dde51e8
3
+ metadata.gz: 8f2fcc8402c27ec959854e3cd032e9e75693e538d3ca0879de3f4cf0b6aae9c5
4
+ data.tar.gz: e2530ff646c436ca88e674a698bf71876f2e62bc0b59f20ebbc4e38fdd787830
5
5
  SHA512:
6
- metadata.gz: 0f2abde64d922b9a871a8a17d225672a5a1148165e9464c0cdde73cd456602c4221b08d5e572a015ffbc8b6b1c28a8c27a0f043b875c9590527930bed778f0c2
7
- data.tar.gz: e27d0edd01a837b53bdcf0400499d52e8ffcb73796ff60fe11d7893d476521d519d8feb1614e6b98ac9af44faeb5a556a19afaf8e8f83c6cf634ec5055ef3fea
6
+ metadata.gz: 30932a09a0a0d0717c4e5caa9a579bb60a3a930dc144dc318029945e0364e71e5ddf5d5868ccf758a11d3ed5f73f5d690f482521e3475f1f16a5a041fa4abd8a
7
+ data.tar.gz: da8ac76f281cf9f8c67805621fe098d1480889f2fb5a55a378d1ffae3383c1913d572c28c9a68c876fb710b4e8bc3213b157c51cdf008f1505c320ef5fabedd0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- log_sense (1.2.0)
4
+ log_sense (1.0.7)
5
5
  apache_log-parser
6
6
  browser
7
7
  ipaddr
@@ -34,4 +34,4 @@ DEPENDENCIES
34
34
  rake (~> 12.0)
35
35
 
36
36
  BUNDLED WITH
37
- 2.2.29
37
+ 2.2.32
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Adolfo Villafiorita
3
+ Copyright (c) 2021 Shair.Tech
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/exe/log_sense CHANGED
@@ -6,10 +6,11 @@ require 'log_sense.rb'
6
6
  # Parse Command Line Arguments
7
7
  #
8
8
 
9
- # better be here... OptionsParser consumes ARGV
9
+ # this better be here... OptionsParser consumes ARGV
10
10
  @command_line = ARGV.join(" ")
11
+
11
12
  @options = LogSense::OptionsParser.parse ARGV
12
- @input_file = @options[:input_file]
13
+ @input_file = @options[:input_file] || ARGV[0]
13
14
  @output_file = @options[:output_file]
14
15
 
15
16
  if not @input_file
@@ -11,8 +11,8 @@ module LogSense
11
11
  last_day_s = db.execute "SELECT datetime from LogLine order by datetime desc limit 1"
12
12
 
13
13
  # make first and last day into dates or nil
14
- @first_day = first_day_s.empty? ? nil : Date.parse(first_day_s[0][0])
15
- @last_day = last_day_s.empty? ? nil : Date.parse(last_day_s[0][0])
14
+ @first_day = first_day_s[0][0] ? nil : Date.parse(first_day_s[0][0])
15
+ @last_day = last_day_s[0][0] ? nil : Date.parse(last_day_s[0][0])
16
16
 
17
17
  @total_days = 0
18
18
  if @first_day and @last_day
@@ -20,8 +20,13 @@ module LogSense
20
20
  end
21
21
 
22
22
  @log_size = db.execute "SELECT count(datetime) from LogLine"
23
- @crawlers_size = db.execute "SELECT count(datetime) from LogLine where bot == 1"
23
+ @log_size = @log_size[0][0]
24
+
24
25
  @selfpolls_size = db.execute "SELECT count(datetime) from LogLine where ip == '::1'"
26
+ @selfpolls_size = @selfpolls_size[0][0]
27
+
28
+ @crawlers_size = db.execute "SELECT count(datetime) from LogLine where bot == 1"
29
+ @crawlers_size = @crawlers_size[0][0]
25
30
 
26
31
  @first_day_requested = options[:from_date]
27
32
  @last_day_requested = options[:to_date]
@@ -74,8 +79,13 @@ module LogSense
74
79
  EOS
75
80
 
76
81
  @total_hits = db.execute "SELECT count(datetime) from LogLine where #{filter}"
77
- @total_unique_visitors = db.execute "SELECT count(distinct(unique_visitor)) from LogLine where #{filter}"
82
+ @total_hits = @total_hits[0][0]
83
+
84
+ @total_unique_visits = db.execute "SELECT count(distinct(unique_visitor)) from LogLine where #{filter}"
85
+ @total_unique_visits = @total_unique_visits[0][0]
86
+
78
87
  @total_size = db.execute "SELECT #{human_readable_size} from LogLine where #{filter}"
88
+ @total_size = @total_size[0][0]
79
89
 
80
90
  @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)"
81
91
  @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)"
@@ -33,14 +33,8 @@ module LogSense
33
33
 
34
34
  private
35
35
 
36
- def self.output_txt_table name, headings, rows
37
- name = "#+NAME: #{name}"
38
- table = Terminal::Table.new headings: headings, rows: rows, style: { border_x: "-", border_i: "|" }
39
- name + "\n" + table.to_s
40
- end
41
-
42
36
  def self.render(template, vars)
43
- @template = File.join(File.dirname(__FILE__), "templates", "_#{template}.html.erb")
37
+ @template = File.join(File.dirname(__FILE__), "templates", "_#{template}")
44
38
  erb_template = File.read @template
45
39
  ERB.new(erb_template).result(OpenStruct.new(vars).instance_eval { binding })
46
40
  end
@@ -1,6 +1,6 @@
1
1
  require 'optparse'
2
2
  require 'optparse/date'
3
- require 'apache_log_report/version'
3
+ require 'log_sense/version'
4
4
 
5
5
  module LogSense
6
6
  module OptionsParser
@@ -14,19 +14,19 @@ module LogSense
14
14
  opt_parser = OptionParser.new do |opts|
15
15
  opts.banner = "Usage: log_sense [options] [logfile]"
16
16
 
17
- opts.on("-fFORMAT", "--from=FORMAT", String, "Input format (either rails or apache)") do |n|
17
+ opts.on("-fFORMAT", "--input-format=FORMAT", String, "Input format (either rails or apache)") do |n|
18
18
  args[:input_format] = n
19
19
  end
20
20
 
21
- opts.on("-iINPUT_FILE", "--input=INPUT_FILE", String, "Input file") do |n|
21
+ opts.on("-iINPUT_FILE", "--input-file=INPUT_FILE", String, "Input file") do |n|
22
22
  args[:input_file] = n
23
23
  end
24
24
 
25
- opts.on("-tFORMAT", "--to=FORMAT", String, "Output format: html, org, txt, sqlite. Defaults to org mode") do |n|
25
+ opts.on("-tFORMAT", "--output-format=FORMAT", String, "Output format: html, org, txt, sqlite. Defaults to org mode") do |n|
26
26
  args[:output_format] = n
27
27
  end
28
28
 
29
- opts.on("-oOUTPUT_FILE", "--output=OUTPUT_FILE", String, "Output file") do |n|
29
+ opts.on("-oOUTPUT_FILE", "--output-file=OUTPUT_FILE", String, "Output file") do |n|
30
30
  args[:output_file] = n
31
31
  end
32
32
 
@@ -57,16 +57,28 @@ module LogSense
57
57
 
58
58
  opts.on("-v", "--version", "Prints version information") do
59
59
  puts "log_sense version #{LogSense::VERSION}"
60
- puts "Copyright (C) 2020 Adolfo Villafiorita"
60
+ puts "Copyright (C) 2021 Shair.Tech"
61
61
  puts "Distributed under the terms of the MIT license"
62
- puts ""
63
- puts "Written by Adolfo Villafiorita"
64
62
  exit
65
63
  end
66
64
 
67
65
  opts.on("-h", "--help", "Prints this help") do
68
66
  puts opts
67
+ puts ""
69
68
  puts "This is version #{LogSense::VERSION}"
69
+
70
+ puts ""
71
+ puts "Output formats"
72
+ pathname = File.join(File.dirname(__FILE__), "templates", "*")
73
+ templates = Dir.glob(pathname).select { |x| ! File.basename(x).start_with? /_|#/ and ! File.basename(x).end_with? "~" }
74
+ components = templates.map { |x| File.basename(x).split "." }.group_by { |x| x[0] }
75
+ components.each do |k, vs|
76
+ puts "#{k} parsing can produce the following outputs:"
77
+ vs.each do |v|
78
+ puts " - #{v[1]}"
79
+ end
80
+ end
81
+
70
82
  exit
71
83
  end
72
84
  end
@@ -8,22 +8,28 @@ module LogSense
8
8
  #
9
9
 
10
10
  def self.crunch db, options = { limit: 30 }
11
- first_day_s = db.execute "SELECT started_at from Event order by started_at limit 1"
11
+ first_day_s = db.execute "SELECT started_at from Event where started_at not NULL order by started_at limit 1"
12
12
  # we could use ended_at to cover the full activity period, but I prefer started_at
13
13
  # with the meaning that the monitor event initiation
14
14
  last_day_s = db.execute "SELECT started_at from Event order by started_at desc limit 1"
15
15
 
16
16
  # make first and last day into dates or nil
17
17
  # TODO: bug possible value here: [[nil]], which is not empty
18
- @first_day = first_day_s.empty? ? nil : Date.parse(first_day_s[0][0])
19
- @last_day = last_day_s.empty? ? nil : Date.parse(last_day_s[0][0])
18
+ @first_day = ! first_day_s[0][0] ? nil : Date.parse(first_day_s[0][0])
19
+ @last_day = ! last_day_s[0][0] ? nil : Date.parse(last_day_s[0][0])
20
20
 
21
21
  @total_days = 0
22
22
  if @first_day and @last_day
23
23
  @total_days = (@last_day - @first_day).to_i
24
24
  end
25
25
 
26
+ @log_size = db.execute "SELECT count(started_at) from Event"
27
+ @log_size = @log_size[0][0]
28
+
29
+ # SAME AS ABOVE (but log_size is wrong in the case of Rails
30
+ # logs, since an event takes more than one line)
26
31
  @events = db.execute "SELECT count(started_at) from Event"
32
+ @events = @events[0][0]
27
33
 
28
34
  @first_day_requested = options[:from_date]
29
35
  @last_day_requested = options[:to_date]
@@ -74,6 +80,9 @@ module LogSense
74
80
 
75
81
  @total_events = db.execute "SELECT count(started_at) from Event where #{filter}"
76
82
 
83
+ @total_unique_visits = db.execute "SELECT count(distinct(unique_visitor)) from Event where #{filter}"
84
+ @total_unique_visits = @total_unique_visits[0][0]
85
+
77
86
  @daily_distribution = db.execute "SELECT date(started_at), #{human_readable_day}, count(started_at) from Event where #{filter} group by date(started_at)"
78
87
  @time_distribution = db.execute "SELECT strftime('%H', started_at), count(started_at) from Event where #{filter} group by strftime('%H', started_at)"
79
88
 
@@ -12,6 +12,7 @@ module LogSense
12
12
  ended_at TEXT,
13
13
  log_id TEXT,
14
14
  ip TEXT,
15
+ unique_visitor TEXT,
15
16
  url TEXT,
16
17
  controller TEXT,
17
18
  html_verb TEXT,
@@ -27,6 +28,7 @@ module LogSense
27
28
  ended_at,
28
29
  log_id,
29
30
  ip,
31
+ unique_visitor,
30
32
  url,
31
33
  controller,
32
34
  html_verb,
@@ -35,7 +37,7 @@ module LogSense
35
37
  duration_views_ms,
36
38
  duration_ar_ms,
37
39
  allocations)
38
- values (#{Array.new(12, '?').join(', ')})")
40
+ values (#{Array.new(13, '?').join(', ')})")
39
41
 
40
42
  # requests in the log might be interleaved.
41
43
  #
@@ -90,6 +92,7 @@ module LogSense
90
92
  event[:ended_at],
91
93
  event[:log_id],
92
94
  event[:ip],
95
+ "#{DateTime.parse(event[:ended_at]).strftime("%Y-%m-%d")} #{event[:ip]}",
93
96
  event[:url],
94
97
  event[:controller],
95
98
  event[:html_verb],
@@ -0,0 +1,29 @@
1
+ <table class="table unstriped command-invocation">
2
+ <tbody>
3
+ <tr>
4
+ <th>CLI Command</th>
5
+ <td><code><%= data[:command] %></code></td>
6
+ </tr>
7
+ <tr>
8
+ <th>Input file</th>
9
+ <td><code><%= (data[:log_file] || "stdin") %></code></td>
10
+ </tr>
11
+ <tr>
12
+ <th>Ignore crawlers</th>
13
+ <td><code><%= options[:ignore_crawlers] %></code></td></tr>
14
+ <tr>
15
+ <th>Only crawlers</th>
16
+ <td><code><%= options[:only_crawlers] %></code></td>
17
+ </tr>
18
+ <tr>
19
+ <th>No selfpoll</th>
20
+ <td><code><%= options[:no_selfpoll] %></code></td>
21
+ </tr>
22
+ <tr>
23
+ <th>Filter by date</th>
24
+ <td>
25
+ <code><%= (options[:from_date] != nil or options[:to_date] != nil) %></code>
26
+ </td>
27
+ </tr>
28
+ </tbody>
29
+ </table>
@@ -0,0 +1,6 @@
1
+ <%=
2
+ table = Terminal::Table.new rows: [ ["Command", data[:command] ],
3
+ ["Input file", data[:log_file] || "stdin" ]
4
+ ]
5
+ table
6
+ %>
@@ -4,7 +4,7 @@ def slugify string
4
4
  end
5
5
  %>
6
6
 
7
- <table id="<%= slugify(title || "") %>" class="table <%= slugify(title || "") %>">
7
+ <table id="<%= slugify(title || "") %>-table" class="table unstriped data-table <%= slugify(title || "") %>">
8
8
  <thead>
9
9
  <tr>
10
10
  <% header.each do |heading| %>
@@ -0,0 +1,23 @@
1
+ <table class="table unstriped performance">
2
+ <tbody>
3
+ <tr>
4
+ <th>Analysis started at</th>
5
+ <td><%= data[:started_at].to_s %></td>
6
+ </tr>
7
+ <tr>
8
+ <th>Analysis ended at</th>
9
+ <td><%= data[:ended_at].to_s %></td>
10
+ </tr>
11
+ <tr>
12
+ <th>Duration</th>
13
+ <td><%= "%02d:%02d" % [data[:duration] / 60, data[:duration] % 60] %></td>
14
+ </tr>
15
+ <tr>
16
+ <th>Events</th>
17
+ <td><%= data[:log_size] %></td>
18
+ </tr>
19
+ <tr>
20
+ <th>Parsed Events/sec</th>
21
+ <td><%= "%.2f" % (data[:log_size] / data[:duration]) %></td></tr>
22
+ </tbody>
23
+ </table>
@@ -0,0 +1,9 @@
1
+ <%=
2
+ table = Terminal::Table.new rows: [ ["Analysis started at", data[:started_at].to_s ],
3
+ ["Analysis ended at", data[:ended_at].to_s ],
4
+ ["Duration", "%02d:%02d" % [data[:duration] / 60, data[:duration] % 60] ],
5
+ ["Events", "%9d" % data[:log_size] ],
6
+ ["Parsed events/sec", "%.2f" % (data[:log_size] / data[:duration]) ] ]
7
+ table.align_column(2, :right)
8
+ table
9
+ %>
@@ -0,0 +1,34 @@
1
+ <table class="table unstriped summary">
2
+ <tr>
3
+ <th>Input file</th>
4
+ <td><b><%= (data[:log_file] || "stdin") %></b></td>
5
+ </tr>
6
+ <tr>
7
+ <th class="period">Period Analyzed</th>
8
+ <td class="period">
9
+ <%= data[:first_day_in_analysis] %>
10
+ --
11
+ <%= data[:last_day_in_analysis] %>
12
+ </td>
13
+ </tr>
14
+ <tr>
15
+ <th class="days">Days </th>
16
+ <td class="days"><%= data[:total_days_in_analysis] %></td>
17
+ </tr>
18
+ <tr>
19
+ <th class="hits">Hits</th>
20
+ <td class="hits"><%= data[:total_hits] %></td>
21
+ </tr>
22
+ <tr>
23
+ <th class="unique-visits">Unique Visits</th>
24
+ <td class="unique-visits"><%= data[:total_unique_visits] %></td>
25
+ </tr>
26
+ <tr>
27
+ <th class="avg-hits-per-unique-visits">Unique Visits</th>
28
+ <td class="avg-hits-per-unique-visits"><%= data[:total_hits] / data[:total_unique_visits] %></td>
29
+ </tr>
30
+ <tr>
31
+ <th class="tx">Tx</th>
32
+ <td class="tx"><%= data[:total_size] %></td>
33
+ </tr>
34
+ </table>
@@ -0,0 +1,10 @@
1
+ <%=
2
+ table = Terminal::Table.new rows: [ ["Input File", data[:log_file] || "stdin" ],
3
+ ["Period Analyzed", "#{data[:first_day_in_analysis]} -- #{data[:last_day_in_analysis]}" ],
4
+ ["Days", data[:total_days_in_analysis] ],
5
+ ["Events", data[:events] ],
6
+ ["Unique Visits", data[:total_unique_visits] ],
7
+ ["Avg. Events per Visit", data[:events] / data[:total_unique_visits] ]
8
+ ]
9
+ table
10
+ %>
@@ -0,0 +1,32 @@
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>