logeater 0.5.0.pre → 0.5.4.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|