lib/semantic_logger/formatters/logfmt.rb in semantic_logger-4.8.2 vs lib/semantic_logger/formatters/logfmt.rb in semantic_logger-4.9.0
- old
+ new
@@ -1,9 +1,24 @@
require "json"
module SemanticLogger
module Formatters
+ # Produces logfmt formatted messages
+ #
+ # The following fields are extracted from the raw log and included in the formatted message:
+ # :timestamp, :level, :name, :message, :duration, :tags, :named_tags
+ #
+ # E.g.
+ # timestamp="2020-07-20T08:32:05.375276Z" level=info name="DefaultTest" base="breakfast" spaces="second breakfast" double_quotes="\"elevensies\"" single_quotes="'lunch'" tag="success"
+ #
+ # All timestamps are ISO8601 formatteed
+ # All user supplied values are escaped and surrounded by double quotes to avoid ambiguious message delimeters
+ # `tags` are treated as keys with boolean values. Tag names are not formatted or validated, ensure you use valid logfmt format for tag names.
+ # `named_tags` are flattened are merged into the top level message field. Any conflicting fields are overridden.
+ # `payload` values take precedence over `tags` and `named_tags`. Any conflicting fields are overridden.
+ #
+ # Futher Reading https://brandur.org/logfmt
class Logfmt < Raw
def initialize(time_format: :iso_8601, time_key: :timestamp, **args)
super(time_format: time_format, time_key: time_key, **args)
end
@@ -14,17 +29,26 @@
end
private
def raw_to_logfmt
- @parsed = @raw.slice(:timestamp, :level, :name, :message, :duration).merge tag: "success"
+ @parsed = @raw.slice(time_key, :level, :name, :message, :duration).merge(tag: "success")
+ handle_tags
handle_payload
handle_exception
flatten_log
end
+ def handle_tags
+ tags = @raw.fetch(:tags){ [] }
+ .each_with_object({}){ |tag, accum| accum[tag] = true }
+
+ @parsed = @parsed.merge(tags)
+ .merge(@raw.fetch(:named_tags){ {} })
+ end
+
def handle_payload
return unless @raw.key? :payload
@parsed = @parsed.merge(@raw[:payload])
end
@@ -36,19 +60,13 @@
@parsed = @parsed.merge(@raw[:exception])
end
def flatten_log
flattened = @parsed.map do |key, value|
- "#{key}=#{parse_value(value)}"
+ "#{key}=#{value.to_json}"
end
flattened.join(" ")
- end
-
- def parse_value(value)
- return value.to_json if value.instance_of? String
-
- value
end
end
end
end