/* eslint no-void: [ "error", { "allowAsStatement": true } ] */ import { BatchSpanProcessorBase } from "@apexthirdparty/opentelemetry-sdk-trace-base/build/src/export/BatchSpanProcessorBase"; /** * Span processor {@link SpanProcessor} that auto-flushes on the following browser events: * - `visibilitychange` to `hidden` -- covers most scenarios for changing or closing a tab, and internal navigations * - `pagehide` -- as a fallback for Safari * - `beforeunload` -- covers corner-cases for external navigations * * This class extends {@link BatchSpanProcessorBase} and duplicates functionality of * {@link BatchSpanProcessor}, to avoid an issue where event listeners were * attached and executed multiple times. */ export class AutoFlushBatchSpanProcessor extends BatchSpanProcessorBase { constructor( exporter, config ) { super( exporter, config ); this.onInit(); } /** * Initialize the span processor by setting up the event listeners. * * This may call `forceFlush()` multiple times if multiple listeners are triggered * for a given event. This appears to be fine -- the first call "wins" and subsequent * calls do nothing. It may be possible to use another feature like `bindOnceFuture` * to debounce calls, but some internal state may be needed to reset the bound * functions on refocus, which could be unreliable and introduce inconsistencies. */ onInit() { if ( typeof document !== "undefined" ) { this._visibilityChangeListener = () => { if ( document.visibilityState === "hidden" ) { void this.forceFlush(); } }; this._pageHideListener = () => { void this.forceFlush(); }; document.addEventListener( "visibilitychange", this._visibilityChangeListener ); document.addEventListener( "pagehide", this._pageHideListener ); } if ( typeof window !== "undefined" ) { this._beforeUnloadListener = () => { void this.forceFlush(); }; window.addEventListener( "beforeunload", this._beforeUnloadListener ); } } /** * Callback executed on tracer `shutdown`. * * Used to cleanup event listeners. */ onShutdown() { if ( typeof document !== "undefined" ) { if ( this._visibilityChangeListener ) { document.removeEventListener( "visibilitychange", this._visibilityChangeListener ); } if ( this._pageHideListener ) { document.removeEventListener( "pagehide", this._pageHideListener ); } } if ( typeof window !== "undefined" ) { if ( this._beforeUnloadListener ) { window.removeEventListener( "beforeunload", this._beforeUnloadListener ); } } } }