class SlackLogDevice

Attributes

channel[R]
flush_delay[R]
max_buffer_size[R]
timeout[R]
username[R]
webhook_url[R]

Public Class Methods

enable_rails_logging!() click to toggle source
# File lib/slack_log_device.rb, line 11
def self.enable_rails_logging!
  require "#{__dir__}/slack_log_device/debug_exceptions"
  require "#{__dir__}/slack_log_device/set_request_in_thread"
  ActionDispatch::DebugExceptions.prepend(SlackLogDevice::DebugExceptions)
  Rails.application.config.middleware.insert_before(Rails::Rack::Logger, SlackLogDevice::SetRequestInThread)
  true
end
formatter(options = {}, &block) click to toggle source
# File lib/slack_log_device.rb, line 19
def self.formatter(options = {}, &block)
  Formatter.new(options, &block)
end
new(options = {}) click to toggle source
# File lib/slack_log_device.rb, line 23
def initialize(options = {})
  options.assert_valid_keys(:auto_flush, :channel, :flush_delay, :max_buffer_size, :timeout, :username, :webhook_url)
  @buffer = []
  @mutex = Mutex.new
  self.auto_flush = options[:auto_flush]
  self.channel = options[:channel]
  self.flush_delay = options.key?(:flush_delay) ? options[:flush_delay] : 1
  self.max_buffer_size = options.key?(:max_buffer_size) ? options[:max_buffer_size] : 10
  self.timeout = options.key?(:timeout) ? options[:timeout] : 5
  self.username = options[:username]
  self.webhook_url = options[:webhook_url]
  at_exit { flush } unless Thread.current.key?(:__rspec)
end

Public Instance Methods

auto_flush=(value) click to toggle source
# File lib/slack_log_device.rb, line 41
def auto_flush=(value)
  @auto_flush = value.present?
end
auto_flush?() click to toggle source
# File lib/slack_log_device.rb, line 37
def auto_flush?
  @auto_flush
end
channel=(value) click to toggle source
# File lib/slack_log_device.rb, line 45
def channel=(value)
  channel = value.to_s.presence
  raise ArgumentError.new("Invalid channel specified: #{value.inspect}, it must start with # or @ and be in lower case with no spaces or special chars and its length must not exceed 22 chars") if channel && channel !~ /^[@#][a-z0-9_-]{1,21}$/
  @channel = channel
end
close() click to toggle source
# File lib/slack_log_device.rb, line 51
def close
  # Does nothing, this method must exist to consider the LogDevice as an IO.
end
flush() click to toggle source
# File lib/slack_log_device.rb, line 55
def flush
  while !@buffer.empty? do
    message = nil
    @mutex.synchronize do
      message = @buffer.pop
    end
    text = message.to_s.strip
    next if text.empty?
    data = { 'text' => text }
    data['channel'] = channel if channel.present?
    data['icon_emoji'] = message.icon_emoji if message.respond_to?(:icon_emoji) && message.icon_emoji.present?
    data['username'] = username if username.present?
    begin
      HTTParty.post(webhook_url, body: data.to_json, headers: { 'Content-Type' => 'application/json' }, timeout: timeout)
    rescue Exception => e
      STDERR.puts(e)
    end
  end
  nil
end
flush?() click to toggle source
# File lib/slack_log_device.rb, line 76
def flush?
  auto_flush? || flush_delay.zero? || @buffer.size > max_buffer_size
end
flush_delay=(value) click to toggle source
# File lib/slack_log_device.rb, line 80
def flush_delay=(value)
  delay = Integer(value) rescue nil
  raise ArgumentError.new("Invalid flush delay: #{value.inspect}") if delay.nil? || delay < 0
  @flush_delay = delay
end
max_buffer_size=(value) click to toggle source
# File lib/slack_log_device.rb, line 86
def max_buffer_size=(value)
  size = Integer(value) rescue nil
  raise ArgumentError.new("Invalid max buffer size: #{value.inspect}") if size.nil? || size < 0
  @max_buffer_size = size
end
timeout=(value) click to toggle source
# File lib/slack_log_device.rb, line 92
def timeout=(value)
  timeout = Integer(value) rescue nil
  raise ArgumentError.new("Invalid timeout: #{value.inspect}") if timeout.nil? || timeout <= 0
  @timeout = timeout
end
username=(value) click to toggle source
# File lib/slack_log_device.rb, line 98
def username=(value)
  @username = value.to_s.squish.presence
end
webhook_url=(value) click to toggle source
# File lib/slack_log_device.rb, line 102
def webhook_url=(value)
  raise ArgumentError.new('Webhook URL must be specified') if value.blank?
  uri = URI(value.to_s) rescue nil
  raise ArgumentError.new("Invalid webhook URL: #{value.inspect}") if uri.nil? || !uri.is_a?(URI::HTTP)
  @webhook_url = uri.to_s
end
write(message) click to toggle source
# File lib/slack_log_device.rb, line 109
def write(message)
  return if message.blank?
  @mutex.synchronize do
    @buffer << message
  end
  @flush_thread.kill if @flush_thread
  if flush?
    flush
  else
    @flush_thread = Thread.new do
      sleep(flush_delay)
      flush
    end
  end
  nil
end