sapience 2.4.0 → 2.5.0
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/CHANGELOG.md +6 -0
- data/Gemfile +1 -0
- data/Rakefile +1 -0
- data/lib/sapience/ansi_colors.rb +2 -1
- data/lib/sapience/appender/stream.rb +3 -3
- data/lib/sapience/appender/wrapper.rb +1 -0
- data/lib/sapience/appender.rb +1 -0
- data/lib/sapience/base.rb +6 -4
- data/lib/sapience/concerns/compatibility.rb +3 -4
- data/lib/sapience/config_loader.rb +3 -3
- data/lib/sapience/configuration.rb +4 -4
- data/lib/sapience/core_ext/hash.rb +4 -3
- data/lib/sapience/core_ext/symbol.rb +15 -12
- data/lib/sapience/core_ext/thread.rb +1 -0
- data/lib/sapience/descendants.rb +1 -1
- data/lib/sapience/error_handler/sentry.rb +3 -4
- data/lib/sapience/error_handler/silent.rb +2 -1
- data/lib/sapience/error_handler.rb +1 -0
- data/lib/sapience/extensions/action_cable/tagged_logger_proxy.rb +2 -1
- data/lib/sapience/extensions/action_controller/live.rb +1 -0
- data/lib/sapience/extensions/action_controller/log_subscriber.rb +6 -5
- data/lib/sapience/extensions/action_controller/notifications.rb +1 -0
- data/lib/sapience/extensions/action_dispatch/debug_exceptions.rb +2 -1
- data/lib/sapience/extensions/action_view/log_subscriber.rb +1 -0
- data/lib/sapience/extensions/action_view/streaming_template_renderer.rb +2 -1
- data/lib/sapience/extensions/active_job/logging.rb +2 -1
- data/lib/sapience/extensions/active_job/notifications.rb +1 -0
- data/lib/sapience/extensions/active_model_serializers/logging.rb +2 -1
- data/lib/sapience/extensions/active_record/log_subscriber.rb +3 -2
- data/lib/sapience/extensions/active_record/model_metrics.rb +17 -10
- data/lib/sapience/extensions/active_record/notifications.rb +1 -0
- data/lib/sapience/extensions/grape/middleware/logging.rb +8 -5
- data/lib/sapience/extensions/grape/notifications.rb +1 -0
- data/lib/sapience/extensions/grape/request_format_helper.rb +1 -0
- data/lib/sapience/extensions/grape/timings.rb +1 -0
- data/lib/sapience/extensions/notifications.rb +1 -0
- data/lib/sapience/extensions/rails/rack/logger.rb +2 -1
- data/lib/sapience/extensions/rails/rack/logger_info_as_debug.rb +2 -1
- data/lib/sapience/formatters/base.rb +2 -1
- data/lib/sapience/formatters/color.rb +3 -2
- data/lib/sapience/formatters/default.rb +3 -2
- data/lib/sapience/formatters/json.rb +1 -0
- data/lib/sapience/formatters/raw.rb +1 -0
- data/lib/sapience/grape.rb +1 -0
- data/lib/sapience/log.rb +7 -6
- data/lib/sapience/log_methods.rb +9 -8
- data/lib/sapience/loggable.rb +1 -1
- data/lib/sapience/logger.rb +13 -10
- data/lib/sapience/metrics/datadog.rb +3 -2
- data/lib/sapience/metrics.rb +1 -0
- data/lib/sapience/rails/engine.rb +3 -2
- data/lib/sapience/rails/railtie.rb +1 -0
- data/lib/sapience/rails.rb +1 -0
- data/lib/sapience/sapience.rb +13 -12
- data/lib/sapience/sneakers.rb +1 -0
- data/lib/sapience/subscriber.rb +7 -7
- data/lib/sapience/version.rb +2 -1
- data/lib/sapience.rb +1 -0
- data/lib/tasks/coverage.rake +3 -2
- data/sapience.gemspec +2 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c4aff2ff662827ad5cab7dce5d905985bcf2e05
|
4
|
+
data.tar.gz: 16955d4a9f3b194b9ec59a10f854657a6433f014
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d1218d578d34186e838e7ae36e482a215d27086e9e069399805c718ce9bc76314d79ed2d1da16bcc462fccb9aeb4647a090443de30263570bc1f04f08adca5f
|
7
|
+
data.tar.gz: 2b874e89fe7cc09ed5e7b632d695b34b4cd590aa46714cb4561bb973d8e66a5ae70e21ac861faf6ad8651845438a8e4bad5a490f6d9799e3e95bf8303643118e
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/lib/sapience/ansi_colors.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Stream appender
|
2
3
|
#
|
3
4
|
# Writes log messages to a file or open IO stream
|
@@ -5,7 +6,7 @@
|
|
5
6
|
module Sapience
|
6
7
|
module Appender
|
7
8
|
class Stream < Sapience::Subscriber
|
8
|
-
VALIDATION_MESSAGE = "stream is not writable"
|
9
|
+
VALIDATION_MESSAGE = "stream is not writable"
|
9
10
|
# Create a Stream Logger appender instance.
|
10
11
|
#
|
11
12
|
# Parameters
|
@@ -58,7 +59,6 @@ module Sapience
|
|
58
59
|
#
|
59
60
|
# logger = Sapience['test']
|
60
61
|
# logger.info 'Hello World'
|
61
|
-
# rubocop:disable AbcSize, CyclomaticComplexity, PerceivedComplexity
|
62
62
|
def initialize(options = {}, &block)
|
63
63
|
unless options[:io] || options[:file_name]
|
64
64
|
fail ArgumentError, "missing mandatory argument :file_name or :io"
|
@@ -115,7 +115,7 @@ module Sapience
|
|
115
115
|
# Since only one appender thread will be writing to the file at a time
|
116
116
|
# it is not necessary to protect access to the file with a semaphore
|
117
117
|
# Allow this logger to filter out log levels lower than it's own
|
118
|
-
@log.write(formatter.call(log, self) << "\n")
|
118
|
+
@log.write(+formatter.call(log, self) << "\n")
|
119
119
|
true
|
120
120
|
end
|
121
121
|
|
data/lib/sapience/appender.rb
CHANGED
data/lib/sapience/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
# rubocop:disable ClassLength
|
3
4
|
class Base
|
@@ -75,7 +76,7 @@ module Sapience
|
|
75
76
|
end
|
76
77
|
|
77
78
|
# :nodoc:
|
78
|
-
|
79
|
+
alias with_tags tagged
|
79
80
|
|
80
81
|
# :nodoc:
|
81
82
|
def tags
|
@@ -86,7 +87,7 @@ module Sapience
|
|
86
87
|
def push_tags(*tags)
|
87
88
|
Sapience.push_tags(*tags)
|
88
89
|
end
|
89
|
-
|
90
|
+
alias tags= push_tags
|
90
91
|
|
91
92
|
# :nodoc:
|
92
93
|
def pop_tags(quantity = 1)
|
@@ -268,7 +269,7 @@ module Sapience
|
|
268
269
|
return false if duration <= min_duration
|
269
270
|
log.duration = duration
|
270
271
|
end
|
271
|
-
log.payload = payload
|
272
|
+
log.payload = payload unless payload.empty?
|
272
273
|
end
|
273
274
|
self.log(log) if include_message?(log)
|
274
275
|
end
|
@@ -280,7 +281,7 @@ module Sapience
|
|
280
281
|
merged_tags = tags.dup
|
281
282
|
if payload.is_a?(Hash)
|
282
283
|
payload_tags = payload.delete(:tags) || []
|
283
|
-
merged_tags.concat(payload_tags)
|
284
|
+
merged_tags.concat(payload_tags) unless payload_tags.empty?
|
284
285
|
end
|
285
286
|
merged_tags.uniq
|
286
287
|
end
|
@@ -297,6 +298,7 @@ module Sapience
|
|
297
298
|
# Measure the supplied block and log the message
|
298
299
|
# rubocop:disable AbcSize, PerceivedComplexity, CyclomaticComplexity, LineLength
|
299
300
|
def measure_internal(level, index, message, params)
|
301
|
+
params.dup
|
300
302
|
start = Time.now
|
301
303
|
exception = nil
|
302
304
|
begin
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# :nodoc:
|
2
3
|
module Sapience
|
3
4
|
# :nodoc:
|
@@ -29,12 +30,10 @@ module Sapience
|
|
29
30
|
end
|
30
31
|
|
31
32
|
# :nodoc:
|
32
|
-
def close
|
33
|
-
end
|
33
|
+
def close; end
|
34
34
|
|
35
35
|
# :nodoc:
|
36
|
-
def reopen(_logdev = nil)
|
37
|
-
end
|
36
|
+
def reopen(_logdev = nil); end
|
38
37
|
|
39
38
|
# :nodoc:
|
40
39
|
def add(severity, message = nil, progname = nil, &block)
|
@@ -12,7 +12,7 @@ module Sapience
|
|
12
12
|
# during a run of the sapience program, if files in several
|
13
13
|
# directories are inspected.
|
14
14
|
module ConfigLoader
|
15
|
-
SAPIENCE_FILE = "sapience.yml"
|
15
|
+
SAPIENCE_FILE = "sapience.yml"
|
16
16
|
SAPIENCE_HOME = File.realpath(File.join(File.dirname(__FILE__), "..", ".."))
|
17
17
|
DEFAULT_FILE = File.join(SAPIENCE_HOME, "config", "default.yml")
|
18
18
|
|
@@ -24,7 +24,7 @@ module Sapience
|
|
24
24
|
|
25
25
|
def self.merge_configs(left_config = {}, right_config = {})
|
26
26
|
left_config.each do |key, config = {}|
|
27
|
-
right = right_config.fetch(key) {
|
27
|
+
right = right_config.fetch(key) { {} }
|
28
28
|
config.merge!(right)
|
29
29
|
end
|
30
30
|
|
@@ -78,7 +78,7 @@ module Sapience
|
|
78
78
|
YAML.safe_load(yaml_code, [Regexp], [], false, filename)
|
79
79
|
end
|
80
80
|
else
|
81
|
-
YAML.
|
81
|
+
YAML.safe_load(yaml_code, filename)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "ostruct"
|
2
3
|
|
3
4
|
module Sapience
|
@@ -23,10 +24,10 @@ module Sapience
|
|
23
24
|
# Initial default Level for all new instances of Sapience::Logger
|
24
25
|
def initialize(options = {}) # rubocop:disable AbcSize
|
25
26
|
fail ArgumentError, "options need to be a hash #{options.inspect}" unless options.is_a?(Hash)
|
26
|
-
@options
|
27
|
+
@options = DEFAULT.merge(options.dup.deep_symbolize_keyz!)
|
27
28
|
@options[:log_executor] &&= @options[:log_executor].to_sym
|
28
29
|
validate_log_executor!(@options[:log_executor])
|
29
|
-
self.default_level
|
30
|
+
self.default_level = @options[:log_level].to_sym
|
30
31
|
self.backtrace_level = @options[:log_level].to_sym
|
31
32
|
self.host = @options[:host]
|
32
33
|
self.app_name = @options[:app_name]
|
@@ -52,7 +53,7 @@ module Sapience
|
|
52
53
|
|
53
54
|
# Internal method to return the log level as an internal index
|
54
55
|
# Also supports mapping the ::Logger levels to Sapience levels
|
55
|
-
def level_to_index(level)
|
56
|
+
def level_to_index(level)
|
56
57
|
return if level.nil?
|
57
58
|
|
58
59
|
case level
|
@@ -90,7 +91,6 @@ module Sapience
|
|
90
91
|
Thread.current[:sapience_silence] || @default_level_index
|
91
92
|
end
|
92
93
|
|
93
|
-
|
94
94
|
# Sets the level at which backtraces should be captured
|
95
95
|
# for every log message.
|
96
96
|
#
|
@@ -1,14 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Hash
|
2
3
|
# Returns a Hash with all keys symbolized
|
3
4
|
def deep_symbolize_keyz!
|
4
5
|
deep_transform_keyz! { |key| key.to_sym rescue key } # rubocop:disable RescueModifier
|
5
6
|
end
|
6
|
-
|
7
|
+
alias deep_symbolize_keys! deep_symbolize_keyz!
|
7
8
|
|
8
9
|
def deep_transform_keyz!(&block)
|
9
10
|
_deep_transform_keyz_in_object!(self, &block)
|
10
11
|
end
|
11
|
-
|
12
|
+
alias deep_transform_keys! deep_transform_keyz!
|
12
13
|
|
13
14
|
def _deep_transform_keyz_in_object!(object, &block)
|
14
15
|
case object
|
@@ -24,5 +25,5 @@ class Hash
|
|
24
25
|
object
|
25
26
|
end
|
26
27
|
end
|
27
|
-
|
28
|
+
alias _deep_transform_keys_in_object! _deep_transform_keyz_in_object!
|
28
29
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Symbol
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
unless :sym.respond_to?(:camelize)
|
4
|
+
def camelize(uppercase_first_letter = true)
|
5
|
+
string = to_s
|
6
|
+
string = if uppercase_first_letter
|
7
|
+
string.sub(/^[a-z\d]*/) { $&.capitalize }
|
8
|
+
else
|
9
|
+
string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase }
|
10
|
+
end
|
11
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do
|
12
|
+
"#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}"
|
13
|
+
end
|
14
|
+
string.gsub!(/\//, "::")
|
15
|
+
string
|
11
16
|
end
|
12
|
-
|
13
|
-
string
|
14
|
-
end unless :sym.respond_to?(:camelize)
|
17
|
+
end
|
15
18
|
end
|
data/lib/sapience/descendants.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
begin
|
2
3
|
require "sentry-raven"
|
3
4
|
rescue LoadError
|
@@ -9,11 +10,10 @@ end
|
|
9
10
|
# Example:
|
10
11
|
# Sapience.add_appender(:stream, {io: STDOUT, formatter: :color})
|
11
12
|
#
|
12
|
-
# rubocop:disable Style/ClassAndModuleChildren
|
13
13
|
module Sapience
|
14
14
|
class ErrorHandler
|
15
15
|
class Sentry < Sapience::ErrorHandler
|
16
|
-
VALIDATION_MESSAGE = "DSN is not valid, please add appender with :dsn key or set SENTRY_DSN"
|
16
|
+
VALIDATION_MESSAGE = "DSN is not valid, please add appender with :dsn key or set SENTRY_DSN"
|
17
17
|
URI_REGEXP = URI::DEFAULT_PARSER.regexp[:ABS_URI]
|
18
18
|
#
|
19
19
|
# level: [:trace | :debug | :info | :warn | :error | :fatal]
|
@@ -52,7 +52,7 @@ module Sapience
|
|
52
52
|
def tags_context(options = {})
|
53
53
|
Raven.tags_context(options)
|
54
54
|
end
|
55
|
-
|
55
|
+
alias tags= tags_context
|
56
56
|
|
57
57
|
def configured?
|
58
58
|
@configured == true
|
@@ -119,7 +119,6 @@ module Sapience
|
|
119
119
|
(@sentry_dsn || ENV["SENTRY_DSN"]).to_s
|
120
120
|
end
|
121
121
|
|
122
|
-
|
123
122
|
# Sapience logger
|
124
123
|
def sentry_logger
|
125
124
|
@sentry_logger ||= begin
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
class ErrorHandler
|
3
4
|
class Silent < Sapience::ErrorHandler
|
@@ -24,7 +25,7 @@ module Sapience
|
|
24
25
|
def capture(_options: {})
|
25
26
|
nil
|
26
27
|
end
|
27
|
-
|
28
|
+
alias capture! capture
|
28
29
|
|
29
30
|
def user_context(_options = {})
|
30
31
|
nil
|
@@ -1,20 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "action_controller/log_subscriber"
|
2
3
|
|
3
4
|
module Sapience
|
4
5
|
module Extensions
|
5
6
|
module ActionController
|
6
|
-
class LogSubscriber < ::ActionController::LogSubscriber
|
7
|
-
|
8
|
-
|
7
|
+
class LogSubscriber < ::ActionController::LogSubscriber
|
8
|
+
alias orig_start_processing start_processing
|
9
|
+
alias orig_process_action process_action
|
9
10
|
|
10
11
|
# Log as debug to hide Processing messages in production
|
11
12
|
def start_processing(event)
|
12
13
|
debug { "Processing ##{event.payload[:action]}" }
|
13
14
|
end
|
14
15
|
|
15
|
-
def process_action(event)
|
16
|
+
def process_action(event)
|
16
17
|
return unless logger.info?
|
17
|
-
data
|
18
|
+
data = request(event.payload)
|
18
19
|
data.merge! request_id(event)
|
19
20
|
data.merge! runtimes(event)
|
20
21
|
data.merge! exception(event.payload)
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Log actual exceptions, not a string representation
|
2
3
|
|
3
4
|
class ActionDispatch::DebugExceptions # rubocop:disable ClassAndModuleChildren
|
4
5
|
private
|
5
6
|
|
6
|
-
|
7
|
+
alias orig_log_error log_error
|
7
8
|
|
8
9
|
def log_error(_request, wrapper)
|
9
10
|
ActiveSupport::Deprecation.silence do
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Log actual exceptions, not a string representation
|
2
3
|
|
3
4
|
class ActionView::StreamingTemplateRenderer # rubocop:disable ClassAndModuleChildren
|
4
5
|
class Body
|
5
6
|
private
|
6
7
|
|
7
|
-
|
8
|
+
alias log_error_original log_error
|
8
9
|
|
9
10
|
def log_error(exception) #:nodoc:
|
10
11
|
ActionView::Base.logger.fatal(exception)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Patch ActiveJob logger
|
2
3
|
require "active_job/logging"
|
3
4
|
|
@@ -6,7 +7,7 @@ module ActiveJob::Logging # rubocop:disable ClassAndModuleChildren
|
|
6
7
|
|
7
8
|
private
|
8
9
|
|
9
|
-
|
10
|
+
alias orig_tag_logger tag_logger
|
10
11
|
|
11
12
|
def tag_logger(*tags, &block)
|
12
13
|
logger.tagged(*tags, &block)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Patch ActiveModelSerializers logger
|
2
3
|
|
3
4
|
require "active_model_serializers/logging"
|
@@ -9,7 +10,7 @@ module ActiveModelSerializers::Logging # rubocop:disable ClassAndModuleChildren
|
|
9
10
|
|
10
11
|
private
|
11
12
|
|
12
|
-
|
13
|
+
alias orig_tag_logger tag_logger
|
13
14
|
|
14
15
|
def tag_logger(*tags, &block)
|
15
16
|
logger.tagged(*tags, &block)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "active_support/notifications"
|
2
3
|
require "active_record/log_subscriber"
|
3
4
|
|
@@ -11,14 +12,14 @@ module Sapience
|
|
11
12
|
event = normalize(event)
|
12
13
|
debug(event) if logger && event
|
13
14
|
end
|
14
|
-
|
15
|
+
alias sql identity
|
15
16
|
|
16
17
|
private
|
17
18
|
|
18
19
|
def normalize(event)
|
19
20
|
data = event.payload
|
20
21
|
|
21
|
-
return if
|
22
|
+
return if data[:name] == "SCHEMA"
|
22
23
|
|
23
24
|
data.merge! runtimes(event)
|
24
25
|
data.merge! extract_sql(data)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
module Extensions
|
3
4
|
module ActiveRecord
|
@@ -9,23 +10,29 @@ module Sapience
|
|
9
10
|
const_set(:SAPIENCE_MODEL_UPDATE_METRICS_KEY, "model.#{tableized_name}.update")
|
10
11
|
const_set(:SAPIENCE_MODEL_DESTROY_METRICS_KEY, "model.#{tableized_name}.destroy")
|
11
12
|
|
12
|
-
before_create
|
13
|
-
|
14
|
-
|
13
|
+
if respond_to?(:before_create)
|
14
|
+
before_create do
|
15
|
+
Sapience.metrics.increment(self.class.const_get(:SAPIENCE_MODEL_CREATE_METRICS_KEY))
|
16
|
+
end
|
17
|
+
end
|
15
18
|
|
16
|
-
before_update
|
17
|
-
|
18
|
-
|
19
|
+
if respond_to?(:before_update)
|
20
|
+
before_update do
|
21
|
+
Sapience.metrics.increment(self.class.const_get(:SAPIENCE_MODEL_UPDATE_METRICS_KEY))
|
22
|
+
end
|
23
|
+
end
|
19
24
|
|
20
|
-
before_destroy
|
21
|
-
|
22
|
-
|
25
|
+
if respond_to?(:before_destroy)
|
26
|
+
before_destroy do
|
27
|
+
Sapience.metrics.increment(self.class.const_get(:SAPIENCE_MODEL_DESTROY_METRICS_KEY))
|
28
|
+
end
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
26
33
|
module ClassMethods
|
27
34
|
def tableized_name
|
28
|
-
@tableized_name ||= name.tableize.singularize.
|
35
|
+
@tableized_name ||= name.tableize.singularize.tr("/", ".")
|
29
36
|
end
|
30
37
|
end
|
31
38
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "grape/middleware/base"
|
2
3
|
require_relative "../request_format_helper"
|
3
4
|
|
@@ -8,10 +9,12 @@ module Sapience
|
|
8
9
|
class Logging < ::Grape::Middleware::Base
|
9
10
|
include RequestFormatHelper
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
if defined?(ActiveRecord)
|
13
|
+
ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
|
14
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
15
|
+
Grape::Timings.append_db_runtime(event)
|
16
|
+
end
|
17
|
+
end
|
15
18
|
|
16
19
|
def initialize(app, options = {})
|
17
20
|
super
|
@@ -36,7 +39,7 @@ module Sapience
|
|
36
39
|
after_failure(error)
|
37
40
|
throw(:error, error)
|
38
41
|
else
|
39
|
-
@status,
|
42
|
+
@status, = *@app_response
|
40
43
|
after
|
41
44
|
end
|
42
45
|
@app_response
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Replace rack started message with a semantic equivalent
|
2
3
|
class Rails::Rack::Logger # rubocop:disable ClassAndModuleChildren
|
3
|
-
|
4
|
+
alias started_request_message_original started_request_message
|
4
5
|
def started_request_message(request)
|
5
6
|
{
|
6
7
|
message: "Started",
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Drop rack Started message to debug level message
|
2
3
|
class Rails::Rack::Logger # rubocop:disable ClassAndModuleChildren
|
3
4
|
|
@@ -13,7 +14,7 @@ class Rails::Rack::Logger # rubocop:disable ClassAndModuleChildren
|
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
+
alias orig_logger logger
|
17
18
|
|
18
19
|
def logger
|
19
20
|
@logger ||= begin
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
module Formatters
|
3
4
|
class Base
|
@@ -16,7 +17,7 @@ module Sapience
|
|
16
17
|
@time_format = options.key?(:time_format) ? options.delete(:time_format) : default_format
|
17
18
|
@log_host = options.key?(:log_host) ? options.delete(:log_host) : true
|
18
19
|
@log_application = options.key?(:log_application) ? options.delete(:log_application) : true
|
19
|
-
fail(ArgumentError, "Unknown options: #{options.inspect}")
|
20
|
+
fail(ArgumentError, "Unknown options: #{options.inspect}") unless options.empty?
|
20
21
|
end
|
21
22
|
|
22
23
|
# Return the Time as a formatted string
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Load AwesomePrint if available
|
2
3
|
begin
|
3
4
|
require "awesome_print"
|
@@ -27,13 +28,13 @@ module Sapience
|
|
27
28
|
colors = Sapience::AnsiColors
|
28
29
|
level_color = colors::LEVEL_MAP[log.level]
|
29
30
|
|
30
|
-
message = time_format.nil? ? "" : "#{format_time(log.time)} "
|
31
|
+
message = time_format.nil? ? +"" : +"#{format_time(log.time)} "
|
31
32
|
|
32
33
|
# Header with date, time, log level and process info
|
33
34
|
message << "#{level_color}#{log.level_to_s}#{colors::CLEAR} [#{log.process_info}]"
|
34
35
|
|
35
36
|
# Tags
|
36
|
-
message << " " << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(" ") if log.tags &&
|
37
|
+
message << " " << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(" ") if log.tags && !log.tags.empty? # rubocop:disable LineLength
|
37
38
|
|
38
39
|
# Duration
|
39
40
|
message << " (#{colors::BOLD}#{log.duration_human}#{colors::CLEAR})" if log.duration
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
module Formatters
|
3
4
|
class Default < Base
|
@@ -6,13 +7,13 @@ module Sapience
|
|
6
7
|
# 2011-07-19 14:36:15.660235 D [1149:ScriptThreadProcess] Rails -- Hello World
|
7
8
|
def call(log, _logger) # rubocop:disable AbcSize, PerceivedComplexity, CyclomaticComplexity
|
8
9
|
# Date & time
|
9
|
-
message = time_format.nil? ? "" : "#{format_time(log.time)} "
|
10
|
+
message = time_format.nil? ? +"" : +"#{format_time(log.time)} "
|
10
11
|
|
11
12
|
# Log level and process info
|
12
13
|
message << "#{log.level_to_s} [#{log.process_info}]"
|
13
14
|
|
14
15
|
# Tags
|
15
|
-
message << " " << log.tags.collect { |tag| "[#{tag}]" }.join(" ") if log.tags &&
|
16
|
+
message << " " << log.tags.collect { |tag| "[#{tag}]" }.join(" ") if log.tags && !log.tags.empty?
|
16
17
|
|
17
18
|
# Duration
|
18
19
|
message << " (#{log.duration_human})" if log.duration
|
data/lib/sapience/grape.rb
CHANGED
data/lib/sapience/log.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
# Log Struct
|
3
4
|
#
|
@@ -48,13 +49,13 @@ module Sapience
|
|
48
49
|
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception, :metric, :backtrace, :metric_amount) do
|
49
50
|
MAX_EXCEPTIONS_TO_UNWRAP = 5
|
50
51
|
MILLISECONDS_IN_SECOND = 1_000
|
51
|
-
MILLISECONDS_IN_MINUTE =
|
52
|
+
MILLISECONDS_IN_MINUTE = 60_000
|
52
53
|
MILLISECONDS_IN_HOUR = 3_600_000
|
53
54
|
MILLISECONDS_IN_DAY = 86_400_000
|
54
55
|
|
55
56
|
# Returns [String] the exception backtrace including all of the child / caused by exceptions
|
56
57
|
def backtrace_to_s
|
57
|
-
trace = ""
|
58
|
+
trace = +""
|
58
59
|
each_exception do |exception, i|
|
59
60
|
if i == 0
|
60
61
|
trace << (exception.backtrace || []).join("\n")
|
@@ -80,7 +81,7 @@ module Sapience
|
|
80
81
|
minutes, ms = ms.divmod(MILLISECONDS_IN_MINUTE)
|
81
82
|
seconds, ms = ms.divmod(MILLISECONDS_IN_SECOND)
|
82
83
|
|
83
|
-
str = ""
|
84
|
+
str = +""
|
84
85
|
str << "#{days}d" if days > 0
|
85
86
|
str << " #{hours}h" if hours > 0
|
86
87
|
str << " #{minutes}m" if minutes > 0
|
@@ -126,7 +127,7 @@ module Sapience
|
|
126
127
|
def file_name_and_line(short_name = false) # rubocop:disable CyclomaticComplexity
|
127
128
|
return unless backtrace || (exception && exception.backtrace)
|
128
129
|
stack = backtrace || exception.backtrace
|
129
|
-
extract_file_and_line(stack, short_name) if stack && stack.
|
130
|
+
extract_file_and_line(stack, short_name) if stack && !stack.empty?
|
130
131
|
end
|
131
132
|
|
132
133
|
# Strip the standard Rails colorizing from the logged message
|
@@ -173,7 +174,7 @@ module Sapience
|
|
173
174
|
# Returns [Hash] representation of this log entry
|
174
175
|
def to_h(host = Sapience.config.host, app_name = Sapience.app_name) # rubocop:disable AbcSize, CyclomaticComplexity, PerceivedComplexity, LineLength
|
175
176
|
# Header
|
176
|
-
h
|
177
|
+
h = {
|
177
178
|
name: name,
|
178
179
|
pid: $PROCESS_ID,
|
179
180
|
thread: thread_name,
|
@@ -190,7 +191,7 @@ module Sapience
|
|
190
191
|
end
|
191
192
|
|
192
193
|
# Tags
|
193
|
-
h[:tags] = tags if tags &&
|
194
|
+
h[:tags] = tags if tags && !tags.empty?
|
194
195
|
|
195
196
|
# Duration
|
196
197
|
if duration
|
data/lib/sapience/log_methods.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sapience
|
2
3
|
module LogMethods
|
3
4
|
def trace(message = nil, payload = nil, exception = nil, &block)
|
@@ -77,32 +78,32 @@ module Sapience
|
|
77
78
|
def measure_trace(message, params = {}, &block)
|
78
79
|
measure(:trace, message, params, &block)
|
79
80
|
end
|
80
|
-
|
81
|
+
alias benchmark_trace measure_trace
|
81
82
|
|
82
83
|
def measure_debug(message, params = {}, &block)
|
83
84
|
measure(:debug, message, params, &block)
|
84
85
|
end
|
85
|
-
|
86
|
+
alias benchmark_debug measure_debug
|
86
87
|
|
87
88
|
def measure_info(message, params = {}, &block)
|
88
89
|
measure(:info, message, params, &block)
|
89
90
|
end
|
90
|
-
|
91
|
+
alias benchmark_info measure_info
|
91
92
|
|
92
93
|
def measure_warn(message, params = {}, &block)
|
93
94
|
measure(:warn, message, params, &block)
|
94
95
|
end
|
95
|
-
|
96
|
+
alias benchmark_warn measure_warn
|
96
97
|
|
97
98
|
def measure_error(message, params = {}, &block)
|
98
99
|
measure(:error, message, params, &block)
|
99
100
|
end
|
100
|
-
|
101
|
+
alias benchmark_error measure_error
|
101
102
|
|
102
103
|
def measure_fatal(message, params = {}, &block)
|
103
104
|
measure(:fatal, message, params, &block)
|
104
105
|
end
|
105
|
-
|
106
|
+
alias benchmark_fatal measure_fatal
|
106
107
|
|
107
108
|
# Dynamically supply the log level with every measurement call
|
108
109
|
def measure(level, message, params = {}, &block)
|
@@ -110,11 +111,11 @@ module Sapience
|
|
110
111
|
if level_index <= index
|
111
112
|
measure_internal(level, index, message, params, &block)
|
112
113
|
else
|
113
|
-
block
|
114
|
+
block&.call(params)
|
114
115
|
end
|
115
116
|
end
|
116
117
|
|
117
|
-
|
118
|
+
alias benchmark measure
|
118
119
|
|
119
120
|
def level_to_index(level)
|
120
121
|
Sapience.config.level_to_index(level)
|
data/lib/sapience/loggable.rb
CHANGED
data/lib/sapience/logger.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "concurrent"
|
2
3
|
|
3
4
|
# rubocop:disable ClassVars
|
4
5
|
module Sapience
|
5
6
|
# Logger stores the class name to be used for all log messages so that every
|
6
7
|
# log message written by this instance will include the class name
|
7
|
-
class Logger < Base
|
8
|
+
class Logger < Base
|
8
9
|
include Sapience::Concerns::Compatibility
|
9
10
|
|
10
11
|
# Flush all queued log entries disk, database, etc.
|
@@ -85,7 +86,7 @@ module Sapience
|
|
85
86
|
|
86
87
|
# Separate appender thread responsible for reading log messages and
|
87
88
|
# calling the appenders in it's thread
|
88
|
-
# rubocop:disable
|
89
|
+
# rubocop:disable LineLength
|
89
90
|
def self.appender_thread
|
90
91
|
@@appender_thread
|
91
92
|
end
|
@@ -132,16 +133,18 @@ module Sapience
|
|
132
133
|
def log(log, message = nil, progname = nil, &block)
|
133
134
|
# Compatibility with ::Logger
|
134
135
|
return add(log, message, progname, &block) unless log.is_a?(Sapience::Log)
|
135
|
-
@@appender_thread
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
136
|
+
if @@appender_thread
|
137
|
+
@@appender_thread << lambda do
|
138
|
+
Sapience.appenders.each do |appender|
|
139
|
+
next unless appender.valid?
|
140
|
+
begin
|
141
|
+
appender.log(log)
|
142
|
+
rescue StandardError => exc
|
143
|
+
$stderr.write("Appender thread: Failed to log to appender: #{appender.inspect}\n #{exc.inspect}")
|
144
|
+
end
|
142
145
|
end
|
143
146
|
end
|
144
|
-
end
|
147
|
+
end
|
145
148
|
end
|
146
149
|
# rubocop:enable BlockNesting, AssignmentInCondition, PerceivedComplexity, CyclomaticComplexity, AbcSize, LineLength, RescueException
|
147
150
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "uri"
|
2
3
|
begin
|
3
4
|
require "datadog/statsd"
|
@@ -11,7 +12,7 @@ end
|
|
11
12
|
module Sapience
|
12
13
|
class Metrics
|
13
14
|
class Datadog < Sapience::Metrics
|
14
|
-
VALIDATION_MESSAGE = "Statsd only supports udp. Example: '#{Sapience::DEFAULT_STATSD_URL}'"
|
15
|
+
VALIDATION_MESSAGE = "Statsd only supports udp. Example: '#{Sapience::DEFAULT_STATSD_URL}'"
|
15
16
|
|
16
17
|
# Create Appender
|
17
18
|
#
|
@@ -27,7 +28,7 @@ module Sapience
|
|
27
28
|
# tags: [String]
|
28
29
|
# Example:
|
29
30
|
# tag1:true
|
30
|
-
# rubocop:disable
|
31
|
+
# rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
31
32
|
|
32
33
|
def initialize(opts = {})
|
33
34
|
options = opts.dup
|
data/lib/sapience/metrics.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "sapience"
|
2
3
|
require "sapience/extensions/action_controller/live" if defined?(ActionController::Live)
|
3
4
|
require "sapience/extensions/action_controller/log_subscriber"
|
@@ -22,7 +23,7 @@ module Sapience
|
|
22
23
|
initializer :initialize_logger, group: :all, before: :bootstrap_hook do
|
23
24
|
Sapience.configure
|
24
25
|
|
25
|
-
[
|
26
|
+
%i[active_record action_controller action_mailer action_view].each do |name|
|
26
27
|
ActiveSupport.on_load(name) { include Sapience::Loggable }
|
27
28
|
end
|
28
29
|
ActiveSupport.on_load(:action_cable) { self.logger = Sapience["ActionCable"] }
|
@@ -48,7 +49,7 @@ module Sapience
|
|
48
49
|
|
49
50
|
# Replace the Raven logger
|
50
51
|
# Raven::Configuration.logger = Sapience[Raven::Configuration] if defined?(Raven::Configuration)
|
51
|
-
Raven.send(:include
|
52
|
+
Raven.send(:include, Sapience::Loggable)
|
52
53
|
|
53
54
|
# Replace the Sneakers logger
|
54
55
|
Sneakers.configure(log: Sapience[Sneakers]) if defined?(Sneakers)
|
data/lib/sapience/rails.rb
CHANGED
data/lib/sapience/sapience.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "concurrent"
|
2
3
|
require "socket"
|
3
4
|
require "sapience/descendants"
|
@@ -27,19 +28,19 @@ module Sapience
|
|
27
28
|
UnkownLogLevel = Class.new(StandardError)
|
28
29
|
InvalidLogExecutor = Class.new(StandardError)
|
29
30
|
MissingConfiguration = Class.new(StandardError)
|
30
|
-
@@configured
|
31
|
+
@@configured = false
|
31
32
|
|
32
33
|
# Logging levels in order of most detailed to most severe
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
APP_NAME = "APP_NAME"
|
35
|
+
DEFAULT_ENV = "default"
|
36
|
+
RACK_ENV = "RACK_ENV"
|
37
|
+
RAILS_ENV = "RAILS_ENV"
|
38
|
+
SAPIENCE_ENV = "SAPIENCE_ENV"
|
39
|
+
LEVELS = %i[trace debug info warn error fatal].freeze
|
39
40
|
APPENDER_NAMESPACE = Sapience::Appender
|
40
41
|
METRICS_NAMESPACE = Sapience::Metrics
|
41
42
|
ERROR_HANDLER_NAMESPACE = Sapience::ErrorHandler
|
42
|
-
DEFAULT_STATSD_URL = "udp://localhost:8125"
|
43
|
+
DEFAULT_STATSD_URL = "udp://localhost:8125"
|
43
44
|
|
44
45
|
def self.configure(force: false)
|
45
46
|
yield config if block_given?
|
@@ -115,7 +116,7 @@ module Sapience
|
|
115
116
|
|
116
117
|
def self.namify(appname, sep = "_")
|
117
118
|
return unless appname.is_a?(String)
|
118
|
-
return
|
119
|
+
return if appname.empty?
|
119
120
|
|
120
121
|
# Turn unwanted chars into the separator
|
121
122
|
appname = appname.dup
|
@@ -213,7 +214,7 @@ module Sapience
|
|
213
214
|
# logger = Sapience['Example']
|
214
215
|
# logger.info "Hello World"
|
215
216
|
# logger.debug("Login time", user: 'Joe', duration: 100, ip_address: '127.0.0.1')
|
216
|
-
def self.add_appender(appender_class_name, options = {}, _deprecated_level = nil, &_block)
|
217
|
+
def self.add_appender(appender_class_name, options = {}, _deprecated_level = nil, &_block)
|
217
218
|
fail ArgumentError, "options should be a hash" unless options.is_a?(Hash)
|
218
219
|
options = options.dup.deep_symbolize_keyz!
|
219
220
|
appender_class = constantize_symbol(appender_class_name)
|
@@ -395,7 +396,7 @@ module Sapience
|
|
395
396
|
# Remove specified number of tags from the current tag list
|
396
397
|
def self.pop_tags(quantity = 1)
|
397
398
|
t = Thread.current[:sapience_tags]
|
398
|
-
t
|
399
|
+
t&.pop(quantity)
|
399
400
|
end
|
400
401
|
|
401
402
|
# Silence noisy log levels by changing the default_level within the block
|
@@ -458,7 +459,7 @@ module Sapience
|
|
458
459
|
if RUBY_VERSION.to_i >= 2
|
459
460
|
Object.const_get(class_name)
|
460
461
|
else
|
461
|
-
class_name.split("::").inject(Object) { |o, name| o.const_get(name) }
|
462
|
+
class_name.split("::").inject(Object) { |o, name| o.const_get(name) }
|
462
463
|
end
|
463
464
|
rescue NameError
|
464
465
|
raise UnknownClass, "Could not find class: #{class_name}."
|
data/lib/sapience/sneakers.rb
CHANGED
data/lib/sapience/subscriber.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Abstract Subscriber
|
2
3
|
#
|
3
4
|
# Abstract base class for appender and metrics subscribers.
|
@@ -97,7 +98,7 @@ module Sapience
|
|
97
98
|
@formatter = extract_formatter(options.delete(:formatter), &block)
|
98
99
|
@app_name = options.delete(:app_name)
|
99
100
|
@host = options.delete(:host)
|
100
|
-
fail(ArgumentError, "Unknown options: #{options.inspect}")
|
101
|
+
fail(ArgumentError, "Unknown options: #{options.inspect}") unless options.empty?
|
101
102
|
|
102
103
|
# Subscribers don't take a class name, so use this class name if an subscriber
|
103
104
|
# is logged to directly
|
@@ -122,17 +123,16 @@ module Sapience
|
|
122
123
|
# - Otherwise an instance of the default formatter is returned.
|
123
124
|
# rubocop:disable CyclomaticComplexity, AbcSize, PerceivedComplexity
|
124
125
|
def extract_formatter(formatter, &block)
|
125
|
-
|
126
|
-
when formatter.is_a?(Symbol) || formatter.is_a?(String)
|
126
|
+
if formatter.is_a?(Symbol) || formatter.is_a?(String)
|
127
127
|
Sapience.constantize_symbol(formatter, "Sapience::Formatters").new
|
128
|
-
|
128
|
+
elsif formatter.is_a?(Hash) && !formatter.empty?
|
129
129
|
fmt, options = formatter.first
|
130
130
|
Sapience.constantize_symbol(fmt.to_sym, "Sapience::Formatters").new(options)
|
131
|
-
|
131
|
+
elsif formatter.respond_to?(:call)
|
132
132
|
formatter
|
133
|
-
|
133
|
+
elsif block
|
134
134
|
block
|
135
|
-
|
135
|
+
elsif respond_to?(:call)
|
136
136
|
self
|
137
137
|
else
|
138
138
|
default_formatter
|
data/lib/sapience/version.rb
CHANGED
data/lib/sapience.rb
CHANGED
data/lib/tasks/coverage.rake
CHANGED
data/sapience.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
lib = File.expand_path("../lib", __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require "sapience/version"
|
@@ -44,4 +45,5 @@ Gem::Specification.new do |spec|
|
|
44
45
|
spec.add_development_dependency "gem-release"
|
45
46
|
spec.add_development_dependency "memory_profiler"
|
46
47
|
spec.add_development_dependency "rspec-prof"
|
48
|
+
spec.add_development_dependency "appraisal"
|
47
49
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sapience
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikael Henriksson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-07-
|
12
|
+
date: 2017-07-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: concurrent-ruby
|
@@ -277,6 +277,20 @@ dependencies:
|
|
277
277
|
- - ">="
|
278
278
|
- !ruby/object:Gem::Version
|
279
279
|
version: '0'
|
280
|
+
- !ruby/object:Gem::Dependency
|
281
|
+
name: appraisal
|
282
|
+
requirement: !ruby/object:Gem::Requirement
|
283
|
+
requirements:
|
284
|
+
- - ">="
|
285
|
+
- !ruby/object:Gem::Version
|
286
|
+
version: '0'
|
287
|
+
type: :development
|
288
|
+
prerelease: false
|
289
|
+
version_requirements: !ruby/object:Gem::Requirement
|
290
|
+
requirements:
|
291
|
+
- - ">="
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '0'
|
280
294
|
description: Hasslefree autoconfiguration for logging, metrics and exception collection.
|
281
295
|
email:
|
282
296
|
- mika@reevoo.com
|