# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require_relative 'telemetry_exception_base' require_relative 'telemetry_exception_message_exception' require 'contrast/utils/telemetry_identifier' module Contrast module Agent module Telemetry module TelemetryException # This class will hold the all the information for the specific exceptions # and will be passed in the the event to be sent to TS class Message < Contrast::Agent::Telemetry::TelemetryException::Base VALIDATIONS = { instance: { required: true, range: 12..64 }, tags: { required: true, range: 0..512 }, logger: { required: false, range: 1..128 }, message: { required: false, range: 1..512 }, exceptions: { required: true, range: 1..512, class: Contrast::Agent::Telemetry::TelemetryException::MessageException } }.cs__freeze # Timestamp of creation in ISO8601 format # @return [Integer] attr_reader :timestamp # An Instance ID as defined in Unique Identification // Application ID # @return [String] attr_reader :instance # Tags are key-value string pairs that annotate either metrics # or errors to help provide context, filtering, grouping, and deduplication. # @return [Hash{String => String}] attr_reader :tags # @return [Integer] A number of the occurrences of the exception attr_accessor :occurrences # Array of exceptions, but in our case the Array will only include one exception # @return [Array] attr_reader :exceptions # @return [String,nil] A string denoting the origin of this error. attr_reader :logger # @return [String | nil] A string message to provide additional context to the errors. attr_reader :message def initialize instance, tags, exceptions super() @tags = tags @timestamp = Time.now.iso8601 @instance = instance @occurrences = 1 @exceptions = exceptions validate(VALIDATIONS) end # Optional parameters will be set separately from the required # # @param logger[String] def logger= logger validate_field(VALIDATIONS[:logger], 'logger') @logger = logger end # Optional parameters will be set separately from the required # # @param message[String] def message= message validate_field(VALIDATIONS[:message], 'message') @message = message end # Optional parameters will be set separately from the required # This method is different and is regarding the way we proceed # with incrementing occurrences # If we keep track of them in different places and we store that value # in separated variable - we may directly re-assign occurrences= # But if we are not doing that - we may on same message generated # to increment occurrences from here def increment_occurrences @occurrences += 1 end def to_controlled_hash super() { timestamp: timestamp, instance: instance, occurrences: occurrences, tags: tags, exceptions: exceptions.map(&:to_controlled_hash), logger: logger, message: message }.compact end class << self def build tags, exceptions, logger = nil, message = nil inst = new(Contrast::Utils::Telemetry::Identifier.instance_id, tags, exceptions) inst.logger = logger unless logger.nil? inst.message = message unless message.nil? inst end end end end end end end