class Cabin::Channel

A wonderful channel for logging.

You can log normal messages through here, but you should be really shipping structured data. A message is just part of your data. “An error occurred” - in what? when? why? how?

Logging channels support the usual 'info' 'warn' and other logger methods provided by Ruby's stdlib Logger class

It additionally allows you to store arbitrary pieces of data in it like a hash, so your call stack can do be this:

@logger = Cabin::Channel.new
rubylog = Logger.new(STDOUT) # ruby's stlib logger
@logger.subscribe(rubylog)

def foo(val)
  context = @logger.context()
  context[:foo] = val
  context[:example] = 100
  bar()

  # Clear any context we just wanted bar() to know about
  context.clear()

  @logger.info("Done in foo")
end

def bar
  @logger.info("Fizzle")
end

The result:

I, [2011-10-11T01:00:57.993200 #1209]  INFO -- : {:timestamp=>"2011-10-11T01:00:57.992353-0700", :foo=>"Hello", :example=>100, :message=>"Fizzle", :level=>:info}
I, [2011-10-11T01:00:57.993575 #1209]  INFO -- : {:timestamp=>"2011-10-11T01:00:57.993517-0700", :message=>"Done in foo", :level=>:info}

Attributes

metrics[RW]

All channels come with a metrics provider.

Public Class Methods

each() { |identifier, channel| ... } click to toggle source
# File lib/cabin/channel.rb, line 70
def each(&block)
  @channel_lock.synchronize do
    @channels.each do |identifier, channel|
      yield identifier, channel
    end
  end
end
filter(&block) click to toggle source

Register a new filter. The block is passed the event. It is expected to modify that event or otherwise do nothing.

# File lib/cabin/channel.rb, line 85
def filter(&block)
  @filters ||= []
  @filters << block
end
filters() click to toggle source

Get a list of filters included in this class.

# File lib/cabin/channel.rb, line 79
def filters
  @filters ||= []
end
get(identifier=$0) click to toggle source

Get a channel for a given identifier. If this identifier has never been used, a new channel is created for it. The default identifier is the application executable name.

This is useful for using the same Cabin::Channel across your entire application.

# File lib/cabin/channel.rb, line 62
def get(identifier=$0)
  return @channel_lock.synchronize { @channels[identifier] }
end
new() click to toggle source

Create a new logging channel. The default log level is 'info'

# File lib/cabin/channel.rb, line 104
def initialize
  @subscribers = {}
  @data = {}
  @level = :info
  @metrics = Cabin::Metrics.new
  @metrics.channel = self
  @subscriber_lock = Mutex.new
end
set(identifier, channel) click to toggle source
# File lib/cabin/channel.rb, line 66
def set(identifier, channel)
  return @channel_lock.synchronize { @channels[identifier] = channel }
end

Public Instance Methods

[](key) click to toggle source

Get a context value by name.

# File lib/cabin/channel.rb, line 144
def [](key)
  @data[key]
end
[]=(key, value) click to toggle source

Set some contextual map value

# File lib/cabin/channel.rb, line 139
def []=(key, value)
  @data[key] = value
end
context() click to toggle source
# File lib/cabin/channel.rb, line 181
def context
  ctx = Cabin::Context.new(self)
  return ctx
end
publish(data, &block) click to toggle source

Publish data to all outputs. The data is expected to be a hash or a string.

A new hash is generated based on the data given. If data is a string, then it will be added to the new event hash with key :message.

A special key :timestamp is set at the time of this method call. The value is a string ISO8601 timestamp with microsecond precision.

# File lib/cabin/channel.rb, line 160
def publish(data, &block)
  event = {}
  self.class.filters.each do |filter|
    filter.call(event)
  end

  if data.is_a?(String)
    event[:message] = data
  else
    event.merge!(data)
  end
  event.merge!(@data) # Merge any logger context

  @subscriber_lock.synchronize do
    @subscribers.each do |id, output|
      append =  block_given? ? block.call(output, event) : true
      output << event if append
    end
  end
end
remove(key) click to toggle source

Remove a context value by name.

# File lib/cabin/channel.rb, line 149
def remove(key)
  @data.delete(key)
end
subscribe(output) click to toggle source

Subscribe a new input New events will be sent to the subscriber using the '<<' method

foo << event

Returns a subscription id you can use later to unsubscribe

# File lib/cabin/channel.rb, line 118
def subscribe(output)
  # Wrap ruby stdlib Logger if given.
  if output.is_a?(::Logger)
    output = Cabin::Outputs::StdlibLogger.new(output)
  elsif output.is_a?(::IO)
    output = Cabin::Outputs::IO.new(output)
  end
  @subscriber_lock.synchronize do
    @subscribers[output.object_id] = output
  end
  return output.object_id
end
unsubscribe(id) click to toggle source

Unsubscribe. Takes a 'subscription id' as returned by the subscribe method

# File lib/cabin/channel.rb, line 132
def unsubscribe(id)
  @subscriber_lock.synchronize do
    @subscribers.delete(id)
  end
end

Private Instance Methods

dataify(data) click to toggle source
# File lib/cabin/channel.rb, line 186
def dataify(data)
  if data.is_a?(String)
    data = { :message => data }
  end
  return data
end