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