-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TECH-12593:make global_context global, but just for that logger instance #72
Conversation
…en Thread/Fiber has no setting; add specs for Thread/Fiber
…xin so it can take into account the object_id
87e79a3
to
e0f49aa
Compare
lib/contextual_logger/context.rb
Outdated
module Context | ||
def thread_context_for_logger_instance | ||
# We include the object_id here to make these thread/fiber locals unique per logger instance. | ||
@thread_context_for_logger_instance ||= "ContextualLogger::Context.context_for_#{object_id}".to_sym |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty sneaky. It's the only way I could think to get Thread/Fiber-locals to also be unique for each enclosing Logger
. Notice that they won't get cleaned up when the Logger
goes out of scope. I don't think it's likely that anyone would create a huge number of Logger
s, so we should be fine.
…t_for_thread to default to global_context
…current_context_override, current_context]
Co-authored-by: James Ebentier <[email protected]>
…context_lock_message to prohibit changes after startup
…o have specs for and follow precedence (especially with_context at 2 levels)
@@ -16,7 +23,13 @@ def initialize(logger, context, level: nil) | |||
@logger = logger | |||
self.level = level | |||
@context = normalize_context(context) | |||
@merged_context_cache = {} # so we don't have to merge every time | |||
end | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jebentier This is still a bug. I realized it's one of the reasons I had headed down the path of tracking the global_context
instance for equals?
--that would be necessary in order to fix this bug. But it would be really complicated. And this bug isn't new. The code in this branch works much better in that it handles with_context
on both the original logger as well as the LoggerWithContext
; it just doesn't handle if you repeat the former after having logged something. That seems very unlikely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this seems unlikely and that the code required to fix this limitation is more complex than we want for this logger. Thank you for documenting it so we’re aware moving forward.
@jebentier Can you review the new changes here since you last reviewed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new changes look good. Thanks for working through this. Have we been able to confirm that this resolves the bugs we were seeing when using this with Sidekiq?
@@ -16,7 +23,13 @@ def initialize(logger, context, level: nil) | |||
@logger = logger | |||
self.level = level | |||
@context = normalize_context(context) | |||
@merged_context_cache = {} # so we don't have to merge every time | |||
end | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this seems unlikely and that the code required to fix this limitation is more complex than we want for this logger. Thank you for documenting it so we’re aware moving forward.
… to current_context_override= and include context_override
end | ||
|
||
def current_context_override=(context_override) | ||
ContextualLogger.global_context_lock_message ||= "ContextualLogger::Context.current_context_override set for #{self.class.name} #{object_id}: #{context_override.inspect}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Layout/LineLength: Line is too long. [176/150]
Yes, the previous version did. But I'll be checking again with this latest version. |
@jebentier FYI, I ran the final QA on a kube-platform and confirmed that the Sidekiq logging always contains the full context, once we get fully bootstrapped. As before there's a small window at the start when a ServiceDiscovery thread starts logging before the LoggerMixin logger is in place. That's not new, and I think we can live with it. Here are the first 3 examples from a task pod. Note that the inline context is winding up in the
|
While investigating missing log contexts, we found a few problems:
global_context
was stored into a Thread/Fiber-local... so it would not be applied when running on a different Thread or Fiber.global_context
andcurrent_context
were stored in a Thread/Fiber-local... meaning that they would be shared across different instance of theLogger
, if you had them.Context::Handler
rather than simply theContext
.The changes in this branch are:
global_context
is stored in the logger itself, so it is global to that logger, only.LoggerWithContext
delegates theglobal_context
to thecurrent_context
of the base logger it was created with.current_context
comes from a Thread/Fiber local where the key to the name includes the logger'sobject_id
. So it can be different for multiple logger instances.current_context
defaults tonil
, and may also be set tonil
. Whenever it has anil
value, thecurrent_context
defaults to theglobal_context
for that logger.Context
is now cleanly separated fromContextHandler
.Note: best reviewed with Hide whitespace.