logeater 0.5.0.pre → 0.5.4.pre
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 +5 -5
- data/lib/logeater/cli.rb +17 -1
- data/lib/logeater/event.rb +50 -0
- data/lib/logeater/eventfile.rb +10 -3
- data/lib/logeater/reader.rb +4 -0
- data/lib/logeater/version.rb +1 -1
- data/logeater.gemspec +1 -0
- data/test/data/single_heroku_request.log +15 -0
- data/test/integration/logeater_test.rb +6 -5
- data/test/unit/event_test.rb +19 -0
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cce28ddbf1036163a0b743d2bbc4ba5e93ce484015149e746a7542ab2ff61e94
|
4
|
+
data.tar.gz: 3260cbd40856778f7f28ca9ea0708b87bb35e74f4de8598cd173acc7fef5a2c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d960f461dcb370a50ab96083e2fae80eae3e24ee39870dbf5d82aed2a78197e87b59d21d307b1830cde3145a6d1c9916cdb747676f711df4aa20cd917b96415c
|
7
|
+
data.tar.gz: 751dc4a8370d1e441aece26e50ed1da36760bdc9501e83729dcd474e0af1be23b5181f260a68ff6b2ca889d8f238ab31e2276806b52b708a977c73c8fe378221
|
data/lib/logeater/cli.rb
CHANGED
@@ -78,7 +78,23 @@ module Logeater
|
|
78
78
|
started_all = Time.now
|
79
79
|
$stderr.puts " > \e[34mImporting events since \e[1m#{timestamp}\e[0m\n"
|
80
80
|
|
81
|
-
events = Logeater::Event.where(
|
81
|
+
events = Logeater::Event.where(ep_app: app).since(timestamp)
|
82
|
+
import_file Logeater::Eventfile.new(events), app
|
83
|
+
|
84
|
+
finished_all = Time.now
|
85
|
+
seconds = finished_all - started_all
|
86
|
+
minutes = (seconds / 60).to_i
|
87
|
+
seconds -= (minutes * 60)
|
88
|
+
$stderr.puts "Total time %d minutes, %.2f seconds" % [minutes, seconds]
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
desc "import_new APP", "imports unimported log events"
|
93
|
+
def import_new(app)
|
94
|
+
started_all = Time.now
|
95
|
+
$stderr.puts " > \e[34mImporting unprocessed events for \e[1m#{app}\e[0m\n"
|
96
|
+
|
97
|
+
events = Logeater::Event.where(ep_app: app).unprocessed
|
82
98
|
import_file Logeater::Eventfile.new(events), app
|
83
99
|
|
84
100
|
finished_all = Time.now
|
data/lib/logeater/event.rb
CHANGED
@@ -7,5 +7,55 @@ module Logeater
|
|
7
7
|
def self.since(timestamp)
|
8
8
|
where(arel_table[:received_at].gteq(timestamp))
|
9
9
|
end
|
10
|
+
|
11
|
+
def self.processed
|
12
|
+
where.not(processed_at: nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.unprocessed
|
16
|
+
where(processed_at: nil)
|
17
|
+
end
|
18
|
+
|
19
|
+
def logger_line
|
20
|
+
"#{severity_id}, [#{timestamp}] #{severity_label} -- : #{message}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def severity_id
|
24
|
+
SEVERITY[log_level][:id]
|
25
|
+
end
|
26
|
+
|
27
|
+
def severity_label
|
28
|
+
SEVERITY[log_level][:label]
|
29
|
+
end
|
30
|
+
|
31
|
+
def timestamp
|
32
|
+
emitted_at.strftime("%FT%T.%6N")
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def log_level
|
38
|
+
LOG_LEVELS.fetch(priority % 8)
|
39
|
+
end
|
40
|
+
|
41
|
+
LOG_LEVELS = {
|
42
|
+
0 => Logger::FATAL, # Emergency: system is unusable
|
43
|
+
1 => Logger::FATAL, # Alert: action must be taken immediately
|
44
|
+
2 => Logger::FATAL, # Critical: critical conditions
|
45
|
+
3 => Logger::ERROR, # Error: error conditions
|
46
|
+
4 => Logger::WARN, # Warning: warning conditions
|
47
|
+
5 => Logger::INFO, # Notice: normal but significant condition
|
48
|
+
6 => Logger::INFO, # Informational: informational messages
|
49
|
+
7 => Logger::DEBUG # Debug: debug-level messages
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
SEVERITY = {
|
53
|
+
Logger::FATAL => { id: "F", label: "FATAL" },
|
54
|
+
Logger::ERROR => { id: "E", label: "ERROR" },
|
55
|
+
Logger::WARN => { id: "W", label: "WARN" },
|
56
|
+
Logger::INFO => { id: "I", label: "INFO" },
|
57
|
+
Logger::DEBUG => { id: "D", label: "DEBUG" }
|
58
|
+
}.freeze
|
59
|
+
|
10
60
|
end
|
11
61
|
end
|
data/lib/logeater/eventfile.rb
CHANGED
@@ -6,14 +6,21 @@ module Logeater
|
|
6
6
|
|
7
7
|
def initialize(events)
|
8
8
|
@events = events
|
9
|
-
@filename = "events_#{
|
9
|
+
@filename = "events_#{timestamp}"
|
10
10
|
end
|
11
11
|
|
12
12
|
def each_line
|
13
|
-
events.
|
14
|
-
yield event
|
13
|
+
events.find_each do |event|
|
14
|
+
yield event.logger_line
|
15
|
+
event.touch :processed_at
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
19
|
+
private
|
20
|
+
|
21
|
+
def timestamp
|
22
|
+
@timestamp ||= Time.now.strftime "%Y%m%d%H%M%S.%L"
|
23
|
+
end
|
24
|
+
|
18
25
|
end
|
19
26
|
end
|
data/lib/logeater/reader.rb
CHANGED
data/lib/logeater/version.rb
CHANGED
data/logeater.gemspec
CHANGED
@@ -35,5 +35,6 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_development_dependency "minitest-reporters"
|
36
36
|
spec.add_development_dependency "minitest-reporters-turn_reporter"
|
37
37
|
spec.add_development_dependency "database_cleaner"
|
38
|
+
spec.add_development_dependency "heroku-log-parser"
|
38
39
|
|
39
40
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
243 <190>1 2018-04-06T19:14:09.352835+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] Started GET "/api/v1/holidays/2018-05-01-6189112395f7444881844271027c8c78" for 207.141.132.3 at 2018-04-06 19:14:09 +0000
|
2
|
+
179 <190>1 2018-04-06T19:14:09.354663+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] Processing by BuilderApi::HolidaysController#show as JSON
|
3
|
+
222 <190>1 2018-04-06T19:14:09.354762+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] Parameters: {"year"=>"2018", "month"=>"05", "day"=>"01", "id"=>"6189112395f7444881844271027c8c78"}
|
4
|
+
300 <190>1 2018-04-06T19:14:09.358456+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mUser Load (1.5ms)\x1B[0m \x1B[1m\x1B[34mSELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2\x1B[0m [["email", "user@example.com"], ["LIMIT", 1]]
|
5
|
+
424 <190>1 2018-04-06T19:14:09.360877+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mUserRole Load (1.4ms)\x1B[0m \x1B[1m\x1B[34mSELECT "user_roles".* FROM "user_roles" WHERE "user_roles"."user_id" = $1 AND "user_roles"."tenant_id" = $2 LIMIT $3\x1B[0m [["user_id", "ed80a088ddc04be891131be2394f56f5"], ["tenant_id", "9324b816dbc24bcebc087feef8c0b21e"], ["LIMIT", 1]]
|
6
|
+
288 <190>1 2018-04-06T19:14:09.363353+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mPublisher Load (1.2ms)\x1B[0m \x1B[1m\x1B[34mSELECT "publishers".* FROM "publishers" ORDER BY "publishers"."id" ASC LIMIT $1\x1B[0m [["LIMIT", 1]]
|
7
|
+
657 <190>1 2018-04-06T19:14:09.369707+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mHoliday Load (1.7ms)\x1B[0m \x1B[1m\x1B[34mSELECT "holidays".* FROM "holidays" INNER JOIN "lectionaries" ON "holidays"."lectionary_id" = "lectionaries"."id" LEFT OUTER JOIN "categories" ON "categories"."id" = "holidays"."category_id" WHERE "lectionaries"."publisher_id" = $1 AND "holidays"."id" = $2 ORDER BY "lectionaries"."name" ASC, "categories"."position", "holidays"."position" ASC LIMIT $3\x1B[0m [["publisher_id", "1211d48bb65e420f84a4174918638072"], ["id", "6189112395f7444881844271027c8c78"], ["LIMIT", 1]]
|
8
|
+
318 <190>1 2018-04-06T19:14:09.373153+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mTenant Load (1.2ms)\x1B[0m \x1B[1m\x1B[34mSELECT "tenants".* FROM "tenants" WHERE "tenants"."id" = $1 LIMIT $2\x1B[0m [["id", "9324b816dbc24bcebc087feef8c0b21e"], ["LIMIT", 1]]
|
9
|
+
330 <190>1 2018-04-06T19:14:09.375802+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mPublisher Load (1.2ms)\x1B[0m \x1B[1m\x1B[34mSELECT "publishers".* FROM "publishers" WHERE "publishers"."id" = $1 LIMIT $2\x1B[0m [["id", "1211d48bb65e420f84a4174918638072"], ["LIMIT", 1]]
|
10
|
+
363 <190>1 2018-04-06T19:14:09.379364+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[36mBible Load (1.3ms)\x1B[0m \x1B[1m\x1B[34mSELECT "bibles".* FROM "bibles" WHERE "bibles"."publisher_id" = $1 ORDER BY "bibles"."name" ASC LIMIT $2\x1B[0m [["publisher_id", "1211d48bb65e420f84a4174918638072"], ["LIMIT", 1]]
|
11
|
+
491 <190>1 2018-04-06T19:14:09.383904+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[1m\x1B[35m (1.5ms)\x1B[0m \x1B[1m\x1B[34mSELECT COUNT(*) AS "size", MAX("propers"."updated_at") AS timestamp FROM "propers" WHERE "propers"."holiday_id" = $1 AND "propers"."year" = $2 AND ("propers"."name" NOT IN ('Prayer of Thanksgiving', 'Proper Preface', 'Proper Preface (Jacobean)'))\x1B[0m [["holiday_id", "6189112395f7444881844271027c8c78"], ["year", 1]]
|
12
|
+
207 <190>1 2018-04-06T19:14:09.384229+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] Cache read: proper/base/query-e05e570da916b2c6b24a534e61906087-8-20171010021720928483
|
13
|
+
212 <190>1 2018-04-06T19:14:09.385266+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] Cache fetch_hit: proper/base/query-e05e570da916b2c6b24a534e61906087-8-20171010021720928483
|
14
|
+
157 <190>1 2018-04-06T19:14:09.387137+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] \x1B[33msize: \x1B[1m6.89 KB\x1B[0m
|
15
|
+
184 <190>1 2018-04-06T19:14:09.387366+00:00 host app web.2 - [www] [a0fe6527-2573-4c84-b3b7-6390939bc14e] [user@example.com] Completed 200 OK in 32ms (Views: 0.4ms | ActiveRecord: 10.9ms)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "test_helper"
|
2
|
+
require "heroku-log-parser"
|
2
3
|
|
3
4
|
class LogeaterTest < ActiveSupport::TestCase
|
4
5
|
attr_reader :logfile, :events
|
@@ -68,9 +69,9 @@ class LogeaterTest < ActiveSupport::TestCase
|
|
68
69
|
|
69
70
|
context "Given an app and a timestamp, import_since" do
|
70
71
|
setup do
|
71
|
-
log_sample = File.open(File.expand_path("./test/data/
|
72
|
+
log_sample = File.open(File.expand_path("./test/data/single_heroku_request.log"))
|
72
73
|
log_sample.lines do |line|
|
73
|
-
Logeater::Event.create(ep_app: app
|
74
|
+
Logeater::Event.create HerokuLogParser.parse(line).first.merge(ep_app: app)
|
74
75
|
end
|
75
76
|
@events = Logeater::Event.all
|
76
77
|
end
|
@@ -94,14 +95,14 @@ class LogeaterTest < ActiveSupport::TestCase
|
|
94
95
|
|
95
96
|
context "Given a partial request in one import and the rest in a subsiquent import, it" do
|
96
97
|
setup do
|
97
|
-
@lines = File.open(File.expand_path("./test/data/
|
98
|
+
@lines = File.open(File.expand_path("./test/data/single_heroku_request.log")).lines.to_a
|
98
99
|
end
|
99
100
|
|
100
101
|
should "save the request after having the full request" do
|
101
102
|
# The first two lines will not be enough to describe a complete request
|
102
103
|
# so Logeater will not be able to create a request from them...
|
103
104
|
@lines[0...2].each do |line|
|
104
|
-
Logeater::Event.create(ep_app: app
|
105
|
+
Logeater::Event.create HerokuLogParser.parse(line).first.merge(ep_app: app)
|
105
106
|
end
|
106
107
|
@events = Logeater::Event.all
|
107
108
|
assert_no_difference "Logeater::Request.count" do
|
@@ -111,7 +112,7 @@ class LogeaterTest < ActiveSupport::TestCase
|
|
111
112
|
# ...but if we later discover the rest of the lines that describe a complete
|
112
113
|
# request, it'd be good if Logeater could then recognize and import it.
|
113
114
|
@lines[2..-1].each do |line|
|
114
|
-
Logeater::Event.create(ep_app: app
|
115
|
+
Logeater::Event.create HerokuLogParser.parse(line).first.merge(ep_app: app)
|
115
116
|
end
|
116
117
|
@events = Logeater::Event.all
|
117
118
|
assert_difference "Logeater::Request.count", +1 do
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class EventTest < ActiveSupport::TestCase
|
4
|
+
attr_reader :event
|
5
|
+
|
6
|
+
context "Given an event formatted using RFC 5424" do
|
7
|
+
setup do
|
8
|
+
@event = Logeater::Event.new(
|
9
|
+
emitted_at: Time.new(2018, 4, 6, 10, 15, 30),
|
10
|
+
priority: 190,
|
11
|
+
message: "Started GET or something")
|
12
|
+
end
|
13
|
+
|
14
|
+
should "generate a parseable logger line" do
|
15
|
+
assert_match Logeater::Parser::LINE_MATCHER, event.logger_line
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logeater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Lail
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -252,6 +252,20 @@ dependencies:
|
|
252
252
|
- - ">="
|
253
253
|
- !ruby/object:Gem::Version
|
254
254
|
version: '0'
|
255
|
+
- !ruby/object:Gem::Dependency
|
256
|
+
name: heroku-log-parser
|
257
|
+
requirement: !ruby/object:Gem::Requirement
|
258
|
+
requirements:
|
259
|
+
- - ">="
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: '0'
|
262
|
+
type: :development
|
263
|
+
prerelease: false
|
264
|
+
version_requirements: !ruby/object:Gem::Requirement
|
265
|
+
requirements:
|
266
|
+
- - ">="
|
267
|
+
- !ruby/object:Gem::Version
|
268
|
+
version: '0'
|
255
269
|
description: Parses log files and imports them into a database
|
256
270
|
email:
|
257
271
|
- bob.lail@cph.org
|
@@ -290,10 +304,12 @@ files:
|
|
290
304
|
- lib/logeater/request.rb
|
291
305
|
- lib/logeater/version.rb
|
292
306
|
- logeater.gemspec
|
307
|
+
- test/data/single_heroku_request.log
|
293
308
|
- test/data/single_request.gz
|
294
309
|
- test/data/single_request.log
|
295
310
|
- test/integration/logeater_test.rb
|
296
311
|
- test/test_helper.rb
|
312
|
+
- test/unit/event_test.rb
|
297
313
|
- test/unit/params_parser_test.rb
|
298
314
|
- test/unit/parser_test.rb
|
299
315
|
homepage: ''
|
@@ -315,15 +331,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
315
331
|
- !ruby/object:Gem::Version
|
316
332
|
version: 1.3.1
|
317
333
|
requirements: []
|
318
|
-
|
319
|
-
rubygems_version: 2.6.11
|
334
|
+
rubygems_version: 3.0.3
|
320
335
|
signing_key:
|
321
336
|
specification_version: 4
|
322
337
|
summary: Parses log files and imports them into a database
|
323
338
|
test_files:
|
339
|
+
- test/data/single_heroku_request.log
|
324
340
|
- test/data/single_request.gz
|
325
341
|
- test/data/single_request.log
|
326
342
|
- test/integration/logeater_test.rb
|
327
343
|
- test/test_helper.rb
|
344
|
+
- test/unit/event_test.rb
|
328
345
|
- test/unit/params_parser_test.rb
|
329
346
|
- test/unit/parser_test.rb
|