class SemanticLogger::Appender::SentryRuby
def default_formatter
def default_formatter SemanticLogger::Formatters::Raw.new end
def extract_tags!(context)
Finally, the tag names are limited to 32 characters and the tag values to 256.
joined with a comma.
be used as a "tag" named tag. If such a tag already exists, it is also
Unnamed tags will be stringified and joined with a comma. Then they will
Named tags will be stringified (both key and value).
Extract tags.
def extract_tags!(context) named_tags = context.delete(:named_tags) || {} named_tags = named_tags.map { |k, v| [k.to_s, v.to_s] }.to_h tags = context.delete(:tags) named_tags.merge!("tag" => tags.join(", ")) { |_, v1, v2| "#{v1}, #{v2}" } if tags named_tags.map { |k, v| [k[0...32], v[0...256]] }.to_h end
def extract_user!(*sources)
the above keys is already present.
Any additional value nested in a :user key will be added, provided any of
Keys :username and :ip_address will be used verbatim.
Keys :user_id and :user_email will be used as :id and :email respectively.
Extract user data from named tags or payload.
def extract_user!(*sources) keys = {user_id: :id, username: :username, user_email: :email, ip_address: :ip_address} user = {} sources.each do |source| keys.each do |source_key, target_key| value = source.delete(source_key) user[target_key] = value if value end end return if user.empty? sources.each do |source| extras = source.delete(:user) user.merge!(extras) if extras.is_a?(Hash) end user end
def initialize(level: :error, **args, &block)
Name of this application to appear in log messages.
application: [String]
Default: SemanticLogger.host
Name of this host to appear in log messages.
host: [String]
The Proc must return true or false.
Proc: Only include log messages where the supplied Proc returns true
regular expression. All other messages will be ignored.
RegExp: Only include log messages where the class name matches the supplied.
filter: [Regexp|Proc]
Default: Use the built-in formatter (See: #call)
the output from this appender
An instance of a class that implements #call, or a Proc to be used to format
formatter: [Object|Proc|Symbol|Hash]
Default: :error
Override the log level for this appender.
level: [:trace | :debug | :info | :warn | :error | :fatal]
Parameters
Create Appender
def initialize(level: :error, **args, &block) # Replace the Sentry Ruby logger so that we can identify its log # messages and not forward them to Sentry ::Sentry.init { |config| config.logger = SemanticLogger[::Sentry] } unless ::Sentry.initialized? super end
def log(log)
def log(log) # Ignore logs coming from Sentry itself return false if log.name == "Sentry" context = formatter.call(log, self) payload = context.delete(:payload) || {} named_tags = context[:named_tags] || {} transaction_name = named_tags.delete(:transaction_name) user = extract_user!(named_tags, payload) tags = extract_tags!(context) fingerprint = payload.delete(:fingerprint) ::Sentry.with_scope do |scope| scope.set_user(user) if user scope.set_level(context.delete(:level)) if context[:level] scope.set_fingerprint(fingerprint) if fingerprint scope.set_transaction_name(transaction_name) if transaction_name scope.set_tags(tags) scope.set_extras(context) scope.set_extras(payload) if log.exception ::Sentry.capture_exception(log.exception) elsif log.backtrace ::Sentry.capture_message(context[:message], backtrace: log.backtrace) else ::Sentry.capture_message(context[:message]) end end true end