mirror of
https://github.com/meineerde/rackstash.git
synced 2026-02-17 17:11:59 +00:00
Calling #call in a custom class instead of a lambda performs much
better:
require 'benchmark/ips'
class RawFormatter
def call(_severity, _timestamp, _progname, msg) msg end
end
Benchmark.ips do |x|
message = 'my message'
proc = ->(_severity, _timestamp, _progname, msg) { msg }
instance = RawFormatter.new
x.report('proc') do
proc.call(nil, nil, nil, message)
end
x.report('instance') do
instance.call(nil, nil, nil, message)
end
x.compare!
end
# Warming up --------------------------------------
# proc 159.882k i/100ms
# instance 182.648k i/100ms
# Calculating -------------------------------------
# proc 4.612M (± 5.2%) i/s - 23.023M in 5.005950s
# instance 7.716M (± 6.3%) i/s - 38.539M in 5.015306s
#
# Comparison:
# instance: 7716097.7 i/s
# proc: 4611920.5 i/s - 1.67x slower
91 lines
2.1 KiB
Ruby
91 lines
2.1 KiB
Ruby
# Copyright 2017 Holger Just
|
|
#
|
|
# This software may be modified and distributed under the terms
|
|
# of the MIT license. See the LICENSE.txt file for details.
|
|
|
|
module Rackstash
|
|
# This class and all its data are immutable after initialization
|
|
class Message
|
|
RAW_FORMATTER = RawFormatter.new
|
|
|
|
SEVERITY_LABEL = [
|
|
'DEBUG'.freeze,
|
|
'INFO'.freeze,
|
|
'WARN'.freeze,
|
|
'ERROR'.freeze,
|
|
'FATAL'.freeze,
|
|
'ANY'.freeze
|
|
].freeze
|
|
|
|
attr_reader :message
|
|
|
|
attr_reader :severity
|
|
|
|
attr_reader :progname
|
|
|
|
attr_reader :time
|
|
|
|
attr_reader :formatter
|
|
|
|
def initialize(
|
|
msg,
|
|
severity: UNKNOWN,
|
|
time: Time.now.utc.freeze,
|
|
progname: PROGNAME,
|
|
formatter: RAW_FORMATTER
|
|
)
|
|
@message = cleanup_message(msg)
|
|
|
|
@severity = Integer(severity)
|
|
@severity = 0 if @severity < 0
|
|
|
|
@time = dup_freeze(time)
|
|
@progname = dup_freeze(progname)
|
|
@formatter = formatter
|
|
|
|
# Freeze the newly created message to ensure it can't be changed.
|
|
# All passed values are also effectively frozen, making the Message an
|
|
# immutable object.
|
|
freeze
|
|
end
|
|
|
|
def severity_label
|
|
SEVERITY_LABEL[@severity] || SEVERITY_LABEL.last
|
|
end
|
|
|
|
def to_s
|
|
@formatter.call(severity_label, @time, @progname, @message)
|
|
end
|
|
alias_method :to_str, :to_s
|
|
alias_method :as_json, :to_s
|
|
|
|
private
|
|
|
|
# Sanitize a single mesage to be added to the buffer, can be a single or
|
|
# multi line string
|
|
#
|
|
# @param msg [#to_s] a message to be added to the buffer
|
|
# @return [String] the sanitized frozen message
|
|
def cleanup_message(msg)
|
|
msg = msg.inspect unless msg.is_a?(String)
|
|
msg = utf8_encode(msg)
|
|
# remove useless ANSI color codes
|
|
msg.gsub!(/\e\[[0-9;]*m/, EMPTY_STRING)
|
|
msg.freeze
|
|
end
|
|
|
|
def utf8_encode(str)
|
|
str.to_s.encode(
|
|
Encoding::UTF_8,
|
|
invalid: :replace,
|
|
undef: :replace,
|
|
universal_newline: true
|
|
)
|
|
end
|
|
|
|
def dup_freeze(obj)
|
|
obj.frozen? ? obj : obj.dup.freeze
|
|
end
|
|
end
|
|
end
|