log_sense 1.5.2 → 1.6.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.org +27 -0
  3. data/Gemfile.lock +6 -4
  4. data/README.org +108 -34
  5. data/Rakefile +6 -6
  6. data/exe/log_sense +110 -39
  7. data/ip_locations/dbip-country-lite.sqlite3 +0 -0
  8. data/lib/log_sense/aggregator.rb +191 -0
  9. data/lib/log_sense/apache_aggregator.rb +122 -0
  10. data/lib/log_sense/apache_log_line_parser.rb +23 -21
  11. data/lib/log_sense/apache_log_parser.rb +15 -12
  12. data/lib/log_sense/apache_report_shaper.rb +309 -0
  13. data/lib/log_sense/emitter.rb +55 -553
  14. data/lib/log_sense/ip_locator.rb +24 -12
  15. data/lib/log_sense/options_checker.rb +24 -0
  16. data/lib/log_sense/options_parser.rb +81 -51
  17. data/lib/log_sense/rails_aggregator.rb +69 -0
  18. data/lib/log_sense/rails_log_parser.rb +82 -68
  19. data/lib/log_sense/rails_report_shaper.rb +183 -0
  20. data/lib/log_sense/report_shaper.rb +105 -0
  21. data/lib/log_sense/templates/_cdn_links.html.erb +11 -0
  22. data/lib/log_sense/templates/_command_invocation.html.erb +4 -0
  23. data/lib/log_sense/templates/_log_structure.html.erb +7 -1
  24. data/lib/log_sense/templates/_output_table.html.erb +6 -2
  25. data/lib/log_sense/templates/_rails.css.erb +7 -0
  26. data/lib/log_sense/templates/_summary.html.erb +9 -7
  27. data/lib/log_sense/templates/_summary.txt.erb +2 -2
  28. data/lib/log_sense/templates/{rails.html.erb → report_html.erb} +19 -37
  29. data/lib/log_sense/templates/{apache.txt.erb → report_txt.erb} +1 -1
  30. data/lib/log_sense/version.rb +1 -1
  31. data/lib/log_sense.rb +19 -9
  32. data/log_sense.gemspec +1 -1
  33. data/{apache-screenshot.png → screenshots/apache-screenshot.png} +0 -0
  34. data/screenshots/rails-screenshot.png +0 -0
  35. metadata +17 -11
  36. data/lib/log_sense/apache_data_cruncher.rb +0 -147
  37. data/lib/log_sense/rails_data_cruncher.rb +0 -141
  38. data/lib/log_sense/templates/apache.html.erb +0 -115
  39. data/lib/log_sense/templates/rails.txt.erb +0 -22
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.5.2
4
+ version: 1.6.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: 2022-08-18 00:00:00.000000000 Z
11
+ date: 2022-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: browser
@@ -124,20 +124,25 @@ files:
124
124
  - LICENSE.txt
125
125
  - README.org
126
126
  - Rakefile
127
- - apache-screenshot.png
128
127
  - bin/console
129
128
  - bin/setup
130
129
  - exe/log_sense
131
130
  - ip_locations/dbip-country-lite.sqlite3
132
131
  - lib/log_sense.rb
133
- - lib/log_sense/apache_data_cruncher.rb
132
+ - lib/log_sense/aggregator.rb
133
+ - lib/log_sense/apache_aggregator.rb
134
134
  - lib/log_sense/apache_log_line_parser.rb
135
135
  - lib/log_sense/apache_log_parser.rb
136
+ - lib/log_sense/apache_report_shaper.rb
136
137
  - lib/log_sense/emitter.rb
137
138
  - lib/log_sense/ip_locator.rb
139
+ - lib/log_sense/options_checker.rb
138
140
  - lib/log_sense/options_parser.rb
139
- - lib/log_sense/rails_data_cruncher.rb
141
+ - lib/log_sense/rails_aggregator.rb
140
142
  - lib/log_sense/rails_log_parser.rb
143
+ - lib/log_sense/rails_report_shaper.rb
144
+ - lib/log_sense/report_shaper.rb
145
+ - lib/log_sense/templates/_cdn_links.html.erb
141
146
  - lib/log_sense/templates/_command_invocation.html.erb
142
147
  - lib/log_sense/templates/_command_invocation.txt.erb
143
148
  - lib/log_sense/templates/_log_structure.html.erb
@@ -146,25 +151,26 @@ files:
146
151
  - lib/log_sense/templates/_output_table.txt.erb
147
152
  - lib/log_sense/templates/_performance.html.erb
148
153
  - lib/log_sense/templates/_performance.txt.erb
154
+ - lib/log_sense/templates/_rails.css.erb
149
155
  - lib/log_sense/templates/_report_data.html.erb
150
156
  - lib/log_sense/templates/_stylesheet.css
151
157
  - lib/log_sense/templates/_summary.html.erb
152
158
  - lib/log_sense/templates/_summary.txt.erb
153
159
  - lib/log_sense/templates/_warning.txt.erb
154
- - lib/log_sense/templates/apache.html.erb
155
- - lib/log_sense/templates/apache.txt.erb
156
- - lib/log_sense/templates/rails.html.erb
157
- - lib/log_sense/templates/rails.txt.erb
160
+ - lib/log_sense/templates/report_html.erb
161
+ - lib/log_sense/templates/report_txt.erb
158
162
  - lib/log_sense/version.rb
159
163
  - log_sense.gemspec
160
164
  - sample_logs/safety-critical_org.log
161
165
  - sample_logs/spmbook_com.log
162
- homepage: https://github.com/shair-tech/log_sense/log_sense
166
+ - screenshots/apache-screenshot.png
167
+ - screenshots/rails-screenshot.png
168
+ homepage: https://github.com/shair-tech/log_sense/
163
169
  licenses:
164
170
  - MIT
165
171
  metadata:
166
172
  allowed_push_host: https://rubygems.org/
167
- homepage_uri: https://github.com/shair-tech/log_sense/log_sense
173
+ homepage_uri: https://github.com/shair-tech/log_sense/
168
174
  source_code_uri: https://github.com/shair-tech/log_sense/
169
175
  changelog_uri: https://github.com/shair-tech/log_sense/blob/main/CHANGELOG.org
170
176
  post_install_message:
@@ -1,147 +0,0 @@
1
- module LogSense
2
- module ApacheDataCruncher
3
- #
4
- # take a sqlite3 database and analyze data
5
- #
6
- # @ variables are automatically put in the returned data
7
- #
8
-
9
- def self.crunch db, options = { limit: 900 }
10
- first_day_s = db.execute "SELECT datetime from LogLine order by datetime limit 1"
11
- last_day_s = db.execute "SELECT datetime from LogLine order by datetime desc limit 1"
12
-
13
- # make first and last day into dates or nil
14
- @first_day = first_day_s&.first&.first ? Date.parse(first_day_s[0][0]) : nil
15
- @last_day = last_day_s&.first&.first ? Date.parse(last_day_s[0][0]) : nil
16
-
17
- @total_days = 0
18
- @total_days = (@last_day - @first_day).to_i if @first_day && @last_day
19
-
20
- @source_files = db.execute 'SELECT distinct(source_file) from LogLine'
21
-
22
- @log_size = db.execute 'SELECT count(datetime) from LogLine'
23
- @log_size = @log_size[0][0]
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]
30
-
31
- @first_day_requested = options[:from_date]
32
- @last_day_requested = options[:to_date]
33
-
34
- @first_day_in_analysis = date_intersect options[:from_date], @first_day, :max
35
- @last_day_in_analysis = date_intersect options[:to_date], @last_day, :min
36
-
37
- @total_days_in_analysis = 0
38
- if @first_day_in_analysis && @last_day_in_analysis
39
- @total_days_in_analysis = (@last_day_in_analysis - @first_day_in_analysis).to_i
40
- end
41
-
42
- #
43
- # generate the where clause corresponding to the command line options to filter data
44
- #
45
- filter = [
46
- (options[:from_date] ? "date(datetime) >= '#{options[:from_date]}'" : nil),
47
- (options[:to_date] ? "date(datetime) <= '#{options[:to_date]}'" : nil),
48
- (options[:only_crawlers] ? 'bot == 1' : nil),
49
- (options[:ignore_crawlers] ? 'bot == 0' : nil),
50
- (options[:no_selfpolls] ? "ip != '::1'" : nil),
51
- 'true'
52
- ].compact.join " and "
53
-
54
- mega = 1024 * 1024
55
- giga = mega * 1024
56
- tera = giga * 1024
57
-
58
- # in alternative to sum(size)
59
- human_readable_size = <<-EOS
60
- CASE
61
- WHEN sum(size) < 1024 THEN sum(size) || ' B'
62
- WHEN sum(size) >= 1024 AND sum(size) < (#{mega}) THEN ROUND((CAST(sum(size) AS REAL) / 1024), 2) || ' KB'
63
- WHEN sum(size) >= (#{mega}) AND sum(size) < (#{giga}) THEN ROUND((CAST(sum(size) AS REAL) / (#{mega})), 2) || ' MB'
64
- WHEN sum(size) >= (#{giga}) AND sum(size) < (#{tera}) THEN ROUND((CAST(sum(size) AS REAL) / (#{giga})), 2) || ' GB'
65
- WHEN sum(size) >= (#{tera}) THEN ROUND((CAST(sum(size) AS REAL) / (#{tera})), 2) || ' TB'
66
- END AS size
67
- EOS
68
-
69
- human_readable_day = <<-EOS
70
- case cast (strftime('%w', datetime) as integer)
71
- when 0 then 'Sunday'
72
- when 1 then 'Monday'
73
- when 2 then 'Tuesday'
74
- when 3 then 'Wednesday'
75
- when 4 then 'Thursday'
76
- when 5 then 'Friday'
77
- else 'Saturday'
78
- end as dow
79
- EOS
80
-
81
- @total_hits = db.execute "SELECT count(datetime) 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
-
87
- @total_size = db.execute "SELECT #{human_readable_size} from LogLine where #{filter}"
88
- @total_size = @total_size[0][0]
89
-
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)"
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)"
92
-
93
- good_statuses = "(status like '2%' or status like '3%')"
94
- bad_statuses = "(status like '4%' or status like '5%')"
95
- html_page = "(extension like '.htm%')"
96
- non_html_page = "(extension not like '.htm%')"
97
-
98
- @most_requested_pages = db.execute "SELECT path, count(path), count(distinct(unique_visitor)), #{human_readable_size}, status from LogLine where #{good_statuses} and #{html_page} and #{filter} group by path order by count(path) desc limit #{options[:limit]}"
99
- @most_requested_resources = db.execute "SELECT path, count(path), count(distinct(unique_visitor)), #{human_readable_size}, status from LogLine where #{good_statuses} and #{non_html_page} and #{filter} group by path order by count(path) desc limit #{options[:limit]}"
100
-
101
- @missed_pages = db.execute "SELECT path, count(path), count(distinct(unique_visitor)), status from LogLine where #{bad_statuses} and #{html_page} and #{filter} group by path order by count(path) desc limit #{options[:limit]}"
102
- @missed_resources = db.execute "SELECT path, count(path), count(distinct(unique_visitor)), status from LogLine where #{bad_statuses} and #{filter} group by path order by count(path) desc limit #{options[:limit]}"
103
-
104
- @missed_pages_by_ip = db.execute "SELECT ip, path, status from LogLine where #{bad_statuses} and #{html_page} and #{filter} limit #{options[:limit]}"
105
- @missed_resources_by_ip = db.execute "SELECT ip, path, status from LogLine where #{bad_statuses} and #{filter} limit #{options[:limit]}"
106
-
107
- @statuses = db.execute "SELECT status, count(status) from LogLine where #{filter} group by status order by status"
108
-
109
- @by_day_4xx = db.execute "SELECT date(datetime), count(datetime) from LogLine where substr(status, 1,1) == '4' and #{filter} group by date(datetime)"
110
- @by_day_3xx = db.execute "SELECT date(datetime), count(datetime) from LogLine where substr(status, 1,1) == '3' and #{filter} group by date(datetime)"
111
- @by_day_2xx = db.execute "SELECT date(datetime), count(datetime) from LogLine where substr(status, 1,1) == '2' and #{filter} group by date(datetime)"
112
-
113
- @statuses_by_day = (@by_day_2xx + @by_day_3xx + @by_day_4xx).group_by { |x| x[0] }.to_a.map { |x|
114
- [x[0], x[1].map { |y| y[1] }].flatten
115
- }
116
-
117
- @browsers = db.execute "SELECT browser, count(browser), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by browser order by count(browser) desc"
118
- @platforms = db.execute "SELECT platform, count(platform), count(distinct(unique_visitor)), #{human_readable_size} from LogLine where #{filter} group by platform order by count(platform) desc"
119
-
120
- @combined_platforms = db.execute "SELECT browser, platform, ip, count(datetime), #{human_readable_size} from LogLine where #{filter} group by browser, platform, ip order by count(datetime) desc limit #{options[:limit]}"
121
-
122
- @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]}"
123
-
124
- @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]}"
125
-
126
- @streaks = db.execute 'SELECT ip, substr(datetime, 1, 10), path from LogLine order by ip, datetime'
127
- data = {}
128
-
129
- instance_variables.each do |variable|
130
- var_as_symbol = variable.to_s[1..].to_sym
131
- data[var_as_symbol] = instance_variable_get(variable)
132
- end
133
-
134
- data
135
- end
136
-
137
- def self.date_intersect(date1, date2, method)
138
- if date1 && date2
139
- [date1, date2].send(method)
140
- elsif date1
141
- date1
142
- else
143
- date2
144
- end
145
- end
146
- end
147
- end
@@ -1,141 +0,0 @@
1
- module LogSense
2
- module RailsDataCruncher
3
-
4
- #
5
- # take a sqlite3 database and analyze data
6
- #
7
- # @ variables are automatically put in the returned data
8
- #
9
-
10
- def self.crunch db, options = { limit: 900 }
11
- first_day_s = db.execute "SELECT started_at from Event where started_at not NULL order by started_at limit 1"
12
- # we could use ended_at to cover the full activity period, but I prefer started_at
13
- # with the meaning that the monitor event initiation
14
- last_day_s = db.execute "SELECT started_at from Event order by started_at desc limit 1"
15
-
16
- # make first and last day into dates or nil
17
- # TODO: bug possible value here: [[nil]], which is not empty
18
- @first_day = first_day_s&.first&.first ? Date.parse(first_day_s[0][0]) : nil
19
- @last_day = last_day_s&.first&.first ? Date.parse(last_day_s[0][0]) : nil
20
-
21
- @total_days = 0
22
- @total_days = (@last_day - @first_day).to_i if @first_day && @last_day
23
-
24
- # TODO should also look into Error
25
- @source_files = db.execute "SELECT distinct(source_file) from Event"
26
-
27
- @log_size = db.execute "SELECT count(started_at) from Event"
28
- @log_size = @log_size[0][0]
29
-
30
- # TODO: I should make the names of events/size/etc uniform betweeen Apache and Rails Logs
31
- # SAME AS ABOVE
32
- @total_hits = @log_size
33
-
34
- # SAME AS ABOVE (but log_size is wrong in the case of Rails
35
- # logs, since an event takes more than one line)
36
- @events = db.execute "SELECT count(started_at) from Event"
37
- @events = @events[0][0]
38
-
39
- @first_day_requested = options[:from_date]
40
- @last_day_requested = options[:to_date]
41
-
42
- @first_day_in_analysis = date_intersect options[:from_date], @first_day, :max
43
- @last_day_in_analysis = date_intersect options[:to_date], @last_day, :min
44
-
45
- @total_days_in_analysis = 0
46
- if @first_day_in_analysis and @last_day_in_analysis
47
- @total_days_in_analysis = (@last_day_in_analysis - @first_day_in_analysis).to_i
48
- end
49
-
50
- #
51
- # generate the where clause corresponding to the command line options to filter data
52
- #
53
- filter = [
54
- (options[:from_date] ? "date(started_at) >= '#{options[:from_date]}'" : nil),
55
- (options[:to_date] ? "date(started_at) <= '#{options[:to_date]}'" : nil),
56
- "true"
57
- ].compact.join " and "
58
-
59
- mega = 1024 * 1024
60
- giga = mega * 1024
61
- tera = giga * 1024
62
-
63
- # in alternative to sum(size)
64
- human_readable_size = <<-EOS
65
- CASE
66
- WHEN sum(size) < 1024 THEN sum(size) || ' B'
67
- WHEN sum(size) >= 1024 AND sum(size) < (#{mega}) THEN ROUND((CAST(sum(size) AS REAL) / 1024), 2) || ' KB'
68
- WHEN sum(size) >= (#{mega}) AND sum(size) < (#{giga}) THEN ROUND((CAST(sum(size) AS REAL) / (#{mega})), 2) || ' MB'
69
- WHEN sum(size) >= (#{giga}) AND sum(size) < (#{tera}) THEN ROUND((CAST(sum(size) AS REAL) / (#{giga})), 2) || ' GB'
70
- WHEN sum(size) >= (#{tera}) THEN ROUND((CAST(sum(size) AS REAL) / (#{tera})), 2) || ' TB'
71
- END AS size
72
- EOS
73
-
74
- human_readable_day = <<-EOS
75
- case cast (strftime('%w', started_at) as integer)
76
- when 0 then 'Sunday'
77
- when 1 then 'Monday'
78
- when 2 then 'Tuesday'
79
- when 3 then 'Wednesday'
80
- when 4 then 'Thursday'
81
- when 5 then 'Friday'
82
- else 'Saturday'
83
- end as dow
84
- EOS
85
-
86
- @total_events = db.execute "SELECT count(started_at) from Event where #{filter}"
87
-
88
- @total_unique_visits = db.execute "SELECT count(distinct(unique_visitor)) from Event where #{filter}"
89
- @total_unique_visits = @total_unique_visits[0][0]
90
-
91
- @daily_distribution = db.execute "SELECT date(started_at), #{human_readable_day}, count(started_at) from Event where #{filter} group by date(started_at)"
92
- @time_distribution = db.execute "SELECT strftime('%H', started_at), count(started_at) from Event where #{filter} group by strftime('%H', started_at)"
93
-
94
- @statuses = db.execute "SELECT status, count(status) from Event where #{filter} group by status order by status"
95
-
96
- @by_day_5xx = db.execute "SELECT date(started_at), count(started_at) from Event where substr(status, 1,1) == '5' and #{filter} group by date(started_at)"
97
- @by_day_4xx = db.execute "SELECT date(started_at), count(started_at) from Event where substr(status, 1,1) == '4' and #{filter} group by date(started_at)"
98
- @by_day_3xx = db.execute "SELECT date(started_at), count(started_at) from Event where substr(status, 1,1) == '3' and #{filter} group by date(started_at)"
99
- @by_day_2xx = db.execute "SELECT date(started_at), count(started_at) from Event where substr(status, 1,1) == '2' and #{filter} group by date(started_at)"
100
-
101
- @statuses_by_day = (@by_day_2xx + @by_day_3xx + @by_day_4xx + @by_day_5xx).group_by { |x| x[0] }.to_a.map { |x|
102
- [x[0], x[1].map { |y| y[1] }].flatten
103
- }
104
-
105
- @ips = db.execute "SELECT ip, count(ip) from Event where #{filter} group by ip order by count(ip) desc limit #{options[:limit]}"
106
-
107
- @streaks = db.execute 'SELECT ip, substr(started_at, 1, 10), url from Event order by ip, started_at'
108
- data = {}
109
-
110
- @performance = db.execute "SELECT distinct(controller), count(controller), printf(\"%.2f\", min(duration_total_ms)), printf(\"%.2f\", avg(duration_total_ms)), printf(\"%.2f\", max(duration_total_ms)) from Event group by controller order by controller"
111
-
112
- @fatal = db.execute ("SELECT strftime(\"%Y-%m-%d %H:%M\", started_at), ip, url, error.description, event.log_id FROM Event JOIN Error ON event.log_id == error.log_id WHERE exit_status == 'F'") || [[]]
113
-
114
- @internal_server_error = (db.execute "SELECT strftime(\"%Y-%m-%d %H:%M\", started_at), status, ip, url, error.description, event.log_id FROM Event JOIN Error ON event.log_id == error.log_id WHERE status is 500") || [[]]
115
-
116
- @error = (db.execute "SELECT log_id, context, description, count(log_id) from Error GROUP BY description") || [[]]
117
-
118
- data = {}
119
- self.instance_variables.each do |variable|
120
- var_as_symbol = variable.to_s[1..-1].to_sym
121
- data[var_as_symbol] = eval(variable.to_s)
122
- end
123
- data
124
- end
125
-
126
- private
127
-
128
- def self.date_intersect date1, date2, method
129
- if date1 and date2
130
- [date1, date2].send(method)
131
- elsif date1
132
- date1
133
- else
134
- date2
135
- end
136
- end
137
-
138
-
139
- end
140
- end
141
-
@@ -1,115 +0,0 @@
1
- <!doctype html>
2
- <html class="no-js" lang="en">
3
- <head>
4
- <title>
5
- <%= options[:title] || "Log Sense: #{data[:filenames].empty? ? "stdin" : data[:filenames].join(", ")}" %>
6
- </title>
7
-
8
- <meta charset="utf-8" />
9
- <meta http-equiv="x-ua-compatible" content="ie=edge">
10
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
11
-
12
- <meta name="author" content="Shair.Tech">
13
- <meta name="description" content="Analysis of <%= data[:filenames].join(', ') %>">
14
-
15
- <link rel="preconnect" href="https://fonts.googleapis.com">
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>
29
-
30
- <style>
31
- <%= render "stylesheet.css" %>
32
- </style>
33
- </head>
34
-
35
- <body>
36
- <div class="off-canvas-wrapper">
37
- <div class="off-canvas position-left" id="offCanvas" data-off-canvas>
38
- <%= render "navigation.html.erb",
39
- menus: Emitter::apache_report_specification.map { |x| x[:title] } %>
40
- </div>
41
- <div class="off-canvas-content" data-off-canvas-content>
42
- <button id="toggle-button" type="button" data-toggle="offCanvas">
43
- &#9776;
44
- </button>
45
-
46
- <section class="main-section grid-container fluid">
47
- <h1><%= options[:title] || "Log Sense Apache Log Report" %></h1>
48
-
49
- <p><b>Input File(s):</b> <%= data[:filenames].empty? ? "stdin" : data[:filenames].join(", ") %></p>
50
-
51
- <div class="grid-x grid-padding-x">
52
- <article class="small-12 large-6 cell">
53
- <h2 id="<%= Emitter::slugify "Summary" %>">Summary</h2>
54
- <%= render "summary.html.erb", data: data %>
55
- </article>
56
-
57
- <article class="small-12 large-6 cell">
58
- <h2 id="<%= Emitter::slugify "Summary" %>">Log Structure</h2>
59
- <%= render "log_structure.html.erb", data: data %>
60
- </article>
61
-
62
- <% @reports.each_with_index do |report, index| %>
63
- <article class="<%= report[:col] || "small-12 large-6" %> cell">
64
- <h2 id="<%= Emitter::slugify report[:title] %>"><%= report[:title] %></h2>
65
-
66
- <%= render "report_data.html.erb", report: report, index: index %>
67
- <% if report[:vega_spec] %>
68
- <div id="<%= "plot-#{index}" %>" class="plot-canvas">
69
- </div>
70
- <script>
71
- plot_spec_<%= index %> = Object.assign(
72
- <%= report[:vega_spec].to_json %>,
73
- { "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
74
- width: "container",
75
- description: "<%= report[:title] %>",
76
- data: {
77
- values: data_<%= index %>
78
- },
79
- });
80
- vegaEmbed('#<%= "plot-#{index}"%>', plot_spec_<%= index %>);
81
- </script>
82
- <% end %>
83
-
84
- <%= render "output_table.html.erb", report: report, index: index %>
85
- </article>
86
- <% end %>
87
-
88
- <article class="small-12 large-6 cell">
89
- <h2 id="<%= Emitter::slugify "Command Invocation" %>">Command Invocation</h2>
90
- <%= render "command_invocation.html.erb", data: data, options: options %>
91
- </article>
92
-
93
- <article class="small-12 large-6 cell">
94
- <h2 id="<%= Emitter::slugify "Performance" %>">Performance</h2>
95
- <%= render "performance.html.erb", data: data %>
96
- </article>
97
- </div>
98
- </section>
99
- </div>
100
- </div>
101
-
102
- <script type="text/javascript" src="js/vendor/what-input.js"></script>
103
- <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
104
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.4/dist/js/foundation.min.js" crossorigin="anonymous"></script>
105
- <script>
106
- $(document).foundation();
107
-
108
- $(document).ready(function () {
109
- $('.data-table').each(function () {
110
- $(this).DataTable();
111
- });
112
- });
113
- </script>
114
- </body>
115
- </html>
@@ -1,22 +0,0 @@
1
- * Rails Log Analysis
2
-
3
- <%= render "warning.txt.erb" %>
4
-
5
- ** Summary
6
-
7
- <%= render "summary.txt.erb", data: data %>
8
-
9
- <% @reports.reject { |x| x[:report] == :html }.each do |report| %>
10
- ** <%= report[:title] %>
11
-
12
- <%= render "output_table.txt.erb", report: report, data: data %>
13
- <% end %>
14
-
15
- ** Command Invocation
16
-
17
- <%= render 'command_invocation.txt.erb', data: data %>
18
-
19
- ** Performance
20
-
21
- <%= render 'performance.txt.erb', data: data %>
22
-