log_sense 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f2fcc8402c27ec959854e3cd032e9e75693e538d3ca0879de3f4cf0b6aae9c5
4
- data.tar.gz: e2530ff646c436ca88e674a698bf71876f2e62bc0b59f20ebbc4e38fdd787830
3
+ metadata.gz: 45cf68bf2165554a6392a9277c121952e05dd9a283fe59b881ef957f3682920e
4
+ data.tar.gz: 99ded91c60080ffbfda3e60f05ee4b058e215286adfccdb2a727a50d2c7d0467
5
5
  SHA512:
6
- metadata.gz: 30932a09a0a0d0717c4e5caa9a579bb60a3a930dc144dc318029945e0364e71e5ddf5d5868ccf758a11d3ed5f73f5d690f482521e3475f1f16a5a041fa4abd8a
7
- data.tar.gz: da8ac76f281cf9f8c67805621fe098d1480889f2fb5a55a378d1ffae3383c1913d572c28c9a68c876fb710b4e8bc3213b157c51cdf008f1505c320ef5fabedd0
6
+ metadata.gz: 45674016ae3c3110584e967dd60166391a07b1401186428e7e949c012bfc883686110e86afeec5450e03d34a8b7831c6bbc1d1b9393215808a2d1feafcd6422b
7
+ data.tar.gz: a4e9b7bf983d23ba4e8ac744621e34c5b83eee45076cf165ba9eb856d5687d47191ab048be6fed0ca4316448c84d8f80e1b7daedb518d94a90b52b7f94ee2077
data/.gitignore CHANGED
@@ -6,5 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
9
+ node_modules
10
10
  *~
@@ -34,6 +34,8 @@ module LogSense
34
34
  end
35
35
 
36
36
  def self.locate_ip ip, db
37
+ return if not ip
38
+
37
39
  ip_n = IPAddr.new(ip).to_i
38
40
  res = db.execute "SELECT * FROM ip_location where from_ip_n <= #{ip_n} order by from_ip_n desc limit 1"
39
41
  begin
@@ -22,7 +22,7 @@ module LogSense
22
22
  args[:input_file] = n
23
23
  end
24
24
 
25
- opts.on("-tFORMAT", "--output-format=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. See below for available formats") do |n|
26
26
  args[:output_format] = n
27
27
  end
28
28
 
@@ -74,6 +74,7 @@ module LogSense
74
74
  components = templates.map { |x| File.basename(x).split "." }.group_by { |x| x[0] }
75
75
  components.each do |k, vs|
76
76
  puts "#{k} parsing can produce the following outputs:"
77
+ puts " - sqlite"
77
78
  vs.each do |v|
78
79
  puts " - #{v[1]}"
79
80
  end
@@ -15,8 +15,8 @@ module LogSense
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[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])
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
20
 
21
21
  @total_days = 0
22
22
  if @first_day and @last_day
@@ -100,6 +100,8 @@ module LogSense
100
100
 
101
101
  @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"
102
102
 
103
+ @fatal = db.execute "SELECT strftime(\"%Y-%m-%d %H:%M\", started_at), ip, url, log_id FROM Event WHERE exit_status == 'F'"
104
+
103
105
  data = {}
104
106
  self.instance_variables.each do |variable|
105
107
  var_as_symbol = variable.to_s[1..-1].to_sym
@@ -8,6 +8,7 @@ module LogSense
8
8
  db = SQLite3::Database.new ":memory:"
9
9
  db.execute 'CREATE TABLE IF NOT EXISTS Event(
10
10
  id INTEGER PRIMARY KEY AUTOINCREMENT,
11
+ exit_status TEXT,
11
12
  started_at TEXT,
12
13
  ended_at TEXT,
13
14
  log_id TEXT,
@@ -20,10 +21,12 @@ module LogSense
20
21
  duration_total_ms FLOAT,
21
22
  duration_views_ms FLOAT,
22
23
  duration_ar_ms FLOAT,
23
- allocations INTEGER
24
+ allocations INTEGER,
25
+ comment TEXT
24
26
  )'
25
27
 
26
28
  ins = db.prepare("insert into Event(
29
+ exit_status,
27
30
  started_at,
28
31
  ended_at,
29
32
  log_id,
@@ -36,8 +39,10 @@ module LogSense
36
39
  duration_total_ms,
37
40
  duration_views_ms,
38
41
  duration_ar_ms,
39
- allocations)
40
- values (#{Array.new(13, '?').join(', ')})")
42
+ allocations,
43
+ comment
44
+ )
45
+ values (#{Array.new(15, '?').join(', ')})")
41
46
 
42
47
  # requests in the log might be interleaved.
43
48
  #
@@ -61,7 +66,7 @@ module LogSense
61
66
 
62
67
  File.readlines(filename).each do |line|
63
68
  # We discard LOG_LEVEL != 'I'
64
- next if line[0] != 'I'
69
+ next if line[0] != 'I' and line[0] != 'F'
65
70
 
66
71
  data = self.match_and_process_start line
67
72
  if data
@@ -77,6 +82,37 @@ module LogSense
77
82
  next
78
83
  end
79
84
 
85
+ data = self.match_and_process_fatal line
86
+ if data
87
+ id = data[:log_id]
88
+ # it might as well be that the first event started before
89
+ # the log. With this, we make sure we add only events whose
90
+ # start was logged and parsed
91
+ if pending[id]
92
+ event = data.merge (pending[id] || {})
93
+
94
+ ins.execute(
95
+ event[:exit_status],
96
+ event[:started_at],
97
+ event[:ended_at],
98
+ event[:log_id],
99
+ event[:ip],
100
+ "#{DateTime.parse(event[:started_at]).strftime("%Y-%m-%d")} #{event[:ip]}",
101
+ event[:url],
102
+ event[:controller],
103
+ event[:html_verb],
104
+ event[:status],
105
+ event[:duration_total_ms],
106
+ event[:duration_views_ms],
107
+ event[:duration_ar_ms],
108
+ event[:allocations],
109
+ event[:comment]
110
+ )
111
+
112
+ pending.delete(id)
113
+ end
114
+ end
115
+
80
116
  data = self.match_and_process_completed line
81
117
  if data
82
118
  id = data[:log_id]
@@ -88,6 +124,40 @@ module LogSense
88
124
  event = data.merge (pending[id] || {})
89
125
 
90
126
  ins.execute(
127
+ event[:exit_status],
128
+ event[:started_at],
129
+ event[:ended_at],
130
+ event[:log_id],
131
+ event[:ip],
132
+ "#{DateTime.parse(event[:started_at]).strftime("%Y-%m-%d")} #{event[:ip]}",
133
+ event[:url],
134
+ event[:controller],
135
+ event[:html_verb],
136
+ event[:status],
137
+ event[:duration_total_ms],
138
+ event[:duration_views_ms],
139
+ event[:duration_ar_ms],
140
+ event[:allocations],
141
+ event[:comment]
142
+ )
143
+
144
+ pending.delete(id)
145
+ end
146
+ end
147
+
148
+
149
+ data = self.match_and_process_completed_no_alloc line
150
+ if data
151
+ id = data[:log_id]
152
+
153
+ # it might as well be that the first event started before
154
+ # the log. With this, we make sure we add only events whose
155
+ # start was logged and parsed
156
+ if pending[id]
157
+ event = data.merge (pending[id] || {})
158
+
159
+ ins.execute(
160
+ event[:exit_status],
91
161
  event[:started_at],
92
162
  event[:ended_at],
93
163
  event[:log_id],
@@ -100,12 +170,14 @@ module LogSense
100
170
  event[:duration_total_ms],
101
171
  event[:duration_views_ms],
102
172
  event[:duration_ar_ms],
103
- event[:allocations]
173
+ event[:allocations],
174
+ event[:comment]
104
175
  )
105
176
 
106
177
  pending.delete(id)
107
178
  end
108
179
  end
180
+
109
181
  end
110
182
 
111
183
  db
@@ -141,9 +213,10 @@ module LogSense
141
213
  COMPLETED_REGEXP = /I, \[#{TIMESTAMP} #[0-9]+\] INFO -- : \[#{ID}\] Completed #{STATUS} [^ ]+ in (?<total>#{MSECS})ms \(Views: (?<views>#{MSECS})ms \| ActiveRecord: (?<arec>#{MSECS})ms \| Allocations: (?<alloc>[0-9]+)\)/
142
214
 
143
215
  def self.match_and_process_completed line
144
- matchdata = COMPLETED_REGEXP.match line
216
+ matchdata = (COMPLETED_REGEXP.match line)
145
217
  if matchdata
146
218
  {
219
+ exit_status: "I",
147
220
  ended_at: matchdata[:timestamp],
148
221
  log_id: matchdata[:id],
149
222
  status: matchdata[:status],
@@ -151,12 +224,36 @@ module LogSense
151
224
  duration_views_ms: matchdata[:views],
152
225
  duration_ar_ms: matchdata[:arec],
153
226
  allocations: matchdata[:alloc],
227
+ comment: ""
228
+ }
229
+ else
230
+ nil
231
+ end
232
+ end
233
+
234
+ # I, [2021-12-09T16:53:52.657727 #2735058] INFO -- : [0064e403-9eb2-439d-8fe1-a334c86f5532] Completed 200 OK in 13ms (Views: 11.1ms | ActiveRecord: 1.2ms)
235
+ COMPLETED_NO_ALLOC_REGEXP = /I, \[#{TIMESTAMP} #[0-9]+\] INFO -- : \[#{ID}\] Completed #{STATUS} [^ ]+ in (?<total>#{MSECS})ms \(Views: (?<views>#{MSECS})ms \| ActiveRecord: (?<arec>#{MSECS})ms\)/
236
+
237
+ def self.match_and_process_completed_no_alloc line
238
+ matchdata = (COMPLETED_NO_ALLOC_REGEXP.match line)
239
+ if matchdata
240
+ {
241
+ exit_status: "I",
242
+ ended_at: matchdata[:timestamp],
243
+ log_id: matchdata[:id],
244
+ status: matchdata[:status],
245
+ duration_total_ms: matchdata[:total],
246
+ duration_views_ms: matchdata[:views],
247
+ duration_ar_ms: matchdata[:arec],
248
+ allocations: -1,
249
+ comment: ""
154
250
  }
155
251
  else
156
252
  nil
157
253
  end
158
254
  end
159
255
 
256
+
160
257
  # I, [2021-10-19T08:16:34.345162 #10477] INFO -- : [67103c0d-455d-4fe8-951e-87e97628cb66] Processing by PeopleController#show as HTML
161
258
  PROCESSING_REGEXP = /I, \[#{TIMESTAMP} #[0-9]+\] INFO -- : \[#{ID}\] Processing by (?<controller>[^ ]+) as/
162
259
 
@@ -172,6 +269,25 @@ module LogSense
172
269
  end
173
270
  end
174
271
 
272
+ # F, [2021-12-04T00:34:05.838973 #2735058] FATAL -- : [3a16162e-a6a5-435e-a9d8-c4df5dc0f728]
273
+ # F, [2021-12-04T00:34:05.839157 #2735058] FATAL -- : [3a16162e-a6a5-435e-a9d8-c4df5dc0f728] ActionController::RoutingError (No route matches [GET] "/wp/wp-includes/wlwmanifest.xml"):
274
+ # F, [2021-12-04T00:34:05.839209 #2735058] FATAL -- : [3a16162e-a6a5-435e-a9d8-c4df5dc0f728]
275
+ # F, [2021-12-04T00:34:05.839269 #2735058] FATAL -- : [3a16162e-a6a5-435e-a9d8-c4df5dc0f728] actionpack (5.2.4.4) lib/action_dispatch/middleware/debug_exceptions.rb:65:in `call'
276
+ FATAL_REGEXP = /F, \[#{TIMESTAMP} #[0-9]+\] FATAL -- : \[#{ID}\] (?<comment>.*)$/
277
+
278
+ def self.match_and_process_fatal line
279
+ matchdata = FATAL_REGEXP.match line
280
+ if matchdata
281
+ {
282
+ exit_status: "F",
283
+ log_id: matchdata[:id],
284
+ comment: matchdata[:comment]
285
+ }
286
+ else
287
+ nil
288
+ end
289
+ end
290
+
175
291
  end
176
292
 
177
293
  end
@@ -25,7 +25,7 @@
25
25
  </tr>
26
26
  <tr>
27
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>
28
+ <td class="avg-hits-per-unique-visits"><%= data[:total_unique_visits] != 0 ? data[:total_hits] / data[:total_unique_visits] : "N/A" %></td>
29
29
  </tr>
30
30
  <tr>
31
31
  <th class="tx">Tx</th>
@@ -4,7 +4,7 @@
4
4
  ["Days", data[:total_days_in_analysis] ],
5
5
  ["Events", data[:events] ],
6
6
  ["Unique Visits", data[:total_unique_visits] ],
7
- ["Avg. Events per Visit", data[:events] / data[:total_unique_visits] ]
7
+ ["Avg. Events per Visit", data[:total_unique_visits] != 0 ? data[:events] / data[:total_unique_visits] : "N/A" ]
8
8
  ]
9
9
  table
10
10
  %>
@@ -44,6 +44,12 @@ table.align_column(4, :right)
44
44
  table
45
45
  %>
46
46
 
47
+ ** Fatal Events
48
+
49
+ <%= table = Terminal::Table.new headings: ['Date', 'IP', 'URL', 'Log ID'], rows: @data[:fatal]
50
+ table
51
+ %>
52
+
47
53
  ** Command Invocation
48
54
 
49
55
  <%= render "command_invocation.txt.erb", data: data %>
@@ -1,3 +1,3 @@
1
1
  module LogSense
2
- VERSION = "1.0.7"
2
+ VERSION = "1.0.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: log_sense
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adolfo Villafiorita