UNPKG

@embrace-io/web-sdk

Version:
1 lines 9.66 kB
{"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":";;;;AAoBA,MAAM,yBAA8D;CAClE,MAAM;CACN,SAAS;CACT,OAAO;AACT;AAEA,IAAa,sBAAb,MAAiE;CAC/D;CAEA,oBAAoD,CAAC;CACrD,gBAAwD;EACtD,WAAW;EACX,WAAW;EACX,aAAa;EACb,UAAU;EACV,YAAY;EACZ,kBAAkB;EAClB,MAAM;EACN,iBAAiB;EACjB,kBAAkB;EAClB,qBAAqB;EACrB,gBAAgB;EAChB,eAAe;EACf,iBAAiB;CACnB;CACA;CACA;CACA;CAEA,YAAmB,EACjB,MAAM,WACN,YACA,WACA,iBAC0B;EAC1B,KAAK,QACH,aACAA,mBAAAA,KAAK,sBAAsB,EACzB,WAAW,sBACb,CAAC;EAEH,KAAK,cAAc;EACnB,KAAK,aAAa;EAClB,KAAK,iBAAiB;CACxB;CAEA,kBAA0B,MAA+B;EACvD,IAAI,KAAK,cAAc,SAAS,KAAK,YAAY,OAAO;GACtD,KAAK,MAAM,KACT,eAAe,KAAK,iCAAiC,KAAK,YAAY,KAAK,CAAC,SAAS,EAAE,2CACzF;GAEA,KAAK,qBAAqB,MAAM,MAAM;GACtC,OAAO;EACT;EAEA,KAAK,cAAc,SAAS,KAAK,cAAc,SAAS,KAAK;EAC7D,OAAO;CACT;CAEA,eAAsB,MAAyB,MAAc;EAC3D,IAAI,KAAK,SAAS,KAAK,WAAW,OAAO;GACvC,KAAK,MAAM,KACT,cAAc,KAAK,6BAA6B,KAAK,WAAW,KAAK,CAAC,SAAS,EAAE,gBAAgB,KAAK,EACxG;GAEA,KAAK,qBAAqB,MAAM,iBAAiB;GACjD,OAAO,KAAK,UAAU,GAAG,KAAK,WAAW,KAAK;EAChD;EAEA,OAAO;CACT;CAEA,oBACE,MACA,YACA,SACA,WACA;EACA,MAAM,OAAO,OAAO,KAAK,UAAU;EAEnC,IAAI,KAAK,SAAS,KAAK,eAAe,OAAO;GAC3C,KAAK,MAAM,KACT,cAAc,KAAK,0CAA0C,KAAK,eAAe,KAAK,CAAC,SAAS,EAAE,KACpG;GACA,KAAK,qBAAqB,MAAM,qBAAqB;EACvD;EAEA,MAAM,sBAAkE,CAAC;EAEzE,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,KAAK,QAAQ,KAAK,eAAe,KAAK,GAAG,KAAK;GACzE,MAAM,eAAe,KAAK,eAAe,SAAS,KAAK,EAAE;GACzD,oBAAoB,gBAAgB,KAAK,eACvC,WACA,WAAW,KAAK,GAAG,EAAE,SAAS,KAAK,EACrC;EACF;EAEA,OAAO;CACT;CAEA,qBAA4B,WAAwC;EAClE,MAAM,OACJ,cAAc,SAAS,qBAAqB;EAC9C,OAAO,KAAK,kBAAkB,IAAI;CACpC;CAEA,0BAA0C;EACxC,OAAO,KAAK,kBAAkB,gBAAgB;CAChD;CAEA,yBAAyC;EACvC,OAAO,KAAK,kBAAkB,eAAe;CAC/C;CAEA,2BAA2C;EACzC,OAAO,KAAK,kBAAkB,iBAAiB;CACjD;CAEA,gBAAuB,MAA6C;EAClE,IAAI,KAAK,kBAAkB,YAAY,GACrC,OAAO;EAGT,OAAO,EACL,MAAM,KAAK,eAAe,cAAc,IAAI,EAC9C;CACF;CAEA,eACE,SACA,YAC8B;EAC9B,IAAI,KAAK,kBAAkB,WAAW,GACpC,OAAO;EAGT,OAAO;GACL,SAAS,KAAK,eAAe,aAAa,OAAO;GACjD,YAAY,KAAK,oBACf,aACA,YACA,2BACA,2BACF;EACF;CACF;CAEA,SACE,SACA,UACA,YACwB;EACxB,MAAM,UAAU,uBAAuB;EAEvC,IAAI,KAAK,kBAAkB,OAAO,GAChC,OAAO;EAGT,OAAO;GACL,SAAS,KAAK,eAAe,SAAS,OAAO;GAC7C,YAAY,KAAK,oBACf,SACA,YACA,qBACA,qBACF;EACF;CACF;CAEA,yBACE,KACA,OACwC;EACxC,IAAI,KAAK,kBAAkB,kBAAkB,GAC3C,OAAO;EAGT,OAAO;GACL,KAAK,KAAK,eAAe,wBAAwB,GAAG;GACpD,OAAO,KAAK,eAAe,0BAA0B,KAAK;EAC5D;CACF;CAEA,iBAAwB,MAA6B;EACnD,MAAM,OACJ,KAAK,WAAA,gBAAA,yBACD,oBACA;EAEN,OAAO,KAAK,kBAAkB,IAAI;CACpC;CAEA,QAAqB;EACnB,KAAK,oBAAoB,CAAC;EAC1B,KAAK,gBAAgB;GACnB,WAAW;GACX,WAAW;GACX,aAAa;GACb,UAAU;GACV,YAAY;GACZ,kBAAkB;GAClB,MAAM;GACN,iBAAiB;GACjB,kBAAkB;GAClB,qBAAqB;GACrB,gBAAgB;GAChB,eAAe;GACf,iBAAiB;EACnB;CACF;CAEA,qBAA6B,MAAmB,WAA2B;EACzE,MAAM,MAAM,yBAAyB,KAAK,GAAG,UAAU;EAEvD,KAAK,kBAAkB,QAAQ,KAAK,kBAAkB,QAAQ,KAAK;CACrE;CACA,sBAAqD;EACnD,OAAO,KAAK;CACd;AACF"}