class Logsly::Logging182::Appenders::Growl

This class provides an Appender that can send notifications to the Growl notification system on Mac OS X.

growlnotify must be installed somewhere in the path in order for the appender to function properly.

Public Class Methods

new( name, opts = {} ) click to toggle source

Create an appender that will log messages to the Growl framework on a Mac OS X machine.

Calls superclass method Logsly::Logging182::Appender::new
# File lib/logsly/logging182/appenders/growl.rb, line 29
def initialize( name, opts = {} )
  super

  @growl = "growlnotify -w -n \"#{@name}\" -t \"%s\" -m \"%s\" -p %d &"

  @coalesce = opts.getopt(:coalesce, false)
  @title_sep = opts.getopt(:separator)

  # provides a mapping from the default Logsly::Logging182 levels
  # to the Growl notification levels
  @map = [-2, -1, 0, 1, 2]

  map = opts.getopt(:map)
  self.map = map unless map.nil?
  setup_coalescing if @coalesce

  # make sure the growlnotify command can be called
  unless system('growlnotify -v >> /dev/null 2>&1')
    self.level = :off
    ::Logsly::Logging182.log_internal {'growl notifications have been disabled'}
  end
end

Public Instance Methods

map = { logging_levels → growl_levels } click to toggle source

Configure the mapping from the Logsly::Logging182 levels to the Growl notification levels. This is needed in order to log events at the proper Growl level.

Without any configuration, the following mapping will be used:

:debug  =>  -2
:info   =>  -1
:warn   =>  0
:error  =>  1
:fatal  =>  2
# File lib/logsly/logging182/appenders/growl.rb, line 67
def map=( levels )
  map = []
  levels.keys.each do |lvl|
    num = ::Logsly::Logging182.level_num(lvl)
    map[num] = growl_level_num(levels[lvl])
  end
  @map = map
end

Private Instance Methods

call_growl( title, message, priority ) click to toggle source

Call the growlnotify application with the given parameters. If the system call fails, the growl appender will be disabled.

# File lib/logsly/logging182/appenders/growl.rb, line 191
def call_growl( *args )
  unless system(@growl % args)
    self.level = :off
    ::Logsly::Logging182.log_internal {'growl notifications have been disabled'}
  end
end
coalesce( title, message, priority ) click to toggle source

Attempt to coalesce the given message with any that might be pending in the queue to send to the growl notifier. Messages are coalesced with any in the queue that have the same title and priority.

There can be only one message in the queue, so if the title and/or priority don't match, the message in the queue is sent immediately to the growl notifier, and the current message is queued.

# File lib/logsly/logging182/appenders/growl.rb, line 145
def coalesce( *msg )
  @c_mutex.synchronize do
    if @c_queue.empty?
      @c_queue << msg
      @c_thread.run

    else
      qmsg = @c_queue.last
      if qmsg.first != msg.first or qmsg.last != msg.last
        @c_queue << msg
      else
        qmsg[1] << "\n" << msg[1]
      end
    end
  end
end
growl( title, message, priority ) click to toggle source

Send the message to the growl notifier using the given title and priority.

# File lib/logsly/logging182/appenders/growl.rb, line 128
def growl( title, message, priority )
  message.tr!("`", "'")
  if @coalesce then coalesce(title, message, priority)
  else call_growl(title, message, priority) end
end
growl_level_num( level ) → integer click to toggle source

Takes the given level as a string or integer and returns the corresponding Growl notification level number.

# File lib/logsly/logging182/appenders/growl.rb, line 114
def growl_level_num( level )
  level = Integer(level)
  if level < -2 or level > 2
    raise ArgumentError, "level '#{level}' is not in range -2..2"
  end
  level
end
setup_coalescing click to toggle source

Setup the appender to handle coalescing of messages before sending them to the growl notifier. This requires the creation of a thread and mutex for passing messages from the appender thread to the growl notifier thread.

# File lib/logsly/logging182/appenders/growl.rb, line 170
def setup_coalescing
  @c_mutex = Mutex.new
  @c_queue = []

  @c_thread = Thread.new do
    loop do
      Thread.stop if @c_queue.empty?
      sleep 1
      @c_mutex.synchronize {
        call_growl(*@c_queue.shift) until @c_queue.empty?
      }
    end  # loop
  end  # Thread.new
end
write( event ) click to toggle source

Write the given event to the growl notification facility. The log event will be processed through the Layout associated with this appender. The message will be logged at the level specified by the event.

# File lib/logsly/logging182/appenders/growl.rb, line 87
def write( event )
  title = ''
  priority = 0
  message = if event.instance_of?(::Logsly::Logging182::LogEvent)
      priority = @map[event.level]
      @layout.format(event)
    else
      event.to_s
    end
  return if message.empty?

  message = message.gsub(ColoredRegexp, '')
  if @title_sep
    title, message = message.split(@title_sep)
    title, message = '', title if message.nil?
  end

  growl(title.strip, message.strip, priority)
  self
end