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’
122 123 124 125 126 127 128 129 |
# File 'lib/cabin/channel.rb', line 122 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.
116 117 118 |
# File 'lib/cabin/channel.rb', line 116 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.
87 88 89 |
# File 'lib/cabin/channel.rb', line 87 def action(&block) actions << block end |
.actions ⇒ Object Also known as: filters
Get a list of actions included in this class.
80 81 82 |
# File 'lib/cabin/channel.rb', line 80 def actions @actions ||= [] end |
.allow_event?(event, subscription) ⇒ Boolean
Decide to publish the event based on conditions and subscription options
104 105 106 |
# File 'lib/cabin/channel.rb', line 104 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).
99 100 101 |
# File 'lib/cabin/channel.rb', line 99 def condition(&block) conditions << block end |
.conditions ⇒ Object
Get a list of conditions included in this class.
93 94 95 |
# File 'lib/cabin/channel.rb', line 93 def conditions @conditions ||= [] end |
.each(&block) ⇒ Object
def Cabin::Channel.set
71 72 73 74 75 76 77 |
# File 'lib/cabin/channel.rb', line 71 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.
63 64 65 |
# File 'lib/cabin/channel.rb', line 63 def get(identifier=$0) return @channel_lock.synchronize { @channels[identifier] } end |
.set(identifier, channel) ⇒ Object
def Cabin::Channel.get
67 68 69 |
# File 'lib/cabin/channel.rb', line 67 def set(identifier, channel) return @channel_lock.synchronize { @channels[identifier] = channel } end |
Instance Method Details
#context ⇒ Object
def publish
202 203 204 205 |
# File 'lib/cabin/channel.rb', line 202 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.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/cabin/channel.rb', line 178 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.
167 168 169 |
# File 'lib/cabin/channel.rb', line 167 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
136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/cabin/channel.rb', line 136 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] = Cabin::Subscriber.new(output, ) end return output.object_id end |
#unsubscribe(id) ⇒ Object
Unsubscribe. Takes a ‘subscription id’ as returned by the subscribe method
150 151 152 153 154 |
# File 'lib/cabin/channel.rb', line 150 def unsubscribe(id) @subscriber_lock.synchronize do @subscribers.delete(id) end end |