lib/cabin/channel.rb in cabin-0.4.2 vs lib/cabin/channel.rb in cabin-0.4.3

- old
+ new

@@ -1,8 +1,9 @@ require "cabin/mixins/logger" +require "cabin/mixins/timestamp" +require "cabin/mixins/timer" require "cabin/namespace" -require "cabin/timer" require "cabin/context" require "cabin/outputs/stdlib-logger" require "cabin/outputs/io" require "cabin/metrics" require "logger" @@ -43,30 +44,46 @@ # # 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} # class Cabin::Channel + class << self + # 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. + def get(identifier=$0) + @channels ||= Hash.new { |h,k| h[k] = Cabin::Channel.new } + return @channels[identifier] + end # def Cabin::Channel.get + + # Get a list of filters included in this class. + def filters + @filters ||= [] + end # def Cabin::Channel.filters + + # Register a new filter. The block is passed the event. It is expected to + # modify that event or otherwise do nothing. + def filter(&block) + @filters ||= [] + @filters << block + end + end # class << self + include Cabin::Mixins::Logger + include Cabin::Mixins::Timestamp + include Cabin::Mixins::Timer # All channels come with a metrics provider. attr_accessor :metrics + + private - # 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. - public - def self.get(identifier=$0) - @channels ||= Hash.new { |h,k| h[k] = Cabin::Channel.new } - return @channels[identifier] - end # def Cabin::Channel.get - # Create a new logging channel. # The default log level is 'info' - public def initialize @outputs = [] @data = {} @level = :info @metrics = Cabin::Metrics.new @@ -74,11 +91,10 @@ end # def initialize # Subscribe a new input # New events will be sent to the subscriber using the '<<' method # foo << event - public 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) @@ -88,23 +104,20 @@ # TODO(sissel): Return a method or object that allows you to easily # unsubscribe? end # def subscribe # Set some contextual map value - public def []=(key, value) @data[key] = value end # def []= # Get a context value by name. - public def [](key) @data[key] end # def [] # Remove a context value by name. - public def remove(key) @data.delete(key) end # def remove # Publish data to all outputs. The data is expected to be a hash or a string. @@ -112,54 +125,38 @@ # 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. - public def publish(data) - event = { - :timestamp => Time.now.strftime("%Y-%m-%dT%H:%M:%S.%6N%z") - } - event.merge!(@data) - # TODO(sissel): need to refactor string->hash shoving. + event = {} + event.merge!(@data) # Merge any logger context + if data.is_a?(String) event[:message] = data else event.merge!(data) end + self.class.filters.each do |filter| + filter.call(event) + end + @outputs.each do |out| out << event end end # def publish - # Start timing something. - # Returns an instance of Cabin::Timer bound to this Cabin::Channel. - # To stop the timer and immediately emit the result to this channel, invoke - # the Cabin::Timer#stop method. - public - def time(data, &block) - # TODO(sissel): need to refactor string->hash shoving. - if data.is_a?(String) - data = { :message => data } - end - - timer = Cabin::Timer.new do |duration| - # TODO(sissel): Document this field - data[:duration] = duration - publish(data) - end - - if block_given? - block.call - return timer.stop - else - return timer - end - end # def time - - public def context ctx = Cabin::Context.new(self) return ctx end # def context + + def dataify(data) + if data.is_a?(String) + data = { :message => data } + end + return data + end # def dataify + + public(:initialize, :context, :subscribe, :[]=, :[], :remove, :publish, :time, :context) end # class Cabin::Channel