contextual_logger 1.2.0.colin.6 → 1.2.0.pre.1
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/lib/contextual_logger/context/handler.rb +28 -0
- data/lib/contextual_logger/logger_with_context.rb +4 -17
- data/lib/contextual_logger/version.rb +1 -1
- data/lib/contextual_logger.rb +16 -43
- metadata +3 -5
- data/lib/contextual_logger/context.rb +0 -21
- data/lib/contextual_logger/context_handler.rb +0 -14
- data/lib/contextual_logger/global_context_lock_message.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5ee8cad9d62ca2d8aeec81f2626b56b4aa6b1db2c6b626518a4708d590ddb4c
|
4
|
+
data.tar.gz: 71be08f271be68de04f942abfa301a2a5ec54be54d0399bb01db8bcf52a07037
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b455d41a46223ea9c6e2583a7d03d81940743215c4eb1dd5977d6ffc8f8ffcb618ce27a3b975fed211987b592e0cfdbc1e691ceef155641764c5d8938da0679
|
7
|
+
data.tar.gz: 6600b357b1dc7b25ee8e746f17280a7e74ac184b38a03340f48e835659259135321a0c0ff0d7c387a7b06b9804b82ad63f8b76a911790a6fb5c2f99a61c0cfdc
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ContextualLogger
|
4
|
+
module Context
|
5
|
+
class Handler
|
6
|
+
THREAD_CONTEXT_NAMESPACE = 'ContextualLoggerCurrentLoggingContext'
|
7
|
+
|
8
|
+
attr_reader :previous_context, :context
|
9
|
+
|
10
|
+
def self.current_context
|
11
|
+
Thread.current[THREAD_CONTEXT_NAMESPACE] || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(context, previous_context: nil)
|
15
|
+
@previous_context = previous_context || self.class.current_context
|
16
|
+
@context = context
|
17
|
+
end
|
18
|
+
|
19
|
+
def set!
|
20
|
+
Thread.current[THREAD_CONTEXT_NAMESPACE] = context
|
21
|
+
end
|
22
|
+
|
23
|
+
def reset!
|
24
|
+
Thread.current[THREAD_CONTEXT_NAMESPACE] = previous_context
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -6,13 +6,6 @@ module ContextualLogger
|
|
6
6
|
# A logger that deep_merges additional context and then delegates to the given logger.
|
7
7
|
# Keeps it own log level (called override_level) that may be set independently of the logger it delegates to.
|
8
8
|
# If override_level is non-nil, it takes precedence; if it is nil (the default), then it delegates to the logger.
|
9
|
-
#
|
10
|
-
# Context Precedence:
|
11
|
-
# 1. inline **context passed to the logger method
|
12
|
-
# 2. `with_context` overrides on this LoggerWithContext object
|
13
|
-
# 3. context passed to this LoggerWithContext constructor
|
14
|
-
# 4. `with_context` overrides on the logger passed to this constructor
|
15
|
-
# 5. `global_context` set on the logger passed to this constructor
|
16
9
|
class LoggerWithContext
|
17
10
|
include LoggerMixin
|
18
11
|
|
@@ -23,13 +16,7 @@ module ContextualLogger
|
|
23
16
|
@logger = logger
|
24
17
|
self.level = level
|
25
18
|
@context = normalize_context(context)
|
26
|
-
|
27
|
-
|
28
|
-
# TODO: It's a (small) bug that the global_context is memoized at this point. There's a chance that the @logger.current_context
|
29
|
-
# changes after this because of an enclosing @logger.with_context block. If that happens, we'll miss that extra context.
|
30
|
-
# The tradeoff is that we don't want to keep calling deep_merge.
|
31
|
-
def global_context
|
32
|
-
@global_context ||= @logger.current_context.deep_merge(@context) # this will include any with_context overrides on the `logger`
|
19
|
+
@merged_context_cache = {} # so we don't have to merge every time
|
33
20
|
end
|
34
21
|
|
35
22
|
def level
|
@@ -42,10 +29,10 @@ module ContextualLogger
|
|
42
29
|
|
43
30
|
def write_entry_to_log(severity, timestamp, progname, message, context:)
|
44
31
|
merged_context =
|
45
|
-
if
|
46
|
-
|
32
|
+
if @merged_context_cache.size >= 1000 # keep this cache memory use finite
|
33
|
+
@merged_context_cache[context] || @context.deep_merge(context)
|
47
34
|
else
|
48
|
-
|
35
|
+
@merged_context_cache[context] ||= @context.deep_merge(context)
|
49
36
|
end
|
50
37
|
|
51
38
|
@logger.write_entry_to_log(severity, timestamp, progname, message, context: merged_context)
|
data/lib/contextual_logger.rb
CHANGED
@@ -4,9 +4,7 @@ require 'active_support'
|
|
4
4
|
require 'active_support/core_ext/module/delegation'
|
5
5
|
require 'json'
|
6
6
|
require_relative './contextual_logger/redactor'
|
7
|
-
require_relative './contextual_logger/context'
|
8
|
-
require_relative './contextual_logger/context_handler'
|
9
|
-
require_relative './contextual_logger/global_context_lock_message'
|
7
|
+
require_relative './contextual_logger/context/handler'
|
10
8
|
|
11
9
|
module ContextualLogger
|
12
10
|
LOG_LEVEL_NAMES_TO_SEVERITY =
|
@@ -44,37 +42,16 @@ module ContextualLogger
|
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
47
|
-
# Context Precedence when this is mixed into a logger:
|
48
|
-
# 1. inline **context passed to the logger method
|
49
|
-
# 2. `with_context` overrides on the logger object
|
50
|
-
# 3. `global_context` set on the logger passed to this constructor
|
51
45
|
module LoggerMixin
|
52
|
-
include Context
|
53
|
-
|
54
46
|
delegate :register_secret, :register_secret_regex, to: :redactor
|
55
47
|
|
56
|
-
def global_context
|
57
|
-
@global_context ||= Context::EMPTY_CONTEXT
|
58
|
-
end
|
59
|
-
|
60
48
|
def global_context=(context)
|
61
|
-
|
62
|
-
raise ::ContextualLogger::GlobalContextIsLocked, global_context_lock_message
|
63
|
-
end
|
64
|
-
@global_context = context.freeze
|
49
|
+
Context::Handler.new(context).set!
|
65
50
|
end
|
66
51
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
# TODO: Deprecate current_context_for_thread in v2.0.
|
72
|
-
alias current_context_for_thread current_context
|
73
|
-
|
74
|
-
def with_context(stacked_context)
|
75
|
-
context_handler = ContextHandler.new(self, current_context_override)
|
76
|
-
self.current_context_override = deep_merge_with_current_context(stacked_context)
|
77
|
-
|
52
|
+
def with_context(context)
|
53
|
+
context_handler = Context::Handler.new(current_context_for_thread.deep_merge(context))
|
54
|
+
context_handler.set!
|
78
55
|
if block_given?
|
79
56
|
begin
|
80
57
|
yield
|
@@ -82,11 +59,15 @@ module ContextualLogger
|
|
82
59
|
context_handler.reset!
|
83
60
|
end
|
84
61
|
else
|
85
|
-
# If no block given,
|
62
|
+
# If no block given, the context handler is returned to the caller so they can handle reset! themselves.
|
86
63
|
context_handler
|
87
64
|
end
|
88
65
|
end
|
89
66
|
|
67
|
+
def current_context_for_thread
|
68
|
+
Context::Handler.current_context
|
69
|
+
end
|
70
|
+
|
90
71
|
# In the methods generated below, we assume that presence of context means new code that is
|
91
72
|
# aware of ContextualLogger...and that that code never uses progname.
|
92
73
|
# This is important because we only get 3 args total (not including &block) passed to `add`,
|
@@ -121,7 +102,7 @@ module ContextualLogger
|
|
121
102
|
|
122
103
|
# Note that this interface needs to stay compatible with the underlying ::Logger#add interface,
|
123
104
|
# which is: def add(severity, message = nil, progname = nil)
|
124
|
-
def add(arg_severity, arg1 = nil, arg2 = nil, **context) # Ruby will prefer to match hashes to last argument
|
105
|
+
def add(arg_severity, arg1 = nil, arg2 = nil, **context) # Ruby will prefer to match hashes up to last ** argument
|
125
106
|
severity = arg_severity || UNKNOWN
|
126
107
|
if log_level_enabled?(severity)
|
127
108
|
if arg1.nil?
|
@@ -136,7 +117,7 @@ module ContextualLogger
|
|
136
117
|
message = arg1
|
137
118
|
progname = arg2 || @progname
|
138
119
|
end
|
139
|
-
write_entry_to_log(severity, Time.now, progname, message, context:
|
120
|
+
write_entry_to_log(severity, Time.now, progname, message, context: current_context_for_thread.deep_merge(context))
|
140
121
|
end
|
141
122
|
|
142
123
|
true
|
@@ -160,7 +141,7 @@ module ContextualLogger
|
|
160
141
|
normalized_message = ContextualLogger.normalize_message(message)
|
161
142
|
normalized_progname = ContextualLogger.normalize_message(progname) unless progname.nil?
|
162
143
|
if @formatter
|
163
|
-
@formatter.call(severity, timestamp, normalized_progname, { message: normalized_message
|
144
|
+
@formatter.call(severity, timestamp, normalized_progname, { message: normalized_message }.merge!(context))
|
164
145
|
else
|
165
146
|
"#{basic_json_log_entry(severity, timestamp, normalized_progname, normalized_message, context: context)}\n"
|
166
147
|
end
|
@@ -170,20 +151,12 @@ module ContextualLogger
|
|
170
151
|
message_hash = {
|
171
152
|
message: normalized_progname ? "#{normalized_progname}: #{normalized_message}" : normalized_message,
|
172
153
|
severity: severity,
|
173
|
-
timestamp: timestamp
|
174
|
-
**context
|
154
|
+
timestamp: timestamp
|
175
155
|
}
|
176
156
|
message_hash[:progname] = normalized_progname if normalized_progname
|
177
157
|
|
178
|
-
message_hash
|
179
|
-
|
180
|
-
|
181
|
-
def deep_merge_with_current_context(stacked_context)
|
182
|
-
if stacked_context.any?
|
183
|
-
current_context.deep_merge(stacked_context)
|
184
|
-
else
|
185
|
-
current_context
|
186
|
-
end
|
158
|
+
# merge! is faster and OK here since message_hash is still local only to this method
|
159
|
+
message_hash.merge!(context).to_json
|
187
160
|
end
|
188
161
|
end
|
189
162
|
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: 1.2.0.
|
4
|
+
version: 1.2.0.pre.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Ebentier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09
|
11
|
+
date: 2023-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -45,9 +45,7 @@ extensions: []
|
|
45
45
|
extra_rdoc_files: []
|
46
46
|
files:
|
47
47
|
- lib/contextual_logger.rb
|
48
|
-
- lib/contextual_logger/context.rb
|
49
|
-
- lib/contextual_logger/context_handler.rb
|
50
|
-
- lib/contextual_logger/global_context_lock_message.rb
|
48
|
+
- lib/contextual_logger/context/handler.rb
|
51
49
|
- lib/contextual_logger/logger_with_context.rb
|
52
50
|
- lib/contextual_logger/overrides/active_support/tagged_logging/formatter.rb
|
53
51
|
- lib/contextual_logger/redactor.rb
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ContextualLogger
|
4
|
-
module Context
|
5
|
-
EMPTY_CONTEXT = {}.freeze
|
6
|
-
|
7
|
-
def thread_context_key_for_logger_instance
|
8
|
-
# We include the object_id here to make these thread/fiber locals unique per logger instance.
|
9
|
-
@thread_context_key_for_logger_instance ||= "ContextualLogger::Context.context_for_#{object_id}".to_sym
|
10
|
-
end
|
11
|
-
|
12
|
-
def current_context_override
|
13
|
-
Thread.current[thread_context_key_for_logger_instance]
|
14
|
-
end
|
15
|
-
|
16
|
-
def current_context_override=(context_override)
|
17
|
-
ContextualLogger.global_context_lock_message ||= "ContextualLogger::Context.current_context_override set for #{self.class.name} #{object_id}: #{context_override.inspect}"
|
18
|
-
Thread.current[thread_context_key_for_logger_instance] = context_override.freeze
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ContextualLogger
|
4
|
-
class ContextHandler
|
5
|
-
def initialize(instance, previous_context_override)
|
6
|
-
@instance = instance
|
7
|
-
@previous_context_override = previous_context_override
|
8
|
-
end
|
9
|
-
|
10
|
-
def reset!
|
11
|
-
@instance.current_context_override = @previous_context_override
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|