contextual_logger 0.9.0.pre.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7396d052ab45c9e40375f045cac2ae2dffa8e0a74b964b61252f5dca8a8500f9
4
- data.tar.gz: 1f6e1299b3ad104625fc0537259c5fab051230bf03d528961be518119b23b8b4
3
+ metadata.gz: 0c5fcdf15e253eb8abb46dde530238633bd584f151e0282526dcfce923b4dc50
4
+ data.tar.gz: da4e10e4a778d244b2c36640ec4600bc76e4357fd4b0ddfbfef362c2276bbd5a
5
5
  SHA512:
6
- metadata.gz: 6649c29d562f319d8c8360ee6016b0b1bde30f07856c03c3f5c97f151a591b5784c4f74488253f6b4afd7c2f3419c857fef8b96b36be2e187fc12cf657d8a6d9
7
- data.tar.gz: 318dbefabf79b8ad34db1aa268d4e930879883ae74c72b05f417e25267ee042a50711688210abfc7b31dc09698b40dbb524d95df59ea463d02d09101928a8948
6
+ metadata.gz: c575941e59fe7196d27528ea0733bd841eb47e45914f8b74add858227fc55161c2cbc2837653033f80ddfea3c3768538c137392d0e3a2b9f64c344982fb281ff
7
+ data.tar.gz: 199b5c2446a3fe1e6730b352dd23e93c0f9a52e04fffc335b28c6b26e0a2f5e3fe658b9949f57f87b3adba952e2b27ebc493e05dc5a3b2944baefcea0203e099
@@ -7,6 +7,16 @@ require_relative './contextual_logger/redactor'
7
7
  require_relative './contextual_logger/context/handler'
8
8
 
9
9
  module ContextualLogger
10
+ LOG_LEVEL_NAMES_TO_SEVERITY =
11
+ {
12
+ debug: Logger::Severity::DEBUG,
13
+ info: Logger::Severity::INFO,
14
+ warn: Logger::Severity::WARN,
15
+ error: Logger::Severity::ERROR,
16
+ fatal: Logger::Severity::FATAL,
17
+ unknown: Logger::Severity::UNKNOWN
18
+ }.freeze
19
+
10
20
  class << self
11
21
  def new(logger)
12
22
  logger.extend(LoggerMixin)
@@ -17,22 +27,8 @@ module ContextualLogger
17
27
  if log_level.is_a?(Integer) && (Logger::Severity::DEBUG..Logger::Severity::UNKNOWN).include?(log_level)
18
28
  log_level
19
29
  else
20
- case log_level.to_s.downcase
21
- when 'debug'
22
- Logger::Severity::DEBUG
23
- when 'info'
24
- Logger::Severity::INFO
25
- when 'warn'
26
- Logger::Severity::WARN
27
- when 'error'
28
- Logger::Severity::ERROR
29
- when 'fatal'
30
- Logger::Severity::FATAL
31
- when 'unknown'
32
- Logger::Severity::UNKNOWN
33
- else
30
+ LOG_LEVEL_NAMES_TO_SEVERITY[log_level.to_s.downcase.to_sym] or
34
31
  raise ArgumentError, "invalid log level: #{log_level.inspect}"
35
- end
36
32
  end
37
33
  end
38
34
 
@@ -72,45 +68,54 @@ module ContextualLogger
72
68
  Context::Handler.current_context
73
69
  end
74
70
 
75
- def debug(message = nil, context = {})
76
- add(Logger::Severity::DEBUG, message.nil? && block_given? ? yield : message, **context)
77
- end
78
-
79
- def info(message = nil, context = {})
80
- add(Logger::Severity::INFO, message.nil? && block_given? ? yield : message, **context)
81
- end
82
-
83
- def warn(message = nil, context = {})
84
- add(Logger::Severity::WARN, message.nil? && block_given? ? yield : message, **context)
85
- end
86
-
87
- def error(message = nil, context = {})
88
- add(Logger::Severity::ERROR, message.nil? && block_given? ? yield : message, **context)
89
- end
71
+ # In the methods generated below, we assume that presence of context means new code that is
72
+ # aware of ContextualLogger...and that that code never uses progname.
73
+ # This is important because we only get 3 args total (not including &block) passed to `add`,
74
+ # in order to be compatible with classic implementations like in the plain ::Logger and
75
+ # ActiveSupport::Logger.broadcast.
90
76
 
91
- def fatal(message = nil, context = {})
92
- add(Logger::Severity::FATAL, message.nil? && block_given? ? yield : message, **context)
93
- end
77
+ # Note that we can't yield before `add` because `add` might skip it based on log_level. And we can't check
78
+ # log_level here because we might be running in ActiveSupport::Logging.broadcast which has multiple
79
+ # loggers, each with their own log_level.
94
80
 
95
- def unknown(message = nil, context = {})
96
- add(Logger::Severity::UNKNOWN, message.nil? && block_given? ? yield : message, **context)
81
+ LOG_LEVEL_NAMES_TO_SEVERITY.each do |method_name, log_level|
82
+ class_eval(<<~EOS, __FILE__, __LINE__ + 1)
83
+ def #{method_name}(arg = nil, **context, &block)
84
+ if context.empty?
85
+ add(#{log_level}, nil, arg, &block)
86
+ else
87
+ if arg.nil?
88
+ add(#{log_level}, nil, context, &block)
89
+ elsif block
90
+ add(#{log_level}, nil, context.merge(progname: arg), &block)
91
+ else
92
+ add(#{log_level}, arg, context)
93
+ end
94
+ end
95
+ end
96
+ EOS
97
97
  end
98
98
 
99
99
  def log_level_enabled?(severity)
100
100
  severity >= level
101
101
  end
102
102
 
103
- def add(init_severity, message = nil, init_progname = nil, **context) # Ruby will prefer to match hashes up to last ** argument
104
- severity = init_severity || UNKNOWN
103
+ # Note that this interface needs to stay compatible with the underlying ::Logger#add interface,
104
+ # which is: def add(severity, message = nil, progname = nil)
105
+ def add(arg_severity, arg1 = nil, arg2 = nil, **context) # Ruby will prefer to match hashes up to last ** argument
106
+ severity = arg_severity || UNKNOWN
105
107
  if log_level_enabled?(severity)
106
- progname = init_progname || @progname
107
- if message.nil?
108
+ if arg1.nil?
108
109
  if block_given?
109
110
  message = yield
111
+ progname = arg2 || context.delete(:progname) || @progname
110
112
  else
111
- message = init_progname
113
+ message = arg2
112
114
  progname = @progname
113
115
  end
116
+ else
117
+ message = arg1
118
+ progname = arg2 || @progname
114
119
  end
115
120
  write_entry_to_log(severity, Time.now, progname, message, context: current_context_for_thread.deep_merge(context))
116
121
  end
@@ -133,21 +138,25 @@ module ContextualLogger
133
138
  end
134
139
 
135
140
  def format_message(severity, timestamp, progname, message, context: {})
141
+ normalized_message = ContextualLogger.normalize_message(message)
142
+ normalized_progname = ContextualLogger.normalize_message(progname) unless progname.nil?
136
143
  if @formatter
137
- @formatter.call(severity, timestamp, progname, { message: ContextualLogger.normalize_message(message), **context })
144
+ @formatter.call(severity, timestamp, normalized_progname, { message: normalized_message }.merge!(context))
138
145
  else
139
- "#{basic_message_formatting(severity, timestamp, progname, message, context: context).to_json}\n"
146
+ "#{basic_json_log_entry(severity, timestamp, normalized_progname, normalized_message, context: context)}\n"
140
147
  end
141
148
  end
142
149
 
143
- def basic_message_formatting(severity, timestamp, progname, message, context:)
150
+ def basic_json_log_entry(severity, timestamp, normalized_progname, normalized_message, context:)
144
151
  message_hash = {
145
- message: ContextualLogger.normalize_message(message),
152
+ message: normalized_progname ? "#{normalized_progname}: #{normalized_message}" : normalized_message,
146
153
  severity: severity,
147
154
  timestamp: timestamp
148
155
  }
149
- message_hash[:progname] = progname if progname
150
- message_hash.merge(context)
156
+ message_hash[:progname] = normalized_progname if normalized_progname
157
+
158
+ # merge! is faster and OK here since message_hash is still local only to this method
159
+ message_hash.merge!(context).to_json
151
160
  end
152
161
  end
153
162
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/hash/keys'
4
+
3
5
  module ContextualLogger
4
6
  # A logger that deep_merges additional context and then delegates to the given logger.
5
7
  # Keeps it own log level (called override_level) that may be set independently of the logger it delegates to.
@@ -13,7 +15,7 @@ module ContextualLogger
13
15
  logger.is_a?(LoggerMixin) or raise ArgumentError, "logger must include ContextualLogger::LoggerMixin (got #{logger.inspect})"
14
16
  @logger = logger
15
17
  self.level = level
16
- @context = context
18
+ @context = normalize_context(context)
17
19
  @merged_context_cache = {} # so we don't have to merge every time
18
20
  end
19
21
 
@@ -36,6 +38,29 @@ module ContextualLogger
36
38
  @logger.write_entry_to_log(severity, timestamp, progname, message, context: merged_context)
37
39
  end
38
40
 
41
+ private
42
+
43
+ def normalize_context(context)
44
+ if warn_on_string_keys(context)
45
+ context.deep_symbolize_keys
46
+ else
47
+ context
48
+ end
49
+ end
50
+
51
+ def warn_on_string_keys(context)
52
+ if deep_key_has_string?(context)
53
+ ActiveSupport::Deprecation.warn('Context keys must use symbols not strings. This will be asserted as of contextual_logger v1.0.0')
54
+ end
55
+ end
56
+
57
+ def deep_key_has_string?(hash)
58
+ hash.any? do |key, value|
59
+ key.is_a?(String) ||
60
+ (value.is_a?(Hash) && deep_key_has_string?(value))
61
+ end
62
+ end
63
+
39
64
  class << self
40
65
  def for_log_source(logger, log_source, level: nil)
41
66
  new(logger, { log_source: log_source }, level: level)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ContextualLogger
4
- VERSION = '0.9.0.pre.1'
4
+ VERSION = '0.11.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contextual_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.pre.1
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Ebentier
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-17 00:00:00.000000000 Z
11
+ date: 2020-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -56,7 +56,7 @@ licenses:
56
56
  metadata:
57
57
  source_code_uri: https://github.com/Invoca/contextual_logger
58
58
  allowed_push_host: https://rubygems.org
59
- post_install_message:
59
+ post_install_message:
60
60
  rdoc_options: []
61
61
  require_paths:
62
62
  - lib
@@ -67,12 +67,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
67
  version: '0'
68
68
  required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  requirements:
70
- - - ">"
70
+ - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 1.3.1
72
+ version: '0'
73
73
  requirements: []
74
74
  rubygems_version: 3.0.3
75
- signing_key:
75
+ signing_key:
76
76
  specification_version: 4
77
77
  summary: Add context to your logger
78
78
  test_files: []