contextualized_logs 0.0.1.pre.alpha → 0.0.2.pre.alpha
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 +4 -4
- data/README.md +217 -155
- data/app/controllers/application_controller.rb +1 -0
- data/app/controllers/concerns/datadog_set_trace_details.rb +36 -0
- data/app/controllers/custom_context_controller.rb +17 -0
- data/app/controllers/model_controller.rb +1 -1
- data/app/models/model.rb +1 -1
- data/app/workers/model_worker.rb +2 -2
- data/config/initializers/contextualized_logs.rb +23 -0
- data/config/initializers/datadog.rb +17 -0
- data/config/initializers/sidekiq.rb +13 -13
- data/config/routes.rb +1 -0
- data/db/development.sqlite3 +0 -0
- data/lib/contextualized_logs.rb +25 -0
- data/lib/contextualized_logs/config.rb +27 -0
- data/lib/contextualized_logs/contextualized_controller.rb +54 -40
- data/lib/contextualized_logs/contextualized_logger.rb +74 -67
- data/lib/contextualized_logs/contextualized_model.rb +28 -24
- data/lib/contextualized_logs/contextualized_worker.rb +52 -18
- data/lib/contextualized_logs/current_context.rb +69 -67
- data/lib/contextualized_logs/sidekiq/middleware/client/inject_current_context.rb +3 -3
- data/lib/contextualized_logs/sidekiq/middleware/server/restore_current_context.rb +3 -3
- data/lib/contextualized_logs/version.rb +1 -1
- metadata +7 -2
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module DatadogSetTraceDetails
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
included do
|
|
5
|
+
before_action :set_trace_tags, unless: -> { Rails.env.development? }
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def set_trace_tags
|
|
9
|
+
begin
|
|
10
|
+
# set log context as (Datadog) APM trace tags
|
|
11
|
+
tracer = Datadog.configuration[:rails][:tracer]
|
|
12
|
+
span = tracer.active_span
|
|
13
|
+
dotted_hash(ContextualizedLogger.config.current_context).each do |k, v|
|
|
14
|
+
span.set_tag(k, v)
|
|
15
|
+
end
|
|
16
|
+
rescue StandardError => e
|
|
17
|
+
Rails.logger.info "Error setting trace tags #{e}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# {http: {uuid: 123}} => {http.uuid: 123}
|
|
24
|
+
# could be added to Hash
|
|
25
|
+
def dotted_hash(hash, recursive_key = "")
|
|
26
|
+
hash.each_with_object({}) do |(k, v), ret|
|
|
27
|
+
key = recursive_key + k.to_s
|
|
28
|
+
if v.is_a? Hash
|
|
29
|
+
ret.merge! dotted_hash(v, key + ".")
|
|
30
|
+
else
|
|
31
|
+
ret[key] = v
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class CustomContextController < ApplicationController
|
|
2
|
+
include ContextualizedLogs::ContextualizedController
|
|
3
|
+
|
|
4
|
+
def contextualize_request(controller)
|
|
5
|
+
super(controller)
|
|
6
|
+
|
|
7
|
+
ContextualizedLogs::ContextualizedController.current_context.custom_attributes = {
|
|
8
|
+
http: {
|
|
9
|
+
service: 'rails'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show
|
|
15
|
+
render json: {}, status: 200
|
|
16
|
+
end
|
|
17
|
+
end
|
data/app/models/model.rb
CHANGED
data/app/workers/model_worker.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
class ModelWorker
|
|
2
2
|
include Sidekiq::Worker
|
|
3
3
|
include ContextualizedLogs::ContextualizedWorker
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
contextualize_worker true
|
|
5
|
+
contextualize_model true
|
|
6
6
|
def self.contextualize_args(args)
|
|
7
7
|
{ model_id: args.first, action: args.last }
|
|
8
8
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'contextualized_logs'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
module ContextualizedLogs
|
|
5
|
+
configure do |config|
|
|
6
|
+
config.log_formatter = proc do |severity, timestamp, progname, msg|
|
|
7
|
+
log = ContextualizedLogger.default_formatter.call(severity, timestamp, progname, msg)
|
|
8
|
+
log = JSON.parse(log)
|
|
9
|
+
# set log <> APM trace correlation
|
|
10
|
+
datadog_correlation = Datadog.tracer.active_correlation
|
|
11
|
+
log.merge(
|
|
12
|
+
dd: {
|
|
13
|
+
trace_id: datadog_correlation.trace_id,
|
|
14
|
+
span_id: datadog_correlation.span_id
|
|
15
|
+
},
|
|
16
|
+
ddsource: ['ruby']
|
|
17
|
+
).to_json + "\n"
|
|
18
|
+
end
|
|
19
|
+
config.controller_default_contextualizer = proc do |controller|
|
|
20
|
+
ContextualizedController.default_contextualize_request(controller)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Datadog.configure do |c|
|
|
2
|
+
service_name = "#{Rails.env}-rails-app"
|
|
3
|
+
# https://docs.datadoghq.com/tracing/trace_search_and_analytics/?tab=ruby#automatic-configuration
|
|
4
|
+
# c.analytics_enabled = true
|
|
5
|
+
|
|
6
|
+
# add runtime metrics (runtime.ruby.class_count, runtime.ruby.thread_count, runtime.ruby.gc.*)
|
|
7
|
+
# http://gems.datadoghq.com/trace/docs/#Processing_Pipeline
|
|
8
|
+
# c.runtime_metrics_enabled = true
|
|
9
|
+
#c.tracer debug: true, hostname: '127.0.0.1', log: Logger.new(File.new('log/datadog.log', 'w+'))
|
|
10
|
+
c.tracer hostname: '127.0.0.1'
|
|
11
|
+
|
|
12
|
+
# c.use :rack, service_name: "#{service_name}-rack"
|
|
13
|
+
c.use :rails, service_name: service_name, database_service: "#{service_name}-active_record", analytics_enabled: false
|
|
14
|
+
# c.use :rake, service_name: "#{service_name}-rake"
|
|
15
|
+
# c.use :redis, service_name: "#{service_name}-redis"
|
|
16
|
+
# c.use :sidekiq, client_service_name: "#{service_name}-sidekiq-client", service_name: "#{service_name}-sidekiq-worker"
|
|
17
|
+
end
|
|
@@ -8,16 +8,16 @@ require 'sidekiq'
|
|
|
8
8
|
# require 'sidekiq/throttled'
|
|
9
9
|
# Sidekiq::Throttled.setup!
|
|
10
10
|
|
|
11
|
-
Sidekiq.configure_server do |config|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
Sidekiq.configure_client do |config|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end
|
|
11
|
+
# Sidekiq.configure_server do |config|
|
|
12
|
+
# config.redis = { url: 'redis://127.0.0.1:6379/1' }
|
|
13
|
+
# config.server_middleware do |chain|
|
|
14
|
+
# chain.add ContextualizedLogs::Sidekiq::Middleware::Server::RestoreCurrentContext
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# Sidekiq.configure_client do |config|
|
|
19
|
+
# config.redis = { url: 'redis://127.0.0.1:6379/1' }
|
|
20
|
+
# config.client_middleware do |chain|
|
|
21
|
+
# chain.add ContextualizedLogs::Sidekiq::Middleware::Client::InjectCurrentContext
|
|
22
|
+
# end
|
|
23
|
+
# end
|
data/config/routes.rb
CHANGED
data/db/development.sqlite3
CHANGED
|
Binary file
|
data/lib/contextualized_logs.rb
CHANGED
|
@@ -5,7 +5,32 @@ require "contextualized_logs/current_context"
|
|
|
5
5
|
require "contextualized_logs/sidekiq/middleware/client/inject_current_context"
|
|
6
6
|
require "contextualized_logs/sidekiq/middleware/server/restore_current_context"
|
|
7
7
|
require "contextualized_logs/contextualized_worker"
|
|
8
|
+
require "contextualized_logs/config"
|
|
8
9
|
|
|
9
10
|
module ContextualizedLogs
|
|
10
11
|
require "contextualized_logs/railtie" if defined?(Rails)
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
attr_accessor :config
|
|
15
|
+
|
|
16
|
+
def config
|
|
17
|
+
@config || Config.default
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def configure(&block)
|
|
21
|
+
config = Config.default
|
|
22
|
+
block.call(config)
|
|
23
|
+
self.config = config
|
|
24
|
+
ContextualizedLogger.formatter = config.log_formatter
|
|
25
|
+
ContextualizedController.default_contextualizer = config.controller_default_contextualizer
|
|
26
|
+
ContextualizedController.default_contextualize_model = config.controller_default_contextualize_model
|
|
27
|
+
ContextualizedWorker.default_contextualize_model = config.worker_default_contextualize_model
|
|
28
|
+
ContextualizedWorker.default_contextualize_worker = config.worker_default_contextualize_worker
|
|
29
|
+
if defined?(Rails) && Rails.logger.is_a?(ContextualizedLogger)
|
|
30
|
+
Rails.logger.formatter = config.log_formatter
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
11
34
|
end
|
|
35
|
+
|
|
36
|
+
ContextualizedLogs.configure { |config| } # set default configuration
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
module ContextualizedLogs
|
|
3
|
+
class Config
|
|
4
|
+
DEFAULT_CURRENT_CONTEXT = CurrentContext
|
|
5
|
+
DEFAULT_CONTROLLER_CONTEXTUALIZE_MODEL = false
|
|
6
|
+
DEFAULT_WORKER_CONTEXTUALIZE_MODEL = false
|
|
7
|
+
DEFAULT_WORKER_CONTEXTUALIZE_WORKER = true
|
|
8
|
+
|
|
9
|
+
attr_accessor :log_formatter
|
|
10
|
+
attr_accessor :current_context
|
|
11
|
+
attr_accessor :controller_default_contextualizer
|
|
12
|
+
attr_accessor :controller_default_contextualize_model
|
|
13
|
+
attr_accessor :worker_default_contextualize_worker
|
|
14
|
+
attr_accessor :worker_default_contextualize_model
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def default
|
|
18
|
+
config = new
|
|
19
|
+
config.current_context = DEFAULT_CURRENT_CONTEXT
|
|
20
|
+
config.controller_default_contextualize_model = DEFAULT_CONTROLLER_CONTEXTUALIZE_MODEL
|
|
21
|
+
config.worker_default_contextualize_worker = DEFAULT_WORKER_CONTEXTUALIZE_MODEL
|
|
22
|
+
config.worker_default_contextualize_model = DEFAULT_WORKER_CONTEXTUALIZE_WORKER
|
|
23
|
+
config
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,62 +1,76 @@
|
|
|
1
1
|
# https://github.com/rails/rails/pull/29180
|
|
2
2
|
require 'active_support'
|
|
3
|
-
|
|
3
|
+
require 'action_controller'
|
|
4
4
|
|
|
5
5
|
module ContextualizedLogs
|
|
6
6
|
module ContextualizedController
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
class << self
|
|
10
|
+
attr_accessor :default_contextualizer
|
|
11
|
+
attr_writer :default_contextualize_model
|
|
12
|
+
attr_writer :current_context
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
def current_context
|
|
15
|
+
@current_context || ContextualizedLogs.config.current_context
|
|
16
|
+
end
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
self.class.current_context.request_x_forwarded_for = request.x_forwarded_for
|
|
31
|
-
self.class.current_context.request_xhr = request.xhr? ? 'true' : 'false'
|
|
32
|
-
rescue StandardError => e
|
|
33
|
-
Rails.logger.dump_error('error setting context', e)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
18
|
+
def default_contextualize_model
|
|
19
|
+
@default_contextualize_model || ContextualizedLogs.config.controller_default_contextualize_model
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def included(base)
|
|
23
|
+
if !base.ancestors.include?(ActionController::Base) && !base.ancestors.include?(ActionController::API)
|
|
24
|
+
raise ArgumentError, "ContextualizedLogs::ContextualizedController can only be included in a ActionController::Base or ActionController::API"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
base.class_eval do
|
|
28
|
+
before_action do |controller|
|
|
29
|
+
contextualize_request(controller)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
if !base.ancestors.include?(ActionController::Base) && !base.ancestors.include?(ActionController::API)
|
|
39
|
-
raise ArgumentError, "ContextualizedLogs::ContextualizedController can only be included in a ActionController::Base or ActionController::API"
|
|
33
|
+
base.extend(ClassMethods)
|
|
40
34
|
end
|
|
41
35
|
|
|
42
|
-
|
|
36
|
+
def default_contextualize_request(controller)
|
|
37
|
+
# Rails.logger.debug "contextualize_request"
|
|
38
|
+
# store request && user info in CurrentContext ActiveSupport attribute
|
|
39
|
+
# which can then be read from anywhere
|
|
40
|
+
ContextualizedController.current_context.contextualize_model_enabled = controller.class.contextualize_model_enabled?
|
|
41
|
+
ContextualizedController.current_context.resource_name = "#{controller.class.name.downcase}_#{controller.action_name.downcase}" rescue nil
|
|
42
|
+
ContextualizedController.current_context.request_uuid = controller.request.uuid
|
|
43
|
+
ContextualizedController.current_context.request_origin = controller.request.origin
|
|
44
|
+
ContextualizedController.current_context.request_user_agent = controller.request.user_agent
|
|
45
|
+
ContextualizedController.current_context.request_referer = controller.request.referer&.to_s
|
|
46
|
+
ContextualizedController.current_context.request_ip = controller.request.ip
|
|
47
|
+
ContextualizedController.current_context.request_remote_ip = controller.request.remote_ip
|
|
48
|
+
ContextualizedController.current_context.request_remote_addr = controller.request.remote_addr
|
|
49
|
+
ContextualizedController.current_context.request_x_forwarded_for = controller.request.x_forwarded_for
|
|
50
|
+
ContextualizedController.current_context.request_xhr = controller.request.xhr? ? 'true' : 'false'
|
|
51
|
+
end
|
|
43
52
|
end
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
def contextualize_request(controller)
|
|
55
|
+
if ContextualizedController.default_contextualizer
|
|
56
|
+
ContextualizedController.default_contextualizer.call(controller)
|
|
57
|
+
return
|
|
48
58
|
end
|
|
49
59
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
ContextualizedController.default_contextualize_request(controller)
|
|
61
|
+
rescue StandardError => e
|
|
62
|
+
Rails.logger.dump_error('error setting controller context', e)
|
|
63
|
+
end
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
module ClassMethods
|
|
66
|
+
def contextualize_model_enabled?
|
|
67
|
+
return @contextualize_model_enabled if defined?(@contextualize_model_enabled)
|
|
68
|
+
|
|
69
|
+
ContextualizedController.default_contextualize_model
|
|
56
70
|
end
|
|
57
71
|
|
|
58
|
-
def
|
|
59
|
-
@
|
|
72
|
+
def contextualize_model(enable)
|
|
73
|
+
@contextualize_model_enabled = enable
|
|
60
74
|
end
|
|
61
75
|
end
|
|
62
76
|
end
|
|
@@ -6,9 +6,82 @@ module ContextualizedLogs
|
|
|
6
6
|
# support Rails.logger.dump('msg', hash)
|
|
7
7
|
|
|
8
8
|
class ContextualizedLogger < ActiveSupport::Logger
|
|
9
|
+
class << self
|
|
10
|
+
attr_accessor :formatter
|
|
11
|
+
attr_writer :current_context
|
|
12
|
+
|
|
13
|
+
def current_context
|
|
14
|
+
@current_context || ContextualizedLogs.config.current_context
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def default_formatter
|
|
18
|
+
proc do |severity, timestamp, progname, msg|
|
|
19
|
+
# format (and enrich) log in JSON format (-> )
|
|
20
|
+
# https://docs.hq.com/logs/processing/attributes_naming_convention/#source-code
|
|
21
|
+
# correlation = Datadog.tracer.active_correlation
|
|
22
|
+
data = {
|
|
23
|
+
# dd: {
|
|
24
|
+
# trace_id: correlation.trace_id,
|
|
25
|
+
# span_id: correlation.span_id
|
|
26
|
+
# },
|
|
27
|
+
# ddsource: ['ruby'],
|
|
28
|
+
syslog: { env: Rails.env, host: Socket.gethostname },
|
|
29
|
+
type: severity.to_s,
|
|
30
|
+
time: timestamp
|
|
31
|
+
}
|
|
32
|
+
data[:stack] = Kernel.caller.
|
|
33
|
+
map { |caller| caller.gsub(/#{Rails.root}/, '') }.
|
|
34
|
+
reject { |caller| caller.start_with?('/usr/local') || caller.include?('/shared/bundle/') || caller.start_with?('/Users/') }.
|
|
35
|
+
first(15)
|
|
36
|
+
data[:log_type] = 'log'
|
|
37
|
+
data.merge!(parse_msg(msg)) # parse message (string, hash, error, ...)
|
|
38
|
+
data.merge!(current_context.context) # merge current request context
|
|
39
|
+
data.to_json + "\n"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def parse_msg(msg)
|
|
46
|
+
data = {}
|
|
47
|
+
case msg
|
|
48
|
+
when Hash
|
|
49
|
+
# used by logger.dump(msg|error, attributes = {})
|
|
50
|
+
if msg.include?(:attributes)
|
|
51
|
+
# adding message as log attributes if is a hash
|
|
52
|
+
data.merge!(parse_error(msg[:msg]))
|
|
53
|
+
data[:attributes] = msg[:attributes]
|
|
54
|
+
else
|
|
55
|
+
data.merge!(parse_error(msg))
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
data.merge!(parse_error(msg))
|
|
59
|
+
end
|
|
60
|
+
data
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def parse_error(msg)
|
|
64
|
+
data = {}
|
|
65
|
+
case msg
|
|
66
|
+
when ::Exception
|
|
67
|
+
# format data to be interpreted as an error logs by
|
|
68
|
+
data[:error] = {
|
|
69
|
+
kind: msg.class.to_s,
|
|
70
|
+
message: msg.message,
|
|
71
|
+
stack: (msg.backtrace || []).join('; ')
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
data[:message] = msg.to_s
|
|
75
|
+
end
|
|
76
|
+
data
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
attr_accessor :formatter
|
|
81
|
+
|
|
9
82
|
def initialize(*args)
|
|
10
83
|
super(*args)
|
|
11
|
-
@formatter = formatter
|
|
84
|
+
@formatter = self.class.formatter || self.class.default_formatter
|
|
12
85
|
end
|
|
13
86
|
|
|
14
87
|
def dump(msg, attributes, severity = :info)
|
|
@@ -19,72 +92,6 @@ module ContextualizedLogs
|
|
|
19
92
|
def dump_error(msg, attributes)
|
|
20
93
|
dump(msg, attributes, :error)
|
|
21
94
|
end
|
|
22
|
-
|
|
23
|
-
def current_context
|
|
24
|
-
CurrentContext.context
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def formatter
|
|
28
|
-
Proc.new{|severity, timestamp, progname, msg|
|
|
29
|
-
# format (and enrich) log in JSON format (-> )
|
|
30
|
-
# https://docs.hq.com/logs/processing/attributes_naming_convention/#source-code
|
|
31
|
-
# correlation = Datadog.tracer.active_correlation
|
|
32
|
-
data = {
|
|
33
|
-
# dd: {
|
|
34
|
-
# trace_id: correlation.trace_id,
|
|
35
|
-
# span_id: correlation.span_id
|
|
36
|
-
# },
|
|
37
|
-
# ddsource: ['ruby'],
|
|
38
|
-
syslog: { env: Rails.env, host: Socket.gethostname },
|
|
39
|
-
type: severity.to_s,
|
|
40
|
-
time: timestamp
|
|
41
|
-
}
|
|
42
|
-
data[:stack] = Kernel.caller.
|
|
43
|
-
map { |caller| caller.gsub(/#{Rails.root}/, '') }.
|
|
44
|
-
reject { |caller| caller.start_with?('/usr/local') || caller.include?('/shared/bundle/') || caller.start_with?('/Users/') }.
|
|
45
|
-
first(15)
|
|
46
|
-
data[:log_type] = 'log'
|
|
47
|
-
data.merge!(parse_msg(msg)) # parse message (string, hash, error, ...)
|
|
48
|
-
data.merge!(current_context) # merge current request context
|
|
49
|
-
data.to_json + "\n"
|
|
50
|
-
}
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
private
|
|
54
|
-
|
|
55
|
-
def parse_msg(msg)
|
|
56
|
-
data = {}
|
|
57
|
-
case msg
|
|
58
|
-
when Hash
|
|
59
|
-
# used by logger.dump(msg|error, attributes = {})
|
|
60
|
-
if msg.include?(:attributes)
|
|
61
|
-
# adding message as log attributes if is a hash
|
|
62
|
-
data.merge!(parse_error(msg[:msg]))
|
|
63
|
-
data[:attributes] = msg[:attributes]
|
|
64
|
-
else
|
|
65
|
-
data.merge!(parse_error(msg))
|
|
66
|
-
end
|
|
67
|
-
else
|
|
68
|
-
data.merge!(parse_error(msg))
|
|
69
|
-
end
|
|
70
|
-
data
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def parse_error(msg)
|
|
74
|
-
data = {}
|
|
75
|
-
case msg
|
|
76
|
-
when ::Exception
|
|
77
|
-
# format data to be interpreted as an error logs by
|
|
78
|
-
data[:error] = {
|
|
79
|
-
kind: msg.class.to_s,
|
|
80
|
-
message: msg.message,
|
|
81
|
-
stack: (msg.backtrace || []).join('; ')
|
|
82
|
-
}
|
|
83
|
-
else
|
|
84
|
-
data[:message] = msg.to_s
|
|
85
|
-
end
|
|
86
|
-
data
|
|
87
|
-
end
|
|
88
95
|
end
|
|
89
96
|
|
|
90
97
|
end
|