# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'ougai' require 'contrast/utils/object_share' require 'contrast/utils/thread_tracker' module Contrast module Logger # Our format for the Ougai logger allowing for custom log format that # extends the behavior of the default Ougai logger class Format < Ougai::Formatters::Bunyan LOG_TRACKER = Contrast::Utils::ThreadTracker.new # Our override of the _call method to add in the extra data that we want, # based on # https://github.com/tilfin/ougai/blob/1fe4fc2587be8eabc47d36dc57ee2814f8a0162b/lib/ougai/formatters/bunyan.rb#L26 # By default, it adds: # name: progname || @app_name, # hostname: @hostname, # pid: $$, # level: to_level(severity), # time: time, # v: 0 # and we add the fields from #format_hash def _call severity, time, progname, data super(severity, time, progname, format_hash.merge(data) ) end private # The extra values to add to the Bunyan hash. # @return [Hash{Symbol => Object}] the extra data to log def format_hash thread_hash.merge(request_hash) end # Because this is unique per thread, we'll create it once and then store # it, rather than create a new hash on every log call during the request. def thread_hash hash = LOG_TRACKER.get(:logging_hash) unless hash hash = { thread_id: Thread.current.object_id } LOG_TRACKER.set(:logging_hash, hash) end hash end NO_REQUEST_HASH = { request_id: -1 }.cs__freeze def request_hash @request_tracker_defined ||= defined?(Contrast::Agent) && defined?(Contrast::Agent::REQUEST_TRACKER) return NO_REQUEST_HASH unless @request_tracker_defined Contrast::Agent::REQUEST_TRACKER&.current&.logging_hash || NO_REQUEST_HASH end end end end