lib/timber/current_context.rb in timber-2.1.0.rc2 vs lib/timber/current_context.rb in timber-2.1.0.rc3
- old
+ new
@@ -1,22 +1,25 @@
-require "singleton"
-
+require "timber/config"
require "timber/contexts/release"
module Timber
# Holds the current context in a thread safe memory storage. This context is
# appended to every log line. Think of context as join data between your log lines,
# allowing you to relate them and filter them appropriately.
#
# @note Because context is appended to every log line, it is recommended that you limit this
# to only neccessary data needed to relate your log lines.
class CurrentContext
- include Singleton
-
THREAD_NAMESPACE = :_timber_current_context.freeze
class << self
+ # Impelements the Singleton pattern in a thread specific way. Each thread receives
+ # its own context.
+ def instance
+ Thread.current[THREAD_NAMESPACE] ||= new
+ end
+
# Convenience method for {CurrentContext#with}. See {CurrentContext#with} for more info.
def with(*args, &block)
instance.with(*args, &block)
end
@@ -39,21 +42,10 @@
def reset(*args)
instance.reset(*args)
end
end
- # Instantiates a new object, automatically adding context based on env variables (if present).
- # For example, the {Contexts::ReleaseContext} is automatically added if the proper environment
- # variables are present. Please see that class for more details.
- def initialize
- super
- release_context = Contexts::Release.from_env
- if release_context
- add(release_context)
- end
- end
-
# Adds a context and then removes it when the block is finished executing.
#
# @note Because context is included with every log line, it is recommended that you limit this
# to only neccessary data.
#
@@ -87,20 +79,11 @@
#
# @note Because context is included with every log line, it is recommended that you limit this
# to only neccessary data.
def add(*objects)
objects.each do |object|
- context = Contexts.build(object) # Normalizes objects into a Timber::Context descendant.
- key = context.keyspace
- json = context.as_json # Convert to json now so that we aren't doing it for every line
- if key == :custom
- # Custom contexts are merged into the space
- hash[key] ||= {}
- hash[key].merge!(json)
- else
- hash[key] = json
- end
+ add_to(hash, object)
end
expire_cache!
self
end
@@ -149,10 +132,36 @@
end
private
# The internal hash that is maintained. Use {#with} and {#add} for hash maintenance.
def hash
- Thread.current[THREAD_NAMESPACE] ||= {}
+ @hash ||= build_initial_hash
+ end
+
+ # Builds the initial hash. This is extract into a method to support a threaded
+ # environment. Each thread holds it's own context and also needs to instantiate
+ # it's hash properly.
+ def build_initial_hash
+ new_hash = {}
+ release_context = Contexts::Release.from_env
+ if release_context
+ add_to(new_hash, release_context)
+ end
+ new_hash
+ end
+
+ def add_to(hash, object)
+ context = Contexts.build(object) # Normalizes objects into a Timber::Context descendant.
+ key = context.keyspace
+ json = context.as_json # Convert to json now so that we aren't doing it for every line
+ if key == :custom
+ # Custom contexts are merged into the space
+ hash[key] ||= {}
+ hash[key].merge!(json)
+ else
+ hash[key] = json
+ end
+ hash
end
# Hook to clear any caching implement in this class
def expire_cache!
@snapshot = nil