sapience 0.1.1 → 0.1.2
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/.simplecov +6 -2
- data/.travis.yml +8 -25
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +5 -5
- data/README.md +146 -15
- data/Rakefile +2 -1
- data/config/default.yml +29 -0
- data/dev-entrypoint.sh +10 -0
- data/docker-compose.yml +42 -0
- data/lib/sapience/appender/datadog.rb +100 -0
- data/lib/sapience/appender/file.rb +11 -22
- data/lib/sapience/appender/sentry.rb +61 -55
- data/lib/sapience/appender/wrapper.rb +5 -4
- data/lib/sapience/base.rb +21 -13
- data/lib/sapience/config_loader.rb +66 -0
- data/lib/sapience/configuration/grape.rb +9 -0
- data/lib/sapience/configuration.rb +32 -22
- data/lib/sapience/core_ext/hash.rb +25 -0
- data/lib/sapience/core_ext/thread.rb +2 -2
- data/lib/sapience/extensions/action_cable/tagged_logger_proxy.rb +6 -0
- data/lib/sapience/extensions/action_controller/live.rb +6 -0
- data/lib/sapience/extensions/action_controller/log_subscriber.rb +127 -0
- data/lib/sapience/extensions/action_controller/log_subscriber_processing.rb +24 -0
- data/lib/sapience/extensions/action_dispatch/debug_exceptions.rb +11 -0
- data/lib/sapience/extensions/action_view/log_subscriber.rb +9 -0
- data/lib/sapience/extensions/action_view/streaming_template_renderer.rb +11 -0
- data/lib/sapience/extensions/active_job/logging.rb +14 -0
- data/lib/sapience/extensions/active_model_serializers/logging.rb +14 -0
- data/lib/sapience/extensions/active_record/log_subscriber.rb +35 -0
- data/lib/sapience/extensions/grape/middleware/logging.rb +91 -0
- data/lib/sapience/extensions/grape/timings.rb +25 -0
- data/lib/sapience/extensions/rails/rack/logger.rb +11 -0
- data/lib/sapience/extensions/rails/rack/logger_info_as_debug.rb +24 -0
- data/lib/sapience/formatters/color.rb +3 -3
- data/lib/sapience/formatters/default.rb +1 -1
- data/lib/sapience/grape.rb +25 -0
- data/lib/sapience/log.rb +8 -6
- data/lib/sapience/loggable.rb +19 -17
- data/lib/sapience/logger.rb +46 -126
- data/lib/sapience/rails.rb +65 -8
- data/lib/sapience/sapience.rb +74 -73
- data/lib/sapience/subscriber.rb +5 -1
- data/lib/sapience/version.rb +1 -1
- data/lib/sapience.rb +4 -1
- data/sapience.gemspec +7 -4
- data/test_app/Gemfile +5 -1
- data/test_app/Rakefile +5 -1
- data/test_app/app/controllers/posts_controller.rb +12 -11
- data/test_app/config/application.rb +0 -1
- data/test_app/spec/controllers/posts_controller_spec.rb +1 -1
- data/test_app/spec/fixtures/sapience.yml +14 -0
- data/test_app/spec/helpers/posts_helper_spec.rb +1 -1
- data/test_app/spec/integration/sapience_spec.rb +14 -0
- data/test_app/spec/models/post_spec.rb +1 -1
- data/test_app/spec/models/user_spec.rb +1 -1
- data/test_app/spec/rails_helper.rb +15 -0
- data/test_app/spec/requests/posts_spec.rb +1 -1
- data/test_app/spec/routing/posts_routing_spec.rb +8 -10
- data/test_app/spec/spec_helper.rb +0 -44
- metadata +76 -11
- data/lib/sapience/appender/statsd.rb +0 -68
@@ -0,0 +1,91 @@
|
|
1
|
+
require "grape/middleware/base"
|
2
|
+
|
3
|
+
module Sapience
|
4
|
+
module Extensions
|
5
|
+
module Grape
|
6
|
+
module Middleware
|
7
|
+
class Logging < ::Grape::Middleware::Base
|
8
|
+
ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
|
9
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
10
|
+
Grape::Timings.append_db_runtime(event)
|
11
|
+
end if defined?(ActiveRecord)
|
12
|
+
|
13
|
+
def initialize(app, options = {})
|
14
|
+
super
|
15
|
+
@logger = @options[:logger]
|
16
|
+
end
|
17
|
+
|
18
|
+
def before
|
19
|
+
reset_db_runtime
|
20
|
+
start_time
|
21
|
+
end
|
22
|
+
|
23
|
+
def after
|
24
|
+
stop_time
|
25
|
+
@logger.info(parameters)
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def call!(env)
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def response
|
36
|
+
super
|
37
|
+
rescue
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def parameters # rubocop:disable AbcSize
|
42
|
+
{
|
43
|
+
status: (response.nil? ? "fail" : response.status),
|
44
|
+
time: {
|
45
|
+
total: total_runtime,
|
46
|
+
db: db_runtime,
|
47
|
+
view: view_runtime,
|
48
|
+
},
|
49
|
+
method: request.request_method,
|
50
|
+
path: request.path,
|
51
|
+
params: request.params,
|
52
|
+
host: request.host,
|
53
|
+
ip: (request.env["HTTP_X_FORWARDED_FOR"] || request.env["REMOTE_ADDR"]),
|
54
|
+
ua: request.env["HTTP_USER_AGENT"],
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def request
|
61
|
+
@request ||= ::Rack::Request.new(env)
|
62
|
+
end
|
63
|
+
|
64
|
+
def total_runtime
|
65
|
+
((stop_time - start_time) * 1000).round(2)
|
66
|
+
end
|
67
|
+
|
68
|
+
def view_runtime
|
69
|
+
total_runtime - db_runtime
|
70
|
+
end
|
71
|
+
|
72
|
+
def db_runtime
|
73
|
+
Grape::Timings.db_runtime.round(2)
|
74
|
+
end
|
75
|
+
|
76
|
+
def reset_db_runtime
|
77
|
+
Grape::Timings.reset_db_runtime
|
78
|
+
end
|
79
|
+
|
80
|
+
def start_time
|
81
|
+
@start_time ||= Time.now
|
82
|
+
end
|
83
|
+
|
84
|
+
def stop_time
|
85
|
+
@stop_time ||= Time.now
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sapience
|
2
|
+
module Extensions
|
3
|
+
module Grape
|
4
|
+
module Timings
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def db_runtime=(value)
|
8
|
+
Thread.current[:grape_db_runtime] = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def db_runtime
|
12
|
+
Thread.current[:grape_db_runtime] ||= 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset_db_runtime
|
16
|
+
self.db_runtime = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def append_db_runtime(event)
|
20
|
+
self.db_runtime += event.duration
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Replace rack started message with a semantic equivalent
|
2
|
+
class Rails::Rack::Logger # rubocop:disable ClassAndModuleChildren
|
3
|
+
def started_request_message(request)
|
4
|
+
{
|
5
|
+
message: "Started",
|
6
|
+
method: request.request_method,
|
7
|
+
path: request.filtered_path,
|
8
|
+
ip: request.ip,
|
9
|
+
}
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Drop rack Started message to debug level message
|
2
|
+
class Rails::Rack::Logger # rubocop:disable ClassAndModuleChildren
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
module Extensions
|
7
|
+
def info(*args, &block)
|
8
|
+
debug(*args, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def info?
|
12
|
+
debug?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def logger
|
17
|
+
@logger ||= begin
|
18
|
+
logger = Sapience["Rails"]
|
19
|
+
logger.extend(Extensions)
|
20
|
+
logger
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Load AwesomePrint if available
|
2
2
|
begin
|
3
3
|
require "awesome_print"
|
4
|
-
rescue LoadError
|
4
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
5
5
|
end
|
6
6
|
|
7
7
|
module Sapience
|
@@ -33,7 +33,7 @@ module Sapience
|
|
33
33
|
message << "#{level_color}#{log.level_to_s}#{colors::CLEAR} [#{log.process_info}]"
|
34
34
|
|
35
35
|
# Tags
|
36
|
-
message << " " << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(" ") if log.tags && (log.tags.size > 0)
|
36
|
+
message << " " << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(" ") if log.tags && (log.tags.size > 0) # rubocop:disable LineLength
|
37
37
|
|
38
38
|
# Duration
|
39
39
|
message << " (#{colors::BOLD}#{log.duration_human}#{colors::CLEAR})" if log.duration
|
@@ -49,7 +49,7 @@ module Sapience
|
|
49
49
|
payload = log.payload
|
50
50
|
message << " -- " <<
|
51
51
|
if defined?(AwesomePrint) && payload.respond_to?(:ai)
|
52
|
-
payload.ai(@ai_options) rescue payload.inspect
|
52
|
+
payload.ai(@ai_options) rescue payload.inspect # rubocop:disable RescueModifier
|
53
53
|
else
|
54
54
|
payload.inspect
|
55
55
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "sapience"
|
2
|
+
require "sapience/extensions/grape/timings"
|
3
|
+
require "sapience/extensions/grape/middleware/logging"
|
4
|
+
|
5
|
+
module Grape
|
6
|
+
class API
|
7
|
+
def self.descendants # :nodoc:
|
8
|
+
descendants = []
|
9
|
+
ObjectSpace.each_object(singleton_class) do |k|
|
10
|
+
descendants.unshift k unless k == self
|
11
|
+
end
|
12
|
+
descendants
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Sapience
|
18
|
+
class Grape
|
19
|
+
Sapience.configure
|
20
|
+
::Grape::API.send(:include, Sapience::Loggable)
|
21
|
+
::Grape::API.descendants.each do |api|
|
22
|
+
api.send(:use, Sapience::Extensions::Grape::Middleware::Logging, logger: Sapience[self])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/sapience/log.rb
CHANGED
@@ -43,6 +43,8 @@ module Sapience
|
|
43
43
|
# metric_amount [Numeric]
|
44
44
|
# Used for numeric or counter metrics.
|
45
45
|
# For example, the number of inquiries or, the amount purchased etc.
|
46
|
+
|
47
|
+
# rubocop:disable LineLength
|
46
48
|
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception, :metric, :backtrace, :metric_amount) do
|
47
49
|
MAX_EXCEPTIONS_TO_UNWRAP = 5
|
48
50
|
# Call the block for exception and any nested exception
|
@@ -84,7 +86,7 @@ module Sapience
|
|
84
86
|
# Returns nil if their is no duration
|
85
87
|
def duration_to_s
|
86
88
|
return unless duration
|
87
|
-
duration < 10.0 ? "
|
89
|
+
format((duration < 10.0 ? "%.3fms" : "%.1fms"), duration)
|
88
90
|
end
|
89
91
|
|
90
92
|
# Returns [String] the duration in human readable form
|
@@ -98,7 +100,7 @@ module Sapience
|
|
98
100
|
elsif seconds >= 60.0 # 1 minute
|
99
101
|
Time.at(seconds).strftime("%-Mm %-Ss")
|
100
102
|
elsif seconds >= 1.0 # 1 second
|
101
|
-
"
|
103
|
+
format "%.3fs", seconds
|
102
104
|
else
|
103
105
|
duration_to_s
|
104
106
|
end
|
@@ -116,7 +118,7 @@ module Sapience
|
|
116
118
|
file, line = file_name_and_line(true)
|
117
119
|
file_name = " #{file}:#{line}" if file
|
118
120
|
|
119
|
-
"#{$PROCESS_ID}
|
121
|
+
format "#{$PROCESS_ID}:%.#{thread_name_length}s#{file_name}", thread_name
|
120
122
|
end
|
121
123
|
|
122
124
|
CALLER_REGEXP = /^(.*):(\d+).*/
|
@@ -129,7 +131,7 @@ module Sapience
|
|
129
131
|
|
130
132
|
# Returns [String, String] the file_name and line_number from the backtrace supplied
|
131
133
|
# in either the backtrace or exception
|
132
|
-
def file_name_and_line(short_name = false)
|
134
|
+
def file_name_and_line(short_name = false) # rubocop:disable CyclomaticComplexity
|
133
135
|
return unless backtrace || (exception && exception.backtrace)
|
134
136
|
stack = backtrace || exception.backtrace
|
135
137
|
extract_file_and_line(stack, short_name) if stack && stack.size > 0
|
@@ -155,7 +157,7 @@ module Sapience
|
|
155
157
|
# Ruby MRI supports micro seconds
|
156
158
|
# DEPRECATED
|
157
159
|
def formatted_time
|
158
|
-
"#{time.strftime("%Y-%m-%d %H:%M:%S")}
|
160
|
+
format("#{time.strftime("%Y-%m-%d %H:%M:%S")}.%06d", time.usec)
|
159
161
|
end
|
160
162
|
|
161
163
|
# Returns [Hash] representation of this log entry
|
@@ -217,5 +219,5 @@ module Sapience
|
|
217
219
|
h
|
218
220
|
end
|
219
221
|
end
|
220
|
-
|
222
|
+
# rubocop:enable LineLength
|
221
223
|
end
|
data/lib/sapience/loggable.rb
CHANGED
@@ -2,26 +2,28 @@ module Sapience
|
|
2
2
|
# rubocop:disable TrivialAccessors
|
3
3
|
module Loggable
|
4
4
|
def self.included(base)
|
5
|
-
base.
|
6
|
-
|
7
|
-
def self.logger
|
8
|
-
@sapience ||= Sapience[self]
|
9
|
-
end
|
5
|
+
base.send(:extend, Extensions)
|
6
|
+
end
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
# Returns [Sapience::Logger] instance level logger
|
9
|
+
def logger
|
10
|
+
@logger ||= self.class.logger
|
11
|
+
end
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
# Replace instance level logger
|
14
|
+
def logger=(logger)
|
15
|
+
@logger = logger
|
16
|
+
end
|
17
|
+
|
18
|
+
module Extensions
|
19
|
+
# Returns [Sapience::Logger] class level logger
|
20
|
+
def logger
|
21
|
+
@logger ||= Sapience[self]
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
24
|
+
# Replace instance class level logger
|
25
|
+
def logger=(logger)
|
26
|
+
@logger = logger
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
data/lib/sapience/logger.rb
CHANGED
@@ -32,42 +32,45 @@ module Sapience
|
|
32
32
|
super
|
33
33
|
end
|
34
34
|
|
35
|
-
# Returns [Integer] the number of log entries that have not been written
|
36
|
-
# to the appenders
|
37
|
-
#
|
38
|
-
# When this number grows it is because the logging appender thread is not
|
39
|
-
# able to write to the appenders fast enough. Either reduce the amount of
|
40
|
-
# logging, increase the log level, reduce the number of appenders, or
|
41
|
-
# look into speeding up the appenders themselves
|
42
|
-
def self.queue_size
|
43
|
-
queue.size
|
44
|
-
end
|
45
|
-
|
46
35
|
# Flush all queued log entries disk, database, etc.
|
47
36
|
# All queued log messages are written and then each appender is flushed in turn
|
48
|
-
def self.flush
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
37
|
+
def self.flush # rubocop:disable AbcSize
|
38
|
+
return unless appender_thread
|
39
|
+
appender_thread << lambda do
|
40
|
+
Sapience.appenders.each do |appender|
|
41
|
+
begin
|
42
|
+
logger.trace "Appender thread: Flushing appender: #{appender.name}"
|
43
|
+
appender.flush
|
44
|
+
rescue StandardError => exc
|
45
|
+
logger.error "Appender thread: Failed to flush appender: #{appender.inspect}", exc
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
logger.trace "Appender thread: All appenders flushed"
|
56
50
|
end
|
57
|
-
process_request(:flush)
|
58
51
|
end
|
59
52
|
|
60
53
|
# Close all appenders and flush any outstanding messages
|
61
54
|
def self.close
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
55
|
+
return unless appender_thread
|
56
|
+
appender_thread << lambda do
|
57
|
+
Sapience.appenders.each do |appender|
|
58
|
+
begin
|
59
|
+
close_appender(appender)
|
60
|
+
rescue StandardError => exc
|
61
|
+
logger.error "Appender thread: Failed to close appender: #{appender.inspect}", exc
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
logger.trace "Appender thread: All appenders flushed"
|
69
66
|
end
|
70
|
-
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.close_appender(appender)
|
70
|
+
logger.trace "Appender thread: Closing appender: #{appender.name}"
|
71
|
+
appender.flush
|
72
|
+
appender.close
|
73
|
+
Sapience.remove_appender(appender)
|
71
74
|
end
|
72
75
|
|
73
76
|
@@lag_check_interval = 5000
|
@@ -104,25 +107,25 @@ module Sapience
|
|
104
107
|
def log(log, message = nil, progname = nil, &block)
|
105
108
|
# Compatibility with ::Logger
|
106
109
|
return add(log, message, progname, &block) unless log.is_a?(Sapience::Log)
|
107
|
-
|
110
|
+
@@appender_thread.post(log) do |log_message|
|
111
|
+
Sapience.appenders.each do |appender|
|
112
|
+
begin
|
113
|
+
appender.log(log_message)
|
114
|
+
rescue StandardError => exc
|
115
|
+
logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end if @@appender_thread
|
108
119
|
end
|
109
120
|
|
110
|
-
|
111
|
-
|
112
|
-
@@appender_thread = nil
|
113
|
-
@@queue = Queue.new
|
114
|
-
|
115
|
-
# Queue to hold messages that need to be logged to the various appenders
|
116
|
-
def self.queue
|
117
|
-
@@queue
|
118
|
-
end
|
121
|
+
@@appender_thread = nil
|
119
122
|
|
120
123
|
# Internal logger for Sapience
|
121
124
|
# For example when an appender is not working etc..
|
122
125
|
# By default logs to STDERR
|
123
126
|
def self.logger
|
124
127
|
@@logger ||= begin
|
125
|
-
l = Sapience::Appender::File.new(STDERR, :warn)
|
128
|
+
l = Sapience::Appender::File.new(io: STDERR, level: :warn)
|
126
129
|
l.name = name
|
127
130
|
l
|
128
131
|
end
|
@@ -131,106 +134,23 @@ module Sapience
|
|
131
134
|
# Start the appender thread
|
132
135
|
def self.start_appender_thread
|
133
136
|
return false if appender_thread_active?
|
134
|
-
|
137
|
+
|
138
|
+
@@appender_thread = Concurrent::SingleThreadExecutor.new
|
135
139
|
fail "Failed to start Appender Thread" unless @@appender_thread
|
136
140
|
true
|
137
141
|
end
|
138
142
|
|
139
143
|
# Returns true if the appender_thread is active
|
140
144
|
def self.appender_thread_active?
|
141
|
-
@@appender_thread && @@appender_thread.
|
145
|
+
@@appender_thread && @@appender_thread.running?
|
142
146
|
end
|
143
147
|
|
144
148
|
# Separate appender thread responsible for reading log messages and
|
145
149
|
# calling the appenders in it's thread
|
146
150
|
# rubocop:disable BlockNesting, AssignmentInCondition, PerceivedComplexity, CyclomaticComplexity, AbcSize, LineLength, RescueException
|
147
151
|
def self.appender_thread
|
148
|
-
|
149
|
-
# Before terminating at_exit is used to flush all the appenders
|
150
|
-
#
|
151
|
-
# Should any appender fail to log or flush, the exception is logged and
|
152
|
-
# other appenders will still be called
|
153
|
-
Thread.current.name = "Sapience::AppenderThread"
|
154
|
-
logger.trace "V#{VERSION} Appender thread active"
|
155
|
-
begin
|
156
|
-
count = 0
|
157
|
-
while message = queue.pop
|
158
|
-
if message.is_a?(Log)
|
159
|
-
Sapience.appenders.each do |appender|
|
160
|
-
begin
|
161
|
-
appender.log(message)
|
162
|
-
rescue Exception => exc
|
163
|
-
logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
|
164
|
-
end
|
165
|
-
end
|
166
|
-
count += 1
|
167
|
-
# Check every few log messages whether this appender thread is falling behind
|
168
|
-
if count > lag_check_interval
|
169
|
-
if (diff = Time.now - message.time) > lag_threshold_s
|
170
|
-
logger.warn "Appender thread has fallen behind by #{diff} seconds with #{queue_size} messages queued up. Consider reducing the log level or changing the appenders"
|
171
|
-
end
|
172
|
-
count = 0
|
173
|
-
end
|
174
|
-
else
|
175
|
-
case message[:command]
|
176
|
-
when :flush
|
177
|
-
Sapience.appenders.each do |appender|
|
178
|
-
begin
|
179
|
-
logger.trace "Appender thread: Flushing appender: #{appender.name}"
|
180
|
-
appender.flush
|
181
|
-
rescue Exception => exc
|
182
|
-
logger.error "Appender thread: Failed to flush appender: #{appender.inspect}", exc
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
message[:reply_queue] << true if message[:reply_queue]
|
187
|
-
logger.trace "Appender thread: All appenders flushed"
|
188
|
-
when :close
|
189
|
-
Sapience.appenders.each do |appender|
|
190
|
-
begin
|
191
|
-
logger.trace "Appender thread: Closing appender: #{appender.name}"
|
192
|
-
appender.flush
|
193
|
-
appender.close
|
194
|
-
Sapience.remove_appender(appender)
|
195
|
-
rescue Exception => exc
|
196
|
-
logger.error "Appender thread: Failed to close appender: #{appender.inspect}", exc
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
message[:reply_queue] << true if message[:reply_queue]
|
201
|
-
logger.trace "Appender thread: All appenders flushed"
|
202
|
-
else
|
203
|
-
logger.warn "Appender thread: Ignoring unknown command: #{message[:command]}"
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
rescue Exception => exception
|
208
|
-
# This block may be called after the file handles have been released by Ruby
|
209
|
-
begin
|
210
|
-
logger.error "Appender thread restarting due to exception", exception
|
211
|
-
rescue Exception
|
212
|
-
nil
|
213
|
-
end
|
214
|
-
retry
|
215
|
-
ensure
|
216
|
-
@@appender_thread = nil
|
217
|
-
# This block may be called after the file handles have been released by Ruby
|
218
|
-
begin
|
219
|
-
logger.trace "Appender thread has stopped"
|
220
|
-
rescue Exception
|
221
|
-
nil
|
222
|
-
end
|
223
|
-
end
|
152
|
+
@@appender_thread
|
224
153
|
end
|
225
154
|
# rubocop:enable BlockNesting, AssignmentInCondition, PerceivedComplexity, CyclomaticComplexity, AbcSize, LineLength, RescueException
|
226
|
-
|
227
|
-
# Close all appenders and flush any outstanding messages
|
228
|
-
def self.process_request(command)
|
229
|
-
return false unless appender_thread_active?
|
230
|
-
|
231
|
-
reply_queue = Queue.new
|
232
|
-
queue << { command: command, reply_queue: reply_queue }
|
233
|
-
reply_queue.pop
|
234
|
-
end
|
235
155
|
end
|
236
156
|
end
|
data/lib/sapience/rails.rb
CHANGED
@@ -1,15 +1,72 @@
|
|
1
|
+
require "sapience"
|
2
|
+
|
1
3
|
module Sapience
|
2
4
|
class Rails < ::Rails::Engine
|
5
|
+
|
6
|
+
# Replace Rails logger initializer
|
3
7
|
::Rails::Application::Bootstrap.initializers.delete_if { |i| i.name == :initialize_logger }
|
8
|
+
|
4
9
|
initializer :initialize_logger, group: :all do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
Sapience.configure
|
11
|
+
::Rails.logger = Sapience[::Rails]
|
12
|
+
[:active_record, :action_controller, :action_mailer, :action_view].each do |name|
|
13
|
+
ActiveSupport.on_load(name) { include Sapience::Loggable }
|
14
|
+
end
|
15
|
+
ActiveSupport.on_load(:action_cable) { self.logger = Sapience["ActionCable"] }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Before any initializers run, but after the gems have been loaded
|
19
|
+
config.before_initialize do
|
20
|
+
# Replace the Mongoid Logger
|
21
|
+
Mongoid.logger = Sapience[Mongoid] if defined?(Mongoid)
|
22
|
+
Moped.logger = Sapience[Moped] if defined?(Moped)
|
23
|
+
|
24
|
+
# Replace the Resque Logger
|
25
|
+
Resque.logger = Sapience[Resque] if defined?(Resque) && Resque.respond_to?(:logger)
|
26
|
+
|
27
|
+
# Replace the Sidekiq logger
|
28
|
+
Sidekiq::Logging.logger = Sapience[Sidekiq] if defined?(Sidekiq)
|
29
|
+
|
30
|
+
# Replace the Sidetiq logger
|
31
|
+
Sidetiq.logger = Sapience[Sidetiq] if defined?(Sidetiq)
|
32
|
+
|
33
|
+
# Replace the Raven logger
|
34
|
+
# Raven::Configuration.logger = Sapience[Raven::Configuration] if defined?(Raven::Configuration)
|
35
|
+
Raven.send(:include) { Sapience::Loggable }
|
36
|
+
|
37
|
+
# Replace the Sneakers logger
|
38
|
+
Sneakers.logger = Sapience[Sneakers] if defined?(Sneakers)
|
39
|
+
|
40
|
+
# Replace the Bugsnag logger
|
41
|
+
Bugsnag.configure { |config| config.logger = Sapience[Bugsnag] } if defined?(Bugsnag)
|
42
|
+
|
43
|
+
# Set the logger for concurrent-ruby
|
44
|
+
Concurrent.global_logger = Sapience[Concurrent] if defined?(Concurrent)
|
45
|
+
|
46
|
+
# Rails Patches
|
47
|
+
Kernel.require "sapience/extensions/action_cable/tagged_logger_proxy" if defined?(ActionCable)
|
48
|
+
Kernel.require "sapience/extensions/action_controller/live" if defined?(ActionController::Live)
|
49
|
+
Kernel.require "sapience/extensions/action_dispatch/debug_exceptions" if defined?(ActionDispatch::DebugExceptions)
|
50
|
+
if defined?(ActionView::StreamingTemplateRenderer::Body)
|
51
|
+
Kernel.require "sapience/extensions/action_view/streaming_template_renderer"
|
52
|
+
end
|
53
|
+
Kernel.require "sapience/extensions/active_job/logging" if defined?(ActiveJob)
|
54
|
+
Kernel.require "sapience/extensions/active_model_serializers/logging" if defined?(ActiveModelSerializers)
|
55
|
+
Kernel.require "sapience/extensions/action_controller/log_subscriber" if defined?(ActionController)
|
56
|
+
Kernel.require "sapience/extensions/active_record/log_subscriber" if defined?(ActiveRecord::LogSubscriber)
|
57
|
+
Kernel.require "sapience/extensions/rails/rack/logger" if defined?(::Rails::Rack::Logger)
|
58
|
+
Kernel.require "sapience/extensions/rails/rack/logger_info_as_debug" if defined?(::Rails::Rack::Logger)
|
59
|
+
Kernel.require "sapience/extensions/action_view/log_subscriber" if defined?(ActionView::LogSubscriber)
|
60
|
+
if defined?(ActionView::LogSubscriber)
|
61
|
+
Kernel.require "sapience/extensions/action_controller/log_subscriber_processing"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Before any initializers run, but after the gems have been loaded
|
66
|
+
config.after_initialize do
|
67
|
+
# Replace the Bugsnag logger
|
68
|
+
Bugsnag.configure { |config| config.logger = Sapience[Bugsnag] } if defined?(Bugsnag)
|
13
69
|
end
|
70
|
+
|
14
71
|
end
|
15
72
|
end
|