Class: Cabin::Channel
- Inherits:
-
Object
- Object
- Cabin::Channel
- Includes:
- Mixins::Logger, Mixins::Pipe, Mixins::Terminal, Mixins::Timer, Mixins::Timestamp
- Defined in:
- lib/cabin/channel.rb
Overview
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
()
# Clear any context we just wanted bar() to know about
context.clear()
@logger.info("Done in foo")
end
def
@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}
Constant Summary
Constants included from Mixins::Logger
Mixins::Logger::BACKTRACE_RE, Mixins::Logger::LEVELS
Instance Attribute Summary collapse
-
#metrics ⇒ Object
All channels come with a metrics provider.
Attributes included from Mixins::Logger
Class Method Summary collapse
-
.action(&block) ⇒ Object
(also: filter)
Register a new action.
-
.actions ⇒ Object
(also: filters)
Get a list of actions included in this class.
-
.allow_event?(event, subscription) ⇒ Boolean
Decide to publish the event based on conditions and subscription options.
-
.condition(&block) ⇒ Object
Register a new condition.
-
.conditions ⇒ Object
Get a list of conditions included in this class.
-
.each(&block) ⇒ Object
def Cabin::Channel.set.
-
.get(identifier = $0) ⇒ Object
Get a channel for a given identifier.
-
.set(identifier, channel) ⇒ Object
def Cabin::Channel.get.
Instance Method Summary collapse
-
#context ⇒ Object
def publish.
-
#initialize ⇒ Channel
constructor
Create a new logging channel.
-
#publish(data, &block) ⇒ Object
Publish data to all outputs.
-
#remove(key) ⇒ Object
Remove a context value by name.
-
#subscribe(output, options = {}) ⇒ Object
Subscribe a new input New events will be sent to the subscriber using the ‘<<’ method foo << event.
-
#unsubscribe(id) ⇒ Object
Unsubscribe.
Methods included from Mixins::Terminal
Methods included from Mixins::Timer
Methods included from Mixins::Pipe
Methods included from Mixins::Logger
Methods included from Mixins::Timestamp
Constructor Details
#initialize ⇒ Channel
Create a new logging channel. The default log level is ‘info’
121 122 123 124 125 126 127 128 |
# File 'lib/cabin/channel.rb', line 121 def initialize @subscribers = {} @data = {} @level = :info @metrics = Cabin::Metrics.new @metrics.channel = self @subscriber_lock = Mutex.new end |
Instance Attribute Details
#metrics ⇒ Object
All channels come with a metrics provider.
115 116 117 |
# File 'lib/cabin/channel.rb', line 115 def metrics @metrics end |
Class Method Details
.action(&block) ⇒ Object Also known as: filter
Register a new action. The block is passed the event. It is expected to modify that event or otherwise do nothing.
86 87 88 |
# File 'lib/cabin/channel.rb', line 86 def action(&block) actions << block end |
.actions ⇒ Object Also known as: filters
Get a list of actions included in this class.
79 80 81 |
# File 'lib/cabin/channel.rb', line 79 def actions @actions ||= [] end |
.allow_event?(event, subscription) ⇒ Boolean
Decide to publish the event based on conditions and subscription options
103 104 105 |
# File 'lib/cabin/channel.rb', line 103 def allow_event?(event, subscription) conditions.all? { |condition| condition.call(event, subscription) } end |
.condition(&block) ⇒ Object
Register a new condition. The block must expect an event and a subscription. It is expected to either return true (allow the event) or false (reject it).
98 99 100 |
# File 'lib/cabin/channel.rb', line 98 def condition(&block) conditions << block end |
.conditions ⇒ Object
Get a list of conditions included in this class.
92 93 94 |
# File 'lib/cabin/channel.rb', line 92 def conditions @conditions ||= [] end |
.each(&block) ⇒ Object
def Cabin::Channel.set
70 71 72 73 74 75 76 |
# 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 |
.get(identifier = $0) ⇒ Object
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.
62 63 64 |
# File 'lib/cabin/channel.rb', line 62 def get(identifier=$0) return @channel_lock.synchronize { @channels[identifier] } end |
.set(identifier, channel) ⇒ Object
def Cabin::Channel.get
66 67 68 |
# File 'lib/cabin/channel.rb', line 66 def set(identifier, channel) return @channel_lock.synchronize { @channels[identifier] = channel } end |
Instance Method Details
#context ⇒ Object
def publish
201 202 203 204 |
# File 'lib/cabin/channel.rb', line 201 def context ctx = Cabin::Context.new(self) return ctx end |
#publish(data, &block) ⇒ Object
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.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/cabin/channel.rb', line 177 def publish(data, &block) event = {} self.class.actions.each do |action| action.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 |_, subscriber| append = block_given? ? block.call(subscriber, event) : true if append && self.class.allow_event?(event, subscriber) subscriber << event end end end end |
#remove(key) ⇒ Object
Remove a context value by name.
166 167 168 |
# File 'lib/cabin/channel.rb', line 166 def remove(key) @data.delete(key) end |
#subscribe(output, options = {}) ⇒ Object
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
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/cabin/channel.rb', line 135 def subscribe(output, = {}) # Wrap ruby stdlib Logger if given. if Kernel.const_defined?(:Logger) && 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] = Cabin::Subscriber.new(output, ) end return output.object_id end |
#unsubscribe(id) ⇒ Object
Unsubscribe. Takes a ‘subscription id’ as returned by the subscribe method
149 150 151 152 153 |
# File 'lib/cabin/channel.rb', line 149 def unsubscribe(id) @subscriber_lock.synchronize do @subscribers.delete(id) end end |