require 'aws-xray-sdk/logger' require 'aws-xray-sdk/context/context' require 'aws-xray-sdk/exceptions' module XRay # The default context storage management used by # the X-Ray recorder. It uses thread local to store # segments and subsegments. class DefaultContext include Context include Logging LOCAL_KEY = '_aws_xray_entity'.freeze CONTEXT_MISSING_KEY = 'AWS_XRAY_CONTEXT_MISSING'.freeze SUPPORTED_STRATEGY = %w[RUNTIME_ERROR LOG_ERROR IGNORE_ERROR].freeze DEFAULT_STRATEGY = SUPPORTED_STRATEGY[1] attr_reader :context_missing def initialize strategy = ENV[CONTEXT_MISSING_KEY] || DEFAULT_STRATEGY @context_missing = sanitize_strategy(strategy) end # @param [Entity] entity The entity to be stored in the context. def store_entity(entity:) Thread.current[LOCAL_KEY] = entity end # @return [Entity] The current active entity(could be segment or subsegment). def current_entity if entity = Thread.current[LOCAL_KEY] entity else handle_context_missing end end # Clear the current thread local storage on X-Ray related entities. def clear! Thread.current[LOCAL_KEY] = nil end # @param [Entity] entity The entity to inject. # @param [Thread] target_ctx Put the provided entity to the new thread. def inject_context(entity, target_ctx: nil) target_ctx ||= Thread.current target_ctx[LOCAL_KEY] = entity if entity end # When the current entity needs to be accessed but there is none, # it handles the missing context based on the configuration. # On `RUNTIME_ERROR` it raises `ContextMissingError`. # On 'LOG_ERROR' it logs an error message and return `nil`. def handle_context_missing case context_missing when 'RUNTIME_ERROR' raise ContextMissingError when 'LOG_ERROR' logger.error %(cannot find the current context.) end nil end def context_missing=(v) strategy = ENV[CONTEXT_MISSING_KEY] || v @context_missing = sanitize_strategy(strategy) end private def sanitize_strategy(v) if SUPPORTED_STRATEGY.include?(v) v else logger.warn %(context missing #{v} is not supported, switch to default #{DEFAULT_STRATEGY}.) DEFAULT_STRATEGY end end end end