applicaster-logger 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/lib/applicaster-logger.rb +0 -4
- data/lib/applicaster/logger.rb +7 -78
- data/lib/applicaster/logger/formatter.rb +22 -38
- data/lib/applicaster/logger/lograge/formatter.rb +19 -0
- data/lib/applicaster/logger/rack.rb +9 -0
- data/lib/applicaster/logger/rack/request_data.rb +25 -0
- data/lib/applicaster/logger/rack/thread_context.rb +17 -0
- data/lib/applicaster/logger/railtie.rb +59 -7
- data/lib/applicaster/logger/sidekiq.rb +59 -0
- data/lib/applicaster/logger/sidekiq/common_events.rb +42 -0
- data/lib/applicaster/logger/sidekiq/exception_logger.rb +22 -0
- data/lib/applicaster/logger/sidekiq/job_logger.rb +24 -0
- data/lib/applicaster/logger/sidekiq/middleware.rb +35 -0
- data/lib/applicaster/logger/sidekiq/thread_context.rb +16 -0
- data/lib/applicaster/logger/thread_context.rb +20 -0
- data/lib/applicaster/logger/version.rb +1 -1
- metadata +13 -6
- data/lib/applicaster/rack/request_data.rb +0 -24
- data/lib/applicaster/sidekiq/exception_logger.rb +0 -27
- data/lib/applicaster/sidekiq/job_logger.rb +0 -50
- data/lib/applicaster/sidekiq/middleware.rb +0 -109
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fd75cd4993d54d8fa1c251c31497786172a0923
|
4
|
+
data.tar.gz: 7132629f33b219958435d825b07d926ed002ff0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 724db349ba49009faab7624ac1bd482d6c486d28d52e75d5b993836cb2b50e37f7045d74889391d25e2bc3855ae3a28327a38def721c042313fdaa3bef0ee145
|
7
|
+
data.tar.gz: be26f72fe14fe0210ff25054444b241eb3e4651f60ec49e4df7bc51fe081414e4296b25a3eaa98cf979879f0250d83de8b4208f55534a44975edb5b4de8f0ee4
|
data/README.md
CHANGED
@@ -25,6 +25,8 @@ And then execute:
|
|
25
25
|
end
|
26
26
|
```
|
27
27
|
|
28
|
+
defaults to: `ENV["LOGSTASH_URI"].present?`
|
29
|
+
|
28
30
|
2. Configuring logstash output:
|
29
31
|
|
30
32
|
```ruby
|
@@ -33,9 +35,10 @@ And then execute:
|
|
33
35
|
config.applicaster_logger.logstash_config = { type: :redis }
|
34
36
|
end
|
35
37
|
```
|
36
|
-
|
38
|
+
|
39
|
+
defaults to: `{ uri: ENV["LOGSTASH_URI"] }` if `LOGSTASH_URI` is set or `{ type: :stdout }` otherwise
|
37
40
|
|
38
|
-
For
|
41
|
+
For available options see: https://github.com/dwbutler/logstash-logger#basic-usage
|
39
42
|
|
40
43
|
3. To set the application name:
|
41
44
|
|
data/lib/applicaster-logger.rb
CHANGED
data/lib/applicaster/logger.rb
CHANGED
@@ -1,84 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative "./logger/formatter"
|
2
|
+
require_relative "./logger/rack"
|
3
|
+
require_relative "./logger/railtie"
|
4
|
+
require_relative "./logger/sidekiq"
|
5
|
+
require_relative "./logger/thread_context"
|
6
|
+
require_relative "./logger/version"
|
7
|
+
|
4
8
|
|
5
9
|
module Applicaster
|
6
10
|
module Logger
|
7
|
-
# taken from https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/log_subscriber.rb
|
8
|
-
INTERNAL_PARAMS = %w(controller action format only_path)
|
9
|
-
|
10
|
-
def self.setup_lograge(app)
|
11
|
-
app.config.lograge.enabled = true
|
12
|
-
app.config.lograge.formatter = Lograge::Formatters::Logstash.new
|
13
|
-
app.config.lograge.custom_options = lambda do |event|
|
14
|
-
{
|
15
|
-
params: event.payload[:params].except(*INTERNAL_PARAMS).inspect,
|
16
|
-
facility: "action_controller",
|
17
|
-
custom_params: event.payload[:custom_params],
|
18
|
-
}
|
19
|
-
end
|
20
|
-
|
21
|
-
app.middleware.insert_after ActionDispatch::RequestId,
|
22
|
-
Applicaster::Rack::RequestData
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.setup_logger(app)
|
26
|
-
logstash_config = app.config.applicaster_logger.logstash_config
|
27
|
-
|
28
|
-
app.config.logger = LogStashLogger.new(logstash_config)
|
29
|
-
app.config.logger.level = app.config.applicaster_logger.level
|
30
|
-
app.config.logger.formatter =
|
31
|
-
Applicaster::Logger::Formatter.new(facility: "rails_logger")
|
32
|
-
|
33
|
-
if defined?(Delayed)
|
34
|
-
Delayed::Worker.logger = LogStashLogger.new(logstash_config)
|
35
|
-
Delayed::Worker.logger.level = app.config.applicaster_logger.level
|
36
|
-
Delayed::Worker.logger.formatter =
|
37
|
-
Applicaster::Logger::Formatter.new(facility: "delayed_job")
|
38
|
-
end
|
39
|
-
|
40
|
-
if defined?(::Sidekiq)
|
41
|
-
::Sidekiq.configure_server do |config|
|
42
|
-
config.error_handlers.delete_if { |h| h.is_a?(::Sidekiq::ExceptionHandler::Logger) }
|
43
|
-
::Sidekiq.error_handlers << Applicaster::Sidekiq::ExceptionLogger.new
|
44
|
-
|
45
|
-
if Gem::Version.new(::Sidekiq::VERSION) < Gem::Version.new("5.0")
|
46
|
-
require 'sidekiq/api'
|
47
|
-
config.server_middleware do |chain|
|
48
|
-
chain.remove ::Sidekiq::Middleware::Server::Logging
|
49
|
-
chain.add Applicaster::Sidekiq::Middleware::Server::LogstashLogging
|
50
|
-
end
|
51
|
-
else
|
52
|
-
logger = LogStashLogger.new(logstash_config)
|
53
|
-
logger.level = app.config.applicaster_logger.level
|
54
|
-
logger.formatter = Applicaster::Logger::Formatter.new(facility: "sidekiq")
|
55
|
-
::Sidekiq::Logging.logger = logger
|
56
|
-
::Sidekiq.options[:job_logger] = ::Applicaster::Sidekiq::JobLogger
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
if defined?(Sidetiq)
|
62
|
-
Sidetiq.logger = LogStashLogger.new(logstash_config)
|
63
|
-
Sidetiq.logger.level = app.config.applicaster_logger.level
|
64
|
-
Sidetiq.logger.formatter =
|
65
|
-
Applicaster::Logger::Formatter.new(facility: "sidetiq")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.with_thread_data(data)
|
70
|
-
old, Thread.current[:logger_thread_data] =
|
71
|
-
Thread.current[:logger_thread_data], data
|
72
|
-
|
73
|
-
yield
|
74
|
-
ensure
|
75
|
-
Thread.current[:logger_thread_data] = old
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.current_thread_data
|
79
|
-
Thread.current[:logger_thread_data] || {}
|
80
|
-
end
|
81
|
-
|
82
11
|
# Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
|
83
12
|
# breaking string encoding by splitting multibyte characters or breaking
|
84
13
|
# grapheme clusters ("perceptual characters") by truncating at combining
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'socket'
|
3
3
|
require 'time'
|
4
|
+
require 'logstash-logger'
|
4
5
|
|
5
6
|
module Applicaster
|
6
7
|
module Logger
|
@@ -12,53 +13,36 @@ module Applicaster
|
|
12
13
|
attr_accessor :default_fields
|
13
14
|
|
14
15
|
def initialize(options = {})
|
15
|
-
@default_fields = options.
|
16
|
+
@default_fields = options.with_indifferent_access
|
16
17
|
@datetime_format = nil
|
17
18
|
end
|
18
19
|
|
19
20
|
def call(severity, time, progname, message)
|
20
|
-
|
21
|
+
data =
|
22
|
+
default_fields.
|
23
|
+
deep_merge(message_to_data(message)).
|
24
|
+
merge({ severity: severity, host: HOST }).
|
25
|
+
deep_merge(Applicaster::Logger::ThreadContext.current)
|
26
|
+
|
27
|
+
event = LogStash::Event.new(data)
|
28
|
+
event.timestamp = time.utc.iso8601(3)
|
29
|
+
event.tags = current_tags
|
30
|
+
"#{event.to_json}\n"
|
21
31
|
end
|
22
32
|
|
23
33
|
protected
|
24
34
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
else
|
36
|
-
LogStash::Event.new(message: msg2str(data), "@timestamp" => time)
|
37
|
-
end
|
38
|
-
|
39
|
-
event[:severity] ||= severity
|
40
|
-
event[:host] ||= HOST
|
41
|
-
event[:application] ||= Rails.application.config.applicaster_logger.application_name
|
42
|
-
event[:environment] ||= Rails.env
|
43
|
-
event[:token] = ENV['LOGZIO_TOKEN'] if ENV['LOGZIO_TOKEN']
|
44
|
-
|
45
|
-
Applicaster::Logger.current_thread_data.each do |field, value|
|
46
|
-
event[field] = value
|
47
|
-
end
|
48
|
-
|
49
|
-
default_fields.each do |field, value|
|
50
|
-
event[field] ||= value
|
35
|
+
def message_to_data(message)
|
36
|
+
case message
|
37
|
+
when Hash
|
38
|
+
message.with_indifferent_access
|
39
|
+
when LogStash::Event
|
40
|
+
message.to_hash.with_indifferent_access
|
41
|
+
when /^\{/
|
42
|
+
JSON.parse(message).with_indifferent_access rescue { message: msg2str(message) }
|
43
|
+
else
|
44
|
+
{ message: msg2str(message) }.with_indifferent_access
|
51
45
|
end
|
52
|
-
|
53
|
-
current_tags.each do |tag|
|
54
|
-
event.tag(tag)
|
55
|
-
end
|
56
|
-
|
57
|
-
# In case Time#to_json has been overridden
|
58
|
-
if event.timestamp.is_a?(Time)
|
59
|
-
event.timestamp = event.timestamp.iso8601(3)
|
60
|
-
end
|
61
|
-
"#{event.to_json}\n"
|
62
46
|
end
|
63
47
|
end
|
64
48
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Applicaster
|
2
|
+
module Logger
|
3
|
+
module Lograge
|
4
|
+
class Formatter
|
5
|
+
def call(data)
|
6
|
+
{
|
7
|
+
message: message(data),
|
8
|
+
facility: "action_controller",
|
9
|
+
action_controller: data,
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def message(data)
|
14
|
+
"[#{data[:status]}] #{data[:method]} #{data[:path]} (#{data[:controller]}##{data[:action]})"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Applicaster
|
2
|
+
module Logger
|
3
|
+
module Rack
|
4
|
+
class RequestData
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
Applicaster::Logger::ThreadContext.add(request_data(env))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
|
14
|
+
def request_data(env)
|
15
|
+
request = ActionDispatch::Request.new(env)
|
16
|
+
{
|
17
|
+
request_uuid: request.uuid,
|
18
|
+
remote_ip: request.remote_ip,
|
19
|
+
request_host: request.host,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,22 +1,74 @@
|
|
1
1
|
require 'rails/railtie'
|
2
2
|
require 'lograge'
|
3
3
|
require 'logstash-logger'
|
4
|
+
require_relative "./lograge/formatter"
|
4
5
|
|
5
6
|
module Applicaster
|
6
7
|
module Logger
|
7
8
|
class Railtie < Rails::Railtie
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
DEFAULT_APP_NAME = Rails.application.class.parent.to_s.underscore
|
10
|
+
|
11
|
+
# taken from https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/log_subscriber.rb
|
12
|
+
INTERNAL_PARAMS = %w(controller action format only_path)
|
13
|
+
|
14
|
+
config.applicaster_logger = ActiveSupport::OrderedOptions.new.tap do |config|
|
15
|
+
uri = ENV["LOGSTASH_URI"]
|
16
|
+
config.enabled = uri.present?
|
17
|
+
config.level = ::Logger::INFO
|
18
|
+
config.application_name = ENV.fetch("LOG_APP_NAME") { DEFAULT_APP_NAME }
|
19
|
+
config.logstash_config = uri.present? ? { uri: uri } : { type: :stdout }
|
20
|
+
config.logzio_token = ENV['LOGZIO_TOKEN'].presence
|
21
|
+
end
|
22
|
+
|
23
|
+
initializer :applicaster_logger_rack do |app|
|
24
|
+
app.middleware.insert 0, Applicaster::Logger::Rack::ThreadContext
|
25
|
+
app.middleware.insert_after ActionDispatch::RequestId, Applicaster::Logger::Rack::RequestData
|
26
|
+
end
|
13
27
|
|
14
28
|
initializer :applicaster_logger_lograge, before: :lograge do |app|
|
15
|
-
|
29
|
+
setup_lograge(app) if app.config.applicaster_logger.enabled
|
16
30
|
end
|
17
31
|
|
18
32
|
initializer :applicaster_logger, before: :initialize_logger do |app|
|
19
|
-
|
33
|
+
setup_logger(app) if app.config.applicaster_logger.enabled
|
34
|
+
end
|
35
|
+
|
36
|
+
def setup_lograge(app)
|
37
|
+
app.config.lograge.enabled = true
|
38
|
+
app.config.lograge.formatter = Applicaster::Logger::Lograge::Formatter.new
|
39
|
+
app.config.lograge.custom_options = lambda do |event|
|
40
|
+
{
|
41
|
+
params: event.payload[:params].except(*INTERNAL_PARAMS).inspect,
|
42
|
+
custom_params: event.payload[:custom_params],
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup_logger(app)
|
48
|
+
config = app.config.applicaster_logger
|
49
|
+
app.config.logger = new_logger("rails_logger")
|
50
|
+
Applicaster::Logger::Sidekiq.setup(new_logger("sidekiq")) if defined?(::Sidekiq)
|
51
|
+
Sidetiq.logger = new_logger("sidetiq") if defined?(Sidetiq)
|
52
|
+
Delayed::Worker.logger = new_logger("delayed") if defined?(Delayed)
|
53
|
+
end
|
54
|
+
|
55
|
+
def new_logger(facility)
|
56
|
+
config = ::Rails.application.config.applicaster_logger
|
57
|
+
LogStashLogger.new(config.logstash_config).tap do |logger|
|
58
|
+
logger.level = config.level
|
59
|
+
|
60
|
+
logger.formatter = Applicaster::Logger::Formatter.new(
|
61
|
+
default_fields.merge({ facility: facility })
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_fields
|
67
|
+
config = ::Rails.application.config.applicaster_logger
|
68
|
+
{
|
69
|
+
application: config.application_name,
|
70
|
+
environment: Rails.env.to_s
|
71
|
+
}.merge(config.logzio_token ? { token: config.logzio_token } : {})
|
20
72
|
end
|
21
73
|
end
|
22
74
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative "./sidekiq/middleware"
|
2
|
+
require_relative "./sidekiq/job_logger"
|
3
|
+
require_relative "./sidekiq/exception_logger"
|
4
|
+
require_relative "./sidekiq/thread_context"
|
5
|
+
|
6
|
+
module Applicaster
|
7
|
+
module Logger
|
8
|
+
module Sidekiq
|
9
|
+
def self.setup(logger)
|
10
|
+
::Sidekiq::Logging.logger = logger
|
11
|
+
::Sidekiq.configure_server do |config|
|
12
|
+
config.error_handlers.delete_if { |h| h.is_a?(::Sidekiq::ExceptionHandler::Logger) }
|
13
|
+
::Sidekiq.error_handlers << Applicaster::Logger::Sidekiq::ExceptionLogger.new
|
14
|
+
|
15
|
+
config.server_middleware do |chain|
|
16
|
+
chain.prepend Applicaster::Logger::Sidekiq::ThreadContext
|
17
|
+
end
|
18
|
+
|
19
|
+
if Gem::Version.new(::Sidekiq::VERSION) < Gem::Version.new("5.0")
|
20
|
+
require 'sidekiq/api'
|
21
|
+
config.server_middleware do |chain|
|
22
|
+
chain.remove ::Sidekiq::Middleware::Server::Logging
|
23
|
+
chain.add Applicaster::Logger::Sidekiq::Middleware::Server::LogstashLogging
|
24
|
+
end
|
25
|
+
else
|
26
|
+
::Sidekiq.options[:job_logger] = ::Applicaster::Logger::Sidekiq::JobLogger
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def job_context(item, queue)
|
32
|
+
{
|
33
|
+
sidekiq: {
|
34
|
+
# job ID
|
35
|
+
jid: item['jid'],
|
36
|
+
pid: ::Process.pid,
|
37
|
+
# thread ID
|
38
|
+
tid: ::Thread.current.object_id.to_s(36),
|
39
|
+
# batch ID
|
40
|
+
bid: item['bid'],
|
41
|
+
# If we're using a wrapper class, like ActiveJob, use the "wrapped"
|
42
|
+
# attribute to expose the underlying thing.
|
43
|
+
class: (item['wrapped'] || item['class']).to_s,
|
44
|
+
queue: queue,
|
45
|
+
args: item['args'].inspect,
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def logger
|
51
|
+
::Sidekiq.logger
|
52
|
+
end
|
53
|
+
|
54
|
+
def item_class_name(item)
|
55
|
+
(item['wrapped'] || item['class']).to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Applicaster
|
2
|
+
module Logger
|
3
|
+
module Sidekiq
|
4
|
+
module CommonEvents
|
5
|
+
include Applicaster::Logger::Sidekiq
|
6
|
+
|
7
|
+
def start_event(item)
|
8
|
+
{
|
9
|
+
message: "Start: #{item_class_name(item)} JID-#{item['jid']}",
|
10
|
+
sidekiq: {
|
11
|
+
event: "start",
|
12
|
+
latency: ::Sidekiq::Job.new(item).latency,
|
13
|
+
}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def done_event(item, opts)
|
18
|
+
{
|
19
|
+
message: "Done: #{item_class_name(item)} JID-#{item['jid']}",
|
20
|
+
sidekiq: {
|
21
|
+
event: "done",
|
22
|
+
runtime: opts.fetch(:runtime),
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def exception_event(item, opts)
|
28
|
+
exception = opts.fetch(:exception)
|
29
|
+
{
|
30
|
+
message: "Fail: #{item_class_name(item)} JID-#{item['jid']}",
|
31
|
+
sidekiq: {
|
32
|
+
event: "exception",
|
33
|
+
runtime: opts.fetch(:runtime),
|
34
|
+
exception_class: exception.class.to_s,
|
35
|
+
exception_message: Applicaster::Logger.truncate_bytes(exception.message.to_s, 500),
|
36
|
+
}
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "./common_events"
|
2
|
+
|
3
|
+
module Applicaster
|
4
|
+
module Logger
|
5
|
+
module Sidekiq
|
6
|
+
class ExceptionLogger
|
7
|
+
include Applicaster::Logger::Sidekiq
|
8
|
+
include Applicaster::Logger::Sidekiq::CommonEvents
|
9
|
+
|
10
|
+
def call(exception, ctxHash)
|
11
|
+
item = ctxHash[:job]
|
12
|
+
queue = item[:queue]
|
13
|
+
|
14
|
+
logger.error(
|
15
|
+
job_context(item, queue).
|
16
|
+
deep_merge(exception_event(item, exception: exception, runtime: runtime))
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative "./common_events"
|
2
|
+
|
3
|
+
module Applicaster
|
4
|
+
module Sidekiq
|
5
|
+
class JobLogger
|
6
|
+
include Applicaster::Logger::Sidekiq
|
7
|
+
include Applicaster::Logger::Sidekiq::CommonEvents
|
8
|
+
|
9
|
+
def call(item, queue)
|
10
|
+
start = Time.now
|
11
|
+
logger.info(job_context(item, queue).deep_merge(start_event(item)))
|
12
|
+
yield
|
13
|
+
runtime = elapsed(start)
|
14
|
+
logger.info(job_context(item, queue).deep_merge(done_event(item, runtime: runtime)))
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def elapsed(start)
|
20
|
+
(Time.now - start).round(3)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "./common_events"
|
2
|
+
|
3
|
+
module Applicaster
|
4
|
+
module Logger
|
5
|
+
module Sidekiq
|
6
|
+
module Middleware
|
7
|
+
module Server
|
8
|
+
class LogstashLogging
|
9
|
+
include Applicaster::Logger::Sidekiq
|
10
|
+
include Applicaster::Logger::Sidekiq::CommonEvents
|
11
|
+
|
12
|
+
def call(worker, item, queue)
|
13
|
+
logger.info(start_event(item))
|
14
|
+
start = Time.now
|
15
|
+
yield # Pass the torch
|
16
|
+
runtime = elapsed(start)
|
17
|
+
logger.info(done_event(item, runtime: runtime))
|
18
|
+
rescue Exception => exception
|
19
|
+
runtime = elapsed(start)
|
20
|
+
logger.error(exception_event(item, exception: exception, runtime: runtime))
|
21
|
+
raise exception
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def elapsed(start)
|
27
|
+
return nil if start.nil?
|
28
|
+
(Time.now - start).to_f.round(3)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Applicaster
|
2
|
+
module Logger
|
3
|
+
module Sidekiq
|
4
|
+
class ThreadContext
|
5
|
+
include Applicaster::Logger::Sidekiq
|
6
|
+
|
7
|
+
def call(worker, item, queue)
|
8
|
+
Applicaster::Logger::ThreadContext.add(job_context(item, queue))
|
9
|
+
yield # Pass the torch
|
10
|
+
ensure
|
11
|
+
Applicaster::Logger::ThreadContext.clear!
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Applicaster
|
2
|
+
module Logger
|
3
|
+
module ThreadContext
|
4
|
+
module_function
|
5
|
+
KEY = self.name.to_sym
|
6
|
+
|
7
|
+
def current
|
8
|
+
Thread.current[KEY] ||= HashWithIndifferentAccess.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(hash)
|
12
|
+
current.merge!(hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear!
|
16
|
+
Thread.current[KEY] = HashWithIndifferentAccess.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: applicaster-logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vitaly Gorodetsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logstash-logger
|
@@ -82,12 +82,19 @@ files:
|
|
82
82
|
- lib/applicaster-logger.rb
|
83
83
|
- lib/applicaster/logger.rb
|
84
84
|
- lib/applicaster/logger/formatter.rb
|
85
|
+
- lib/applicaster/logger/lograge/formatter.rb
|
86
|
+
- lib/applicaster/logger/rack.rb
|
87
|
+
- lib/applicaster/logger/rack/request_data.rb
|
88
|
+
- lib/applicaster/logger/rack/thread_context.rb
|
85
89
|
- lib/applicaster/logger/railtie.rb
|
90
|
+
- lib/applicaster/logger/sidekiq.rb
|
91
|
+
- lib/applicaster/logger/sidekiq/common_events.rb
|
92
|
+
- lib/applicaster/logger/sidekiq/exception_logger.rb
|
93
|
+
- lib/applicaster/logger/sidekiq/job_logger.rb
|
94
|
+
- lib/applicaster/logger/sidekiq/middleware.rb
|
95
|
+
- lib/applicaster/logger/sidekiq/thread_context.rb
|
96
|
+
- lib/applicaster/logger/thread_context.rb
|
86
97
|
- lib/applicaster/logger/version.rb
|
87
|
-
- lib/applicaster/rack/request_data.rb
|
88
|
-
- lib/applicaster/sidekiq/exception_logger.rb
|
89
|
-
- lib/applicaster/sidekiq/job_logger.rb
|
90
|
-
- lib/applicaster/sidekiq/middleware.rb
|
91
98
|
homepage: ''
|
92
99
|
licenses:
|
93
100
|
- MIT
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Applicaster
|
2
|
-
module Rack
|
3
|
-
class RequestData
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
Applicaster::Logger.with_thread_data(request_data(env)) do
|
10
|
-
@app.call(env)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def request_data(env)
|
15
|
-
request = ActionDispatch::Request.new(env)
|
16
|
-
{
|
17
|
-
request_uuid: request.uuid,
|
18
|
-
remote_ip: request.remote_ip,
|
19
|
-
request_host: request.host,
|
20
|
-
}
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Applicaster
|
2
|
-
module Sidekiq
|
3
|
-
class ExceptionLogger
|
4
|
-
def call(exception, ctxHash)
|
5
|
-
item = ctxHash[:job]
|
6
|
-
queue = item[:queue]
|
7
|
-
|
8
|
-
event = log_context(item, queue).merge({
|
9
|
-
message: "Fail: #{item['class']} JID-#{item['jid']}",
|
10
|
-
exception_class: exception.class.to_s,
|
11
|
-
exception_message: Applicaster::Logger.truncate_bytes(exception.message.to_s, 500),
|
12
|
-
})
|
13
|
-
logger.info(event)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def log_context(item, queue)
|
19
|
-
Applicaster::Sidekiq::JobLogger.log_context(item, queue)
|
20
|
-
end
|
21
|
-
|
22
|
-
def logger
|
23
|
-
::Sidekiq.logger
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Applicaster
|
2
|
-
module Sidekiq
|
3
|
-
class JobLogger
|
4
|
-
def call(item, queue)
|
5
|
-
puts "JobLogger"
|
6
|
-
start = Time.now
|
7
|
-
event = log_context(item, queue).merge({
|
8
|
-
message: "Start: #{item['class']} JID-#{item['jid']}",
|
9
|
-
})
|
10
|
-
logger.info(event)
|
11
|
-
yield
|
12
|
-
event = log_context(item, queue).merge({
|
13
|
-
message: "Done: #{item['class']} JID-#{item['jid']}",
|
14
|
-
})
|
15
|
-
event[:sidekiq][:duration] = elapsed(start)
|
16
|
-
logger.info(event)
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def elapsed(start)
|
22
|
-
(Time.now - start).round(3)
|
23
|
-
end
|
24
|
-
|
25
|
-
def logger
|
26
|
-
::Sidekiq.logger
|
27
|
-
end
|
28
|
-
|
29
|
-
def log_context(item, queue)
|
30
|
-
self.class.log_context(item, queue)
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.sidekiq_context
|
34
|
-
::Thread.current[:sidekiq_context]
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.log_context(item, queue)
|
38
|
-
{
|
39
|
-
sidekiq: {
|
40
|
-
jid: item['jid'],
|
41
|
-
context: sidekiq_context,
|
42
|
-
worker: item['class'].to_s,
|
43
|
-
queue: queue,
|
44
|
-
args: item['args'].inspect,
|
45
|
-
}
|
46
|
-
}
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
module Applicaster
|
2
|
-
module Sidekiq
|
3
|
-
module Middleware
|
4
|
-
module Server
|
5
|
-
class LogstashLogging
|
6
|
-
|
7
|
-
def call(worker, item, queue)
|
8
|
-
::Sidekiq::Logging.with_context("#{worker.class.to_s} JID-#{item['jid']}") do
|
9
|
-
begin
|
10
|
-
logger.info(filter_fields({
|
11
|
-
message: "Start: #{worker.class.to_s} JID-#{item['jid']}",
|
12
|
-
jid: item['jid'],
|
13
|
-
pid: pid,
|
14
|
-
tid: tid,
|
15
|
-
context: context,
|
16
|
-
worker: worker.class.to_s,
|
17
|
-
queue: queue,
|
18
|
-
args: item['args'].inspect,
|
19
|
-
latency: ::Sidekiq::Job.new(::Sidekiq.dump_json(item)).latency,
|
20
|
-
memory: memory
|
21
|
-
}))
|
22
|
-
|
23
|
-
start = Time.now
|
24
|
-
|
25
|
-
yield # Pass the torch
|
26
|
-
|
27
|
-
logger.info(filter_fields({
|
28
|
-
message: "Done: #{worker.class.to_s} JID-#{item['jid']}",
|
29
|
-
jid: item['jid'],
|
30
|
-
pid: pid,
|
31
|
-
tid: tid,
|
32
|
-
context: context,
|
33
|
-
worker: worker.class.to_s,
|
34
|
-
queue: queue,
|
35
|
-
args: item['args'].inspect,
|
36
|
-
runtime: elapsed(start),
|
37
|
-
memory: memory
|
38
|
-
}))
|
39
|
-
rescue Exception => e
|
40
|
-
logger.error(filter_fields({
|
41
|
-
message: "Fail: #{worker.class.to_s} JID-#{item['jid']}",
|
42
|
-
jid: item['jid'],
|
43
|
-
pid: pid,
|
44
|
-
tid: tid,
|
45
|
-
context: context,
|
46
|
-
worker: worker.class.to_s,
|
47
|
-
queue: queue,
|
48
|
-
args: item['args'].inspect,
|
49
|
-
runtime: elapsed(start),
|
50
|
-
exception_class: e.class.to_s,
|
51
|
-
exception_message: Applicaster::Logger.truncate_bytes(e.message.to_s, 500),
|
52
|
-
memory: memory
|
53
|
-
}))
|
54
|
-
|
55
|
-
raise e
|
56
|
-
ensure
|
57
|
-
logger.device.close
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def logger
|
63
|
-
@logger ||=
|
64
|
-
begin
|
65
|
-
applicaster_logger = ::Rails.application.config.applicaster_logger
|
66
|
-
logger = LogStashLogger.new(applicaster_logger.logstash_config)
|
67
|
-
logger.level = applicaster_logger.sidekiq_log_level || applicaster_logger.level
|
68
|
-
logger.formatter = Applicaster::Logger::Formatter.new(facility: "sidekiq")
|
69
|
-
logger
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def pid
|
76
|
-
::Process.pid
|
77
|
-
end
|
78
|
-
|
79
|
-
def tid
|
80
|
-
::Thread.current.object_id.to_s(36)
|
81
|
-
end
|
82
|
-
|
83
|
-
def context
|
84
|
-
::Thread.current[:sidekiq_context]
|
85
|
-
end
|
86
|
-
|
87
|
-
def memory
|
88
|
-
`ps -o rss= -p #{::Process.pid}`.chomp.to_i
|
89
|
-
end
|
90
|
-
|
91
|
-
def elapsed(start)
|
92
|
-
return nil if start.nil?
|
93
|
-
(Time.now - start).to_f.round(3)
|
94
|
-
end
|
95
|
-
|
96
|
-
def filter_fields(data)
|
97
|
-
data.each do |key, val|
|
98
|
-
if val.is_a?(String) && val.length > 32766 # max message length
|
99
|
-
data[key] = "[omitted; length = #{val.length}, max = 32766]"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
data
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|