class Scrolls::Logger
Attributes
exceptions[RW]
logger[R]
timestamp[RW]
Public Class Methods
new(options={})
click to toggle source
# File lib/scrolls/logger.rb, line 39 def initialize(options={}) @stream = options.fetch(:stream, STDOUT) @log_facility = options.fetch(:facility, LOG_FACILITY) @time_unit = options.fetch(:time_unit, "seconds") @timestamp = options.fetch(:timestamp, false) @exceptions = options.fetch(:exceptions, "single") @global_ctx = options.fetch(:global_context, {}) @syslog_opts = options.fetch(:syslog_options, SYSLOG_OPTIONS) @escape_keys = options.fetch(:escape_keys, false) @strict_logfmt = options.fetch(:strict_logfmt, false) # Our main entry point to ensure our options are setup properly setup! end
Public Instance Methods
context()
click to toggle source
# File lib/scrolls/logger.rb, line 54 def context if Thread.current.thread_variables.include?(:scrolls_context) Thread.current.thread_variable_get(:scrolls_context) else Thread.current.thread_variable_set(:scrolls_context, {}) end end
context=(h)
click to toggle source
# File lib/scrolls/logger.rb, line 62 def context=(h) Thread.current.thread_variable_set(:scrolls_context, h || {}) end
escape_keys?()
click to toggle source
# File lib/scrolls/logger.rb, line 78 def escape_keys? @escape_keys end
facility()
click to toggle source
# File lib/scrolls/logger.rb, line 90 def facility @facility end
facility=(f)
click to toggle source
# File lib/scrolls/logger.rb, line 94 def facility=(f) if f setup_facility(f) # If we are using syslog, we need to setup our connection again if stream == "syslog" @logger = Scrolls::SyslogLogger.new( progname, syslog_options, facility ) end end end
global_context()
click to toggle source
# File lib/scrolls/logger.rb, line 117 def global_context @global_context.to_h end
log(data) { || ... }
click to toggle source
# File lib/scrolls/logger.rb, line 121 def log(data, &blk) # If we get a string lets bring it into our structure. if data.kind_of? String rawhash = { "log_message" => data } else rawhash = data end if gc = @global_context.to_h ctx = gc.merge(context) logdata = ctx.merge(rawhash) end # By merging the logdata into the timestamp, rather than vice-versa, we # ensure that the timestamp comes first in the Hash, and is placed first # on the output, which helps with readability. logdata = { :now => Time.now.utc }.merge(logdata) if prepend_timestamp? unless blk write(logdata) else start = Time.now res = nil log(logdata.merge(:at => "start")) begin res = yield rescue StandardError => e logdata.merge!({ at: "exception", reraise: true, class: e.class, message: e.message, exception_id: e.object_id.abs, elapsed: calculate_time(start, Time.now) }) logdata.delete_if { |k,v| k if v == "" } log(logdata) raise e end log(logdata.merge(:at => "finish", :elapsed => calculate_time(start, Time.now))) res end end
log_exception(e, data=nil)
click to toggle source
# File lib/scrolls/logger.rb, line 165 def log_exception(e, data=nil) unless @defined @stream = STDERR setup_stream end # We check our arguments for type case data when String rawhash = { "log_message" => data } when Hash rawhash = data else rawhash = {} end if gc = @global_context.to_h logdata = gc.merge(rawhash) end excepdata = { at: "exception", class: e.class, message: e.message, exception_id: e.object_id.abs } excepdata.delete_if { |k,v| k if v == "" } if e.backtrace if single_line_exceptions? lines = e.backtrace.map { |line| line.gsub(/[`'"]/, "") } if lines.length > 0 excepdata[:site] = lines.join('\n') log(logdata.merge(excepdata)) end else log(logdata.merge(excepdata)) e.backtrace.each do |line| log(logdata.merge(excepdata).merge( :at => "exception", :class => e.class, :exception_id => e.object_id.abs, :site => line.gsub(/[`'"]/, "") )) end end end end
stream()
click to toggle source
# File lib/scrolls/logger.rb, line 66 def stream @stream end
stream=(s)
click to toggle source
# File lib/scrolls/logger.rb, line 70 def stream=(s) # Return early to avoid setup return if s == @stream @stream = s setup_stream end
strict_logfmt?()
click to toggle source
# File lib/scrolls/logger.rb, line 82 def strict_logfmt? @strict_logfmt end
syslog_options()
click to toggle source
# File lib/scrolls/logger.rb, line 86 def syslog_options @syslog_opts end
time_unit()
click to toggle source
# File lib/scrolls/logger.rb, line 108 def time_unit @time_unit end
time_unit=(u)
click to toggle source
# File lib/scrolls/logger.rb, line 112 def time_unit=(u) @time_unit = u setup_time_unit end
with_context(prefix) { || ... }
click to toggle source
# File lib/scrolls/logger.rb, line 217 def with_context(prefix) return unless block_given? old = context self.context = old.merge(prefix) res = yield if block_given? ensure self.context = old res end
Private Instance Methods
calculate_time(start, finish)
click to toggle source
# File lib/scrolls/logger.rb, line 301 def calculate_time(start, finish) translate_time_unit unless @t ((finish - start).to_f * @t) end
log_level_ok?(level)
click to toggle source
# File lib/scrolls/logger.rb, line 306 def log_level_ok?(level) if level raise LogLevelError, "Log level unknown" unless LOG_LEVEL_MAP.key?(level) LOG_LEVEL_MAP[level.to_s] <= LOG_LEVEL else true end end
prepend_timestamp?()
click to toggle source
# File lib/scrolls/logger.rb, line 247 def prepend_timestamp? @timestamp end
progname()
click to toggle source
We need this for our syslog setup
# File lib/scrolls/logger.rb, line 297 def progname File.basename($0) end
setup!()
click to toggle source
# File lib/scrolls/logger.rb, line 229 def setup! setup_global_context prepend_timestamp? setup_facility setup_stream single_line_exceptions? setup_time_unit end
setup_facility(f=nil)
click to toggle source
# File lib/scrolls/logger.rb, line 251 def setup_facility(f=nil) if f @facility = LOG_FACILITY_MAP.fetch(f, LOG_FACILITY) else @facility = LOG_FACILITY_MAP.fetch(@log_facility, LOG_FACILITY) end end
setup_global_context()
click to toggle source
# File lib/scrolls/logger.rb, line 238 def setup_global_context # Builds up an immutable object for our global_context # This is not backwards compatiable and was introduced after 0.3.7. # Removes ability to add to global context once we initialize our # logging object. This also deprecates #add_global_context. @global_context = GlobalContext.new(@global_ctx) @global_context.freeze end
setup_stream()
click to toggle source
# File lib/scrolls/logger.rb, line 259 def setup_stream unless @stream == STDOUT # Set this so we know we aren't using our default stream @defined = true end if @stream == "syslog" @logger = Scrolls::SyslogLogger.new( progname, syslog_options, facility ) else @logger = IOLogger.new(@stream) end end
setup_time_unit()
click to toggle source
# File lib/scrolls/logger.rb, line 281 def setup_time_unit unless %w{s ms seconds milliseconds}.include? @time_unit raise TimeUnitError, "Specify the following: s, ms, seconds, milliseconds" end case @time_unit when %w{s seconds} @t = 1.0 when %w{ms milliseconds} @t = 1000.0 else @t = 1.0 end end
single_line_exceptions?()
click to toggle source
# File lib/scrolls/logger.rb, line 276 def single_line_exceptions? return false if @exceptions == "multi" true end
write(data)
click to toggle source
# File lib/scrolls/logger.rb, line 315 def write(data) if log_level_ok?(data[:level]) msg = Scrolls::Parser.unparse(data, escape_keys=escape_keys?, strict_logfmt=strict_logfmt?) @logger.log(msg) end end