()
| 705 | * This should be called before logout or org switching to prevent data leakage. |
| 706 | */ |
| 707 | export async function flushTelemetry(): Promise<void> { |
| 708 | const meterProvider = getMeterProvider() |
| 709 | if (!meterProvider) { |
| 710 | return |
| 711 | } |
| 712 | |
| 713 | const timeoutMs = parseInt( |
| 714 | process.env.CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS || '5000', |
| 715 | ) |
| 716 | |
| 717 | try { |
| 718 | const flushPromises = [meterProvider.forceFlush()] |
| 719 | const loggerProvider = getLoggerProvider() |
| 720 | if (loggerProvider) { |
| 721 | flushPromises.push(loggerProvider.forceFlush()) |
| 722 | } |
| 723 | const tracerProvider = getTracerProvider() |
| 724 | if (tracerProvider) { |
| 725 | flushPromises.push(tracerProvider.forceFlush()) |
| 726 | } |
| 727 | |
| 728 | await Promise.race([ |
| 729 | Promise.all(flushPromises), |
| 730 | telemetryTimeout(timeoutMs, 'OpenTelemetry flush timeout'), |
| 731 | ]) |
| 732 | |
| 733 | logForDebugging('Telemetry flushed successfully') |
| 734 | } catch (error) { |
| 735 | if (error instanceof TelemetryTimeoutError) { |
| 736 | logForDebugging( |
| 737 | `Telemetry flush timed out after ${timeoutMs}ms. Some metrics may not be exported.`, |
| 738 | { level: 'warn' }, |
| 739 | ) |
| 740 | } else { |
| 741 | logForDebugging(`Telemetry flush failed: ${errorMessage(error)}`, { |
| 742 | level: 'error', |
| 743 | }) |
| 744 | } |
| 745 | // Don't throw - allow logout to continue even if flush fails |
| 746 | } |
| 747 | } |
| 748 | |
| 749 | function parseOtelHeadersEnvVar(): Record<string, string> { |
| 750 | const headers: Record<string, string> = {} |
no test coverage detected