# Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/agent/telemetry/input_analysis_cache_event' module Contrast module Agent module Telemetry # This hash will store the telemetry data for the Protect InputAnalysis cache. class CacheHash < Hash include Contrast::Components::Logger::InstanceMethods # Set per request: HASH_SIZE_LIMIT = 100 # Wrapper to set a value in this Telemetry::Hash only if the provided value is of the data_type for this # Telemetry::CacheHash or the hash has not reached its limit for unique keys. # Saves Array of reportable events. # # @param key [Object] the key to which to associate the value # @param events [array] # @return [Object, nil] echo back out the value as the Hash#[]= method does, or nil if not of the expected # data_type def []= key, events # If telemetry is not running, do not add more as we want to avoid a memory leak. return unless Contrast::Agent.telemetry_queue&.running? # If the Hash is full, do not add more as we want to avoid consuming all application resources. return if at_limit? # If the given value is of unexpected type, do not add it to avoid issues later where type is assumed. return unless valid_event?(events) super(key, events) end # Determine if hash has reached exception event limit. # # @return [Boolean] def at_limit? unless length < HASH_SIZE_LIMIT logger.debug("[Telemetry] Number of IA cache events exceeds limit of #{ HASH_SIZE_LIMIT }") return true end false end private # Checks to see if the given object is a valid event. # @param event [Contrast::Agent::Telemetry::InputAnalysisCacheEvent] def valid_event? events events&.all?(Contrast::Agent::Telemetry::InputAnalysisCacheEvent) end end end end end