This was Cloudflare-specific and it was only used for selecting the currency during user upgrades.
127 lines
4.3 KiB
Ruby
127 lines
4.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# The DanbooruLogger class handles logging messages to the Rails log and to the APM.
|
|
#
|
|
# @see https://guides.rubyonrails.org/debugging_rails_applications.html#the-logger
|
|
class DanbooruLogger
|
|
HEADERS = %w[referer sec-fetch-dest sec-fetch-mode sec-fetch-site sec-fetch-user]
|
|
|
|
# Log a message to the Rails log and to the APM.
|
|
#
|
|
# @param message [String] the message to log
|
|
# @param params [Hash] optional key-value data to log with the message
|
|
def self.info(message, params = {})
|
|
Rails.logger.info(message)
|
|
|
|
params = flatten_hash(params).symbolize_keys
|
|
log_event(:info, message: message, **params)
|
|
end
|
|
|
|
# Log an exception to the Rails log and to the APM. The `expected` flag is
|
|
# used to separate expected exceptions, like search timeouts or auth failures,
|
|
# from unexpected exceptions, like runtime errors, in the error logs.
|
|
#
|
|
# @param message [Exception] the exception to log
|
|
# @param expected [Boolean] whether the exception was expected
|
|
# @param params [Hash] optional key-value data to log with the exception
|
|
def self.log(exception, expected: false, **params)
|
|
if expected
|
|
Rails.logger.info("#{exception.class}: #{exception.message}")
|
|
else
|
|
backtrace = Rails.backtrace_cleaner.clean(exception.backtrace).join("\n")
|
|
Rails.logger.error("#{exception.class}: #{exception.message}\n#{backtrace}")
|
|
end
|
|
|
|
log_exception(exception, expected: expected, custom_params: params)
|
|
end
|
|
|
|
# Log extra HTTP request data to the APM. Logs the user's IP, user agent,
|
|
# request params, and session cookies.
|
|
#
|
|
# @param request the HTTP request
|
|
# @param session the Rails session
|
|
# @param user [User] the current user
|
|
def self.add_session_attributes(request, session, user)
|
|
add_attributes("param", request_params(request))
|
|
add_attributes("session", session_params(session))
|
|
add_attributes("cookie", cookie_params(request.cookies))
|
|
add_attributes("user", user_params(request, user))
|
|
end
|
|
|
|
# Get logged HTTP headers from request.
|
|
def self.header_params(request)
|
|
headers = request.headers.to_h.select { |header, value| header.match?(/\AHTTP_/) }
|
|
headers = headers.transform_keys { |header| header.delete_prefix("HTTP_").downcase }
|
|
headers = headers.select { |header, value| header.in?(HEADERS) }
|
|
headers
|
|
end
|
|
|
|
def self.request_params(request)
|
|
request.parameters.with_indifferent_access.except(:controller, :action).reject do |key, value|
|
|
# exclude strange URL params that don't come from our app.
|
|
!key.match?(/\A[a-z._]+\z/) || key.match?(/\A_|_\z/)
|
|
end
|
|
end
|
|
|
|
def self.session_params(session)
|
|
session.to_h.with_indifferent_access.slice(:session_id, :started_at, :last_authenticated_at)
|
|
end
|
|
|
|
def self.cookie_params(cookies)
|
|
# XXX see also ApplicationHelper#cookie_data_attributes
|
|
cookies.slice(*%w[
|
|
news-ticker hide_upgrade_account_notice hide_verify_account_notice
|
|
hide_dmail_notice dab show-relationship-previews post_preview_size
|
|
post_preview_show_votes
|
|
])
|
|
end
|
|
|
|
def self.user_params(request, user)
|
|
{
|
|
id: user&.id,
|
|
name: user&.name,
|
|
level: user&.level_string,
|
|
#ip: request.remote_ip,
|
|
#safe_mode: CurrentUser.safe_mode?,
|
|
#bot: UserAgent.new(request.headers["HTTP_USER_AGENT"]).is_bot?,
|
|
}
|
|
end
|
|
|
|
def self.add_attributes(prefix, hash)
|
|
attributes = flatten_hash(hash).transform_keys { |key| "#{prefix}.#{key}" }
|
|
attributes.delete_if { |key, value| key.end_with?(*Rails.application.config.filter_parameters.map(&:to_s)) }
|
|
log_attributes(attributes)
|
|
end
|
|
|
|
private_class_method
|
|
|
|
def self.log_attributes(attributes)
|
|
attributes.each do |key, value|
|
|
ElasticAPM.set_label(key, value)
|
|
end
|
|
end
|
|
|
|
def self.log_exception(exception, expected: false, custom_params: {})
|
|
ElasticAPM.report(exception, handled: expected)
|
|
end
|
|
|
|
def self.log_event(level, message: nil, **params)
|
|
ElasticAPM.set_custom_context(params)
|
|
ElasticAPM.report_message(message)
|
|
end
|
|
|
|
# flatten_hash({ foo: { bar: { baz: 42 } } })
|
|
# => { "foo.bar.baz" => 42 }
|
|
def self.flatten_hash(hash)
|
|
hash.each_with_object({}) do |(k, v), h|
|
|
if v.is_a?(Hash)
|
|
flatten_hash(v).map do |h_k, h_v|
|
|
h["#{k}.#{h_k}"] = h_v
|
|
end
|
|
else
|
|
h[k.to_s] = v
|
|
end
|
|
end
|
|
end
|
|
end
|