{"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-web';\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  LimitedSessionProperty,\n  LimitedType,\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  };\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 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 limitSessionProperty(\n    key: string,\n    value: string,\n  ): LimitedSessionProperty | '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    };\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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"}