{"version":3,"file":"EmbraceSessionPartBatchedSpanProcessor.cjs","names":["diag","BindOnceFuture","isSessionPartSpan","ExportResultCode"],"sources":["../../../src/processors/EmbraceSessionPartBatchedSpanProcessor/EmbraceSessionPartBatchedSpanProcessor.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport { diag } from '@opentelemetry/api';\nimport type { ExportResult } from '@opentelemetry/core';\nimport {\n  BindOnceFuture,\n  ExportResultCode,\n  // TODO: `internal._export` is an unstable OTel API; find a supported way to export a batch\n  internal,\n} from '@opentelemetry/core';\nimport type {\n  ReadableSpan,\n  SpanExporter,\n  SpanProcessor,\n} from '@opentelemetry/sdk-trace';\nimport type {\n  LimitManagerInternal,\n  UserSessionManagerInternal,\n} from '../../managers/index.ts';\nimport { isSessionPartSpan } from '../../utils/index.ts';\nimport type { EmbraceSessionPartBatchedSpanProcessorArgs } from './types.ts';\n\ntype ExportFailureReason = 'concurrent_limit' | 'fetch_error' | 'unknown';\n\nconst exportFailureAttributeKey = (\n  reason: ExportFailureReason,\n  session: 'current' | 'previous',\n) =>\n  `emb.${session === 'current' ? 'export_failed' : 'previous_export_failed'}.${reason}`;\n\nexport class EmbraceSessionPartBatchedSpanProcessor implements SpanProcessor {\n  private readonly _shutdownOnce: BindOnceFuture<void>;\n  private _pendingSpans: ReadableSpan[] = [];\n  private readonly _exporter: SpanExporter;\n  private readonly _limitManager: LimitManagerInternal;\n  private readonly _userSessionManager: UserSessionManagerInternal;\n  private readonly _diag: DiagLogger;\n\n  public constructor({\n    exporter,\n    limitManager,\n    userSessionManager,\n    diag: diagParam = diag.createComponentLogger({\n      namespace: 'EmbraceSessionPartBatchedSpanProcessor',\n    }),\n  }: EmbraceSessionPartBatchedSpanProcessorArgs) {\n    this._diag = diagParam;\n    this._exporter = exporter;\n    this._shutdownOnce = new BindOnceFuture(this._shutdown, this);\n    this._limitManager = limitManager;\n    this._userSessionManager = userSessionManager;\n  }\n\n  public forceFlush(): Promise<void> {\n    this._diag.debug(\n      'forceFlush called for EmbraceSessionPartBatchedSpanProcessor. This is a no op',\n    );\n    return Promise.resolve(undefined);\n  }\n\n  public onEnd(span: ReadableSpan): void {\n    if (this._shutdownOnce.isCalled) {\n      this._diag.debug('span ended after processor shutdown. Ignoring span.');\n      return;\n    }\n\n    if (!isSessionPartSpan(span)) {\n      this._diag.debug(\n        'non-session-part span ended. Adding to pending spans queue.',\n      );\n      if (this._limitManager.dropReadableSpan(span)) {\n        return;\n      }\n      this._pendingSpans.push(span);\n    } else {\n      this._diag.debug('session part span ended. Exporting all pending spans.');\n      this._exportSpans([span, ...this._pendingSpans]);\n      this._pendingSpans = [];\n    }\n  }\n\n  private _exportSpans(spans: ReadableSpan[]): void {\n    internal\n      ._export(this._exporter, spans)\n      .then((result: ExportResult) => {\n        if (result.code === ExportResultCode.FAILED) {\n          const errorMessage = result.error?.message || 'unknown error';\n          let failureReason: ExportFailureReason = 'unknown';\n\n          if (errorMessage === 'Concurrent export limit reached') {\n            failureReason = 'concurrent_limit';\n          } else if (errorMessage === 'Fetch request errored') {\n            failureReason = 'fetch_error';\n          }\n\n          this._userSessionManager.incrSessionPartCountForKey(\n            exportFailureAttributeKey(failureReason, 'current'),\n          );\n          this._userSessionManager.incrNextSessionPartCountForKey(\n            exportFailureAttributeKey(failureReason, 'previous'),\n          );\n          this._diag.error(`spans failed to export: ${errorMessage}`);\n        }\n      })\n      // Seems like everything related to the export logic does a good job of catching and only ever resolving with\n      // an ExportResult even on failure: https://github.com/open-telemetry/opentelemetry-js/blob/cf6dffeebcf72c42b2cb4d2bf2db720369b53081/packages/opentelemetry-core/src/internal/exporter.ts#L37\n      // Keep this block just in case that assumption changes in a future version\n      .catch((reason: unknown) => {\n        let msg = 'unknown error';\n        if (reason && reason instanceof Error) {\n          msg = reason.message;\n        } else if (typeof reason === 'string') {\n          msg = reason;\n        }\n\n        this._userSessionManager.incrSessionPartCountForKey(\n          exportFailureAttributeKey('unknown', 'current'),\n        );\n        this._userSessionManager.incrNextSessionPartCountForKey(\n          exportFailureAttributeKey('unknown', 'previous'),\n        );\n        this._diag.error(`spans failed to export: ${msg}`);\n      });\n  }\n\n  public onStart(): void {\n    // do nothing.\n  }\n\n  public shutdown(): Promise<void> {\n    return this._shutdownOnce.call();\n  }\n\n  private readonly _shutdown = () => {\n    return this._exporter.shutdown();\n  };\n}\n"],"mappings":";;;;;AAuBA,MAAM,6BACJ,QACA,YAEA,OAAO,YAAY,YAAY,kBAAkB,yBAAyB,GAAG;AAE/E,IAAa,yCAAb,MAA6E;CAC3E;CACA,gBAAwC,CAAC;CACzC;CACA;CACA;CACA;CAEA,YAAmB,EACjB,UACA,cACA,oBACA,MAAM,YAAYA,mBAAAA,KAAK,sBAAsB,EAC3C,WAAW,yCACb,CAAC,KAC4C;EAC7C,KAAK,QAAQ;EACb,KAAK,YAAY;EACjB,KAAK,gBAAgB,IAAIC,oBAAAA,eAAe,KAAK,WAAW,IAAI;EAC5D,KAAK,gBAAgB;EACrB,KAAK,sBAAsB;CAC7B;CAEA,aAAmC;EACjC,KAAK,MAAM,MACT,+EACF;EACA,OAAO,QAAQ,QAAQ,KAAA,CAAS;CAClC;CAEA,MAAa,MAA0B;EACrC,IAAI,KAAK,cAAc,UAAU;GAC/B,KAAK,MAAM,MAAM,qDAAqD;GACtE;EACF;EAEA,IAAI,CAACC,6BAAAA,kBAAkB,IAAI,GAAG;GAC5B,KAAK,MAAM,MACT,6DACF;GACA,IAAI,KAAK,cAAc,iBAAiB,IAAI,GAC1C;GAEF,KAAK,cAAc,KAAK,IAAI;EAC9B,OAAO;GACL,KAAK,MAAM,MAAM,uDAAuD;GACxE,KAAK,aAAa,CAAC,MAAM,GAAG,KAAK,aAAa,CAAC;GAC/C,KAAK,gBAAgB,CAAC;EACxB;CACF;CAEA,aAAqB,OAA6B;EAChD,oBAAA,SACG,QAAQ,KAAK,WAAW,KAAK,CAAC,CAC9B,MAAM,WAAyB;GAC9B,IAAI,OAAO,SAASC,oBAAAA,iBAAiB,QAAQ;IAC3C,MAAM,eAAe,OAAO,OAAO,WAAW;IAC9C,IAAI,gBAAqC;IAEzC,IAAI,iBAAiB,mCACnB,gBAAgB;SACX,IAAI,iBAAiB,yBAC1B,gBAAgB;IAGlB,KAAK,oBAAoB,2BACvB,0BAA0B,eAAe,SAAS,CACpD;IACA,KAAK,oBAAoB,+BACvB,0BAA0B,eAAe,UAAU,CACrD;IACA,KAAK,MAAM,MAAM,2BAA2B,cAAc;GAC5D;EACF,CAAC,CAAC,CAID,OAAO,WAAoB;GAC1B,IAAI,MAAM;GACV,IAAI,UAAU,kBAAkB,OAC9B,MAAM,OAAO;QACR,IAAI,OAAO,WAAW,UAC3B,MAAM;GAGR,KAAK,oBAAoB,2BACvB,0BAA0B,WAAW,SAAS,CAChD;GACA,KAAK,oBAAoB,+BACvB,0BAA0B,WAAW,UAAU,CACjD;GACA,KAAK,MAAM,MAAM,2BAA2B,KAAK;EACnD,CAAC;CACL;CAEA,UAAuB,CAEvB;CAEA,WAAiC;EAC/B,OAAO,KAAK,cAAc,KAAK;CACjC;CAEA,kBAAmC;EACjC,OAAO,KAAK,UAAU,SAAS;CACjC;AACF"}