{"version":3,"file":"EmbraceLimitManager.cjs","names":["diag"],"sources":["../../../src/managers/EmbraceLimitManager/EmbraceLimitManager.ts"],"sourcesContent":["import type { AttributeValue, DiagLogger } from '@opentelemetry/api';\nimport { diag } from '@opentelemetry/api';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace';\nimport type { LogSeverity } from '../../api-logs/index.ts';\nimport { EMB_TYPES, KEY_EMB_TYPE } from '../../constants/index.ts';\nimport type {\n  AttributeLimitedType,\n  EmbraceLimitManagerArgs,\n  LengthLimitedType,\n  LimitedBreadcrumb,\n  LimitedException,\n  LimitedLog,\n  LimitedType,\n  LimitedUserSessionProperty,\n  LimitManagerInternal,\n  LimitOperation,\n  LogLimitedType,\n  MaxLimitedType,\n} from './types.ts';\n\nconst LogSeverityToLimitType: Record<LogSeverity, LogLimitedType> = {\n  info: 'info_log',\n  warning: 'warning_log',\n  error: 'error_log',\n};\n\nexport class EmbraceLimitManager implements LimitManagerInternal {\n  private readonly _diag: DiagLogger;\n\n  private _diagnosticCounts: Record<string, number> = {};\n  private _currentCount: Record<MaxLimitedType, number> = {\n    exception: 0,\n    error_log: 0,\n    warning_log: 0,\n    info_log: 0,\n    breadcrumb: 0,\n    session_property: 0,\n    span: 0,\n    network_request: 0,\n    user_timing_mark: 0,\n    user_timing_measure: 0,\n    element_timing: 0,\n    server_timing: 0,\n    soft_navigation: 0,\n  };\n  private readonly _maxAllowed: Record<MaxLimitedType, number>;\n  private readonly _maxLength: Record<LengthLimitedType, number>;\n  private readonly _maxAttributes: Record<AttributeLimitedType, number>;\n\n  public constructor({\n    diag: diagParam,\n    maxAllowed,\n    maxLength,\n    maxAttributes,\n  }: EmbraceLimitManagerArgs) {\n    this._diag =\n      diagParam ??\n      diag.createComponentLogger({\n        namespace: 'EmbraceLimitManager',\n      });\n\n    this._maxAllowed = maxAllowed;\n    this._maxLength = maxLength;\n    this._maxAttributes = maxAttributes;\n  }\n\n  private _dropIfMaxReached(type: MaxLimitedType): boolean {\n    if (this._currentCount[type] >= this._maxAllowed[type]) {\n      this._diag.warn(\n        `disallowing ${type} because the maximum number of ${this._maxAllowed[type].toString()} has already been reached for this session`,\n      );\n\n      this._incrDiagnosticCount(type, 'drop');\n      return true;\n    }\n\n    this._currentCount[type] = (this._currentCount[type] || 0) + 1;\n    return false;\n  }\n\n  public truncateString(type: LengthLimitedType, body: string) {\n    if (body.length > this._maxLength[type]) {\n      this._diag.warn(\n        `truncating ${type} because it is longer than ${this._maxLength[type].toString()} characters: \"${body}\"`,\n      );\n\n      this._incrDiagnosticCount(type, 'truncate_string');\n      return body.substring(0, this._maxLength[type]);\n    }\n\n    return body;\n  }\n\n  private _truncateAttributes(\n    type: AttributeLimitedType,\n    attributes: Record<string, AttributeValue | undefined>,\n    keyType: LengthLimitedType,\n    valueType: LengthLimitedType,\n  ) {\n    const keys = Object.keys(attributes);\n\n    if (keys.length > this._maxAttributes[type]) {\n      this._diag.warn(\n        `truncating ${type} attributes because there are more than ${this._maxAttributes[type].toString()} set`,\n      );\n      this._incrDiagnosticCount(type, 'truncate_attributes');\n    }\n\n    const truncatedAttributes: Record<string, AttributeValue | undefined> = {};\n\n    for (let i = 0; i < Math.min(keys.length, this._maxAttributes[type]); i++) {\n      const truncatedKey = this.truncateString(keyType, keys[i]);\n      truncatedAttributes[truncatedKey] = this.truncateString(\n        valueType,\n        attributes[keys[i]]?.toString() || '',\n      );\n    }\n\n    return truncatedAttributes;\n  }\n\n  public limitUserTimingEntry(entryType: 'mark' | 'measure'): boolean {\n    const type =\n      entryType === 'mark' ? 'user_timing_mark' : 'user_timing_measure';\n    return this._dropIfMaxReached(type);\n  }\n\n  public limitElementTimingEntry(): boolean {\n    return this._dropIfMaxReached('element_timing');\n  }\n\n  public limitServerTimingEntry(): boolean {\n    return this._dropIfMaxReached('server_timing');\n  }\n\n  public limitSoftNavigationEntry(): boolean {\n    return this._dropIfMaxReached('soft_navigation');\n  }\n\n  public limitBreadcrumb(name: string): LimitedBreadcrumb | 'dropped' {\n    if (this._dropIfMaxReached('breadcrumb')) {\n      return 'dropped';\n    }\n\n    return {\n      name: this.truncateString('breadcrumb', name),\n    };\n  }\n\n  public limitException(\n    message: string,\n    attributes: Record<string, AttributeValue | undefined>,\n  ): LimitedException | 'dropped' {\n    if (this._dropIfMaxReached('exception')) {\n      return 'dropped';\n    }\n\n    return {\n      message: this.truncateString('exception', message),\n      attributes: this._truncateAttributes(\n        'exception',\n        attributes,\n        'exception_attribute_key',\n        'exception_attribute_value',\n      ),\n    };\n  }\n\n  public limitLog(\n    message: string,\n    severity: LogSeverity,\n    attributes: Record<string, AttributeValue | undefined>,\n  ): LimitedLog | 'dropped' {\n    const logType = LogSeverityToLimitType[severity];\n\n    if (this._dropIfMaxReached(logType)) {\n      return 'dropped';\n    }\n\n    return {\n      message: this.truncateString(logType, message),\n      attributes: this._truncateAttributes(\n        logType,\n        attributes,\n        'log_attribute_key',\n        'log_attribute_value',\n      ),\n    };\n  }\n\n  public limitUserSessionProperty(\n    key: string,\n    value: string,\n  ): LimitedUserSessionProperty | 'dropped' {\n    if (this._dropIfMaxReached('session_property')) {\n      return 'dropped';\n    }\n\n    return {\n      key: this.truncateString('session_property_key', key),\n      value: this.truncateString('session_property_value', value),\n    };\n  }\n\n  public dropReadableSpan(span: ReadableSpan): boolean {\n    const type =\n      span.attributes[KEY_EMB_TYPE] === EMB_TYPES.Network\n        ? 'network_request'\n        : 'span';\n\n    return this._dropIfMaxReached(type);\n  }\n\n  public reset(): void {\n    this._diagnosticCounts = {};\n    this._currentCount = {\n      exception: 0,\n      error_log: 0,\n      warning_log: 0,\n      info_log: 0,\n      breadcrumb: 0,\n      session_property: 0,\n      span: 0,\n      network_request: 0,\n      user_timing_mark: 0,\n      user_timing_measure: 0,\n      element_timing: 0,\n      server_timing: 0,\n      soft_navigation: 0,\n    };\n  }\n\n  private _incrDiagnosticCount(type: LimitedType, operation: LimitOperation) {\n    const key = `emb.app.applied_limit.${type}.${operation}.count`;\n\n    this._diagnosticCounts[key] = (this._diagnosticCounts[key] || 0) + 1;\n  }\n  public getDiagnosticCounts(): Record<string, number> {\n    return this._diagnosticCounts;\n  }\n}\n"],"mappings":"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"}