class Logtail::CurrentContext

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 necessary data needed to relate your log lines.

Constants

THREAD_NAMESPACE

Public Class Methods

add(*args) click to toggle source

Convenience method for {CurrentContext#add}. See {CurrentContext#add} for more info.

# File lib/logtail/current_context.rb, line 23
def add(*args)
  instance.add(*args)
end
fetch(*args) click to toggle source

Convenience method for {CurrentContext#fetch}. See {CurrentContext#fetch} for more info.

# File lib/logtail/current_context.rb, line 28
def fetch(*args)
  instance.fetch(*args)
end
instance() click to toggle source

Implements the Singleton pattern in a thread specific way. Each thread receives its own context.

# File lib/logtail/current_context.rb, line 18
def instance
  Thread.current[THREAD_NAMESPACE] ||= new
end
remove(*args) click to toggle source

Convenience method for {CurrentContext#remove}. See {CurrentContext#remove} for more info.

# File lib/logtail/current_context.rb, line 33
def remove(*args)
  instance.remove(*args)
end
reset(*args) click to toggle source

Convenience method for {CurrentContext#reset}. See {CurrentContext#reset} for more info.

# File lib/logtail/current_context.rb, line 38
def reset(*args)
  instance.reset(*args)
end
with(*args, &block) click to toggle source

Convenience method for {CurrentContext#with}. See {CurrentContext#with} for more info.

# File lib/logtail/current_context.rb, line 43
def with(*args, &block)
  instance.with(*args, &block)
end

Public Instance Methods

add(*objects) click to toggle source

Adds contexts but does not remove them. See {#with} for automatic maintenance and {#remove} to remove them yourself.

@note Because context is included with every log line, it is recommended that you limit this

to only necessary data.
# File lib/logtail/current_context.rb, line 53
def add(*objects)
  objects.each do |object|
    hash.merge!(object.to_hash)
  end
  expire_cache!
  self
end
fetch(*args) click to toggle source

Fetch a specific context by key.

# File lib/logtail/current_context.rb, line 62
def fetch(*args)
  hash.fetch(*args)
end
remove(*keys) click to toggle source

Removes a context. If you wish to remove by key, or some other way, use {#hash} and modify the hash accordingly.

# File lib/logtail/current_context.rb, line 68
def remove(*keys)
  keys.each do |keys|
    hash.delete(keys)
  end
  expire_cache!
  self
end
replace(hash) click to toggle source
# File lib/logtail/current_context.rb, line 76
def replace(hash)
  @hash = hash
  expire_cache!
  self
end
reset() click to toggle source

Resets the context to be blank. Use this carefully! This will remove any context, include context that is automatically included with Logtail.

# File lib/logtail/current_context.rb, line 84
def reset
  hash.clear
  expire_cache!
  self
end
snapshot() click to toggle source

Snapshots the current context so that you get a moment in time representation of the context, since the context can change as execution proceeds. Note that individual contexts should be immutable, and we implement snapshot caching as a result of this assumption.

# File lib/logtail/current_context.rb, line 93
def snapshot
  @snapshot ||= hash.clone
end
with(*objects) { || ... } click to toggle source

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 necessary data.

@example Adding a custom context

Logtail::CurrentContext.with({build: {version: "1.0.0"}}) do
  # ... anything logged here will include the context ...
end

@note Any custom context needs to have a single root key to be valid. i.e. instead of:

Logtail::CurrentContext.with(job_id: "123", job_name: "Refresh User Account")

do

Logtail::CurrentContext.with(job: {job_id: "123", job_name: "Refresh User Account"})

@example Adding multiple contexts

Logtail::CurrentContext.with(context1, context2) { ... }
# File lib/logtail/current_context.rb, line 116
def with(*objects)
  old_hash = hash.clone
  begin
    add(*objects)
    yield
  ensure
    replace(old_hash)
  end
end

Private Instance Methods

build_initial_hash() click to toggle source

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.

# File lib/logtail/current_context.rb, line 135
def build_initial_hash
  new_hash = {}

  # Release context
  release_context = Util::NonNilHashBuilder.build do |h|
    h.add(:commit_hash, ENV['RELEASE_COMMIT'] || ENV['HEROKU_SLUG_COMMIT'])
    h.add(:created_at, ENV['RELEASE_CREATED_AT'] || ENV['HEROKU_RELEASE_CREATED_AT'])
    h.add(:version, ENV['RELEASE_VERSION'] || ENV['HEROKU_RELEASE_VERSION'])
  end

  if release_context != {}
    new_hash.merge!({release: release_context})
  end

  # System context
  hostname = Socket.gethostname.force_encoding('UTF-8')
  pid = Process.pid
  system_context = Contexts::System.new(hostname: hostname, pid: pid)
  new_hash.merge!(system_context.to_hash)

  # Runtime context
  thread_object_id = Thread.current.object_id
  runtime_context = {thread_id: thread_object_id}
  new_hash.merge!({runtime: runtime_context})

  new_hash
end
expire_cache!() click to toggle source

Hook to clear any caching implement in this class

# File lib/logtail/current_context.rb, line 164
def expire_cache!
  @snapshot = nil
end
hash() click to toggle source

The internal hash that is maintained. Use {#with} and {#add} for hash maintenance.

# File lib/logtail/current_context.rb, line 128
def hash
  @hash ||= build_initial_hash
end