posthog-js
Version:
Posthog-js allows you to automatically capture usage and send events to PostHog.
254 lines (253 loc) • 9.84 kB
TypeScript
export { RECORDING_REMOTE_CONFIG_TTL_MS } from '../../../constants';
import { EventType, eventWithTime, IncrementalSource } from '../types/rrweb-types';
import { SessionRecordingStatus, TriggerType } from './triggerMatching';
export { SEVEN_MEGABYTES, splitBuffer } from './sessionrecording-utils';
import { LazyLoadedSessionRecordingInterface } from '../../../utils/globals';
import { PostHog } from '../../../posthog-core';
import { Properties, SessionRecordingPersistedConfig, SessionStartReason } from '../../../types';
export declare const RECORDING_IDLE_THRESHOLD_MS: number;
export declare const RECORDING_MAX_EVENT_SIZE: number;
export declare const RECORDING_BUFFER_TIMEOUT = 2000;
export declare const SESSION_RECORDING_BATCH_KEY = "recordings";
export declare const PENDING_BUFFER_STORAGE_SUFFIX = "_replay_pending_buffer";
export interface SnapshotBuffer {
size: number;
data: any[];
sizes: number[];
sessionId: string;
windowId: string;
}
export type compressedFullSnapshotEvent = {
type: typeof EventType.FullSnapshot;
data: string;
};
export type compressedIncrementalSnapshotEvent = {
type: typeof EventType.IncrementalSnapshot;
data: {
source: IncrementalSource;
texts: string;
attributes: string;
removes: string;
adds: string;
};
};
export type compressedIncrementalStyleSnapshotEvent = {
type: typeof EventType.IncrementalSnapshot;
data: {
source: typeof IncrementalSource.StyleSheetRule;
id?: number;
styleId?: number;
replace?: string;
replaceSync?: string;
adds?: string;
removes?: string;
};
};
export type compressedEvent = compressedIncrementalStyleSnapshotEvent | compressedFullSnapshotEvent | compressedIncrementalSnapshotEvent;
export type compressedEventWithTime = compressedEvent & {
timestamp: number;
delay?: number;
cv: '2024-10';
};
export declare class LazyLoadedSessionRecording implements LazyLoadedSessionRecordingInterface {
private readonly _instance;
private _endpoint;
private _mutationThrottler?;
/**
* Util to help developers working on this feature manually override
*/
private _forceAllowLocalhostNetworkCapture;
private _stopRrweb;
private _jsonLdCapture;
private _jsonLdCaptureReady;
private _lastActivityTimestamp;
private _sessionStartTimestamp;
private _isActivatingTrigger;
/**
* if pageview capture is disabled,
* then we can manually track href changes
*/
private _lastHref?;
/**
* and a queue - that contains rrweb events that we want to send to rrweb, but rrweb wasn't able to accept them yet
*/
private _queuedRRWebEvents;
private _isIdle;
private _eventsDroppedWhileIdle;
private _throttledMutationsDropped;
private _oversizedMutationsDropped;
private _oversizedMutationBytesDropped;
private _unstringifiableEventsDropped;
private _holdFlushUntilInteraction;
private _flushHoldReason;
private _lastLoggedFlushHold;
private _heldEpochShipsOnUnload;
private _documentWasEverVisible;
private _heldBufferOverflowed;
private _suppressNextFreshStartHold;
private _rrwebError;
private _rrwebStartAttempted;
private _lastSeenSnapshotCost;
private _snapshotCostErrorLogged;
private _hasWarnedClientMaskingOverride;
private _hasWarnedExclusiveAttributeMasking;
private _maskRegionsFnFailed;
private _hasLoggedRecorderCallbackError;
private _linkedFlagMatching;
private _urlTriggerMatching;
private _eventTriggerMatching;
private _strategy;
private _fullSnapshotTimer?;
private _lastFullSnapshotSessionId;
private _fullSnapshotHealAttemptedFor;
private _windowId;
private _sessionId;
get sessionId(): string;
private _flushBufferTimer?;
private _buffer;
private readonly _pendingBufferStorageKey;
private _pendingBufferRestored;
private _lastParkedBufferSize;
private _compressionQueue?;
private _pendingCompressionEvents;
private _queuedCompressionEvents;
private _compressionQueueGeneration;
private _isStoppingAfterCompression;
private _removePageViewCaptureHook;
private _removeEventTriggerCaptureHook;
private _flushedSizeTracker;
private get _sessionManager();
private get _sessionIdleThresholdMilliseconds();
private get _isSampled();
private get _sampleRate();
private get _minimumDuration();
private _onSessionIdListener;
private _onSessionIdleResetForcedListener;
private _forceIdleSessionIdListener;
constructor(_instance: PostHog, documentWasEverVisible?: boolean);
setDocumentWasEverVisible(documentWasEverVisible: boolean): void;
private get _masking();
/**
* Client-side masking config in `posthog.init` intentionally wins over the "Privacy and masking"
* project setting (the remote config). That precedence is by-design, but silent: a developer who
* sets e.g. `maskTextSelector: '*'` locally can be surprised that their dashboard setting has no
* effect. Warn (once per recorder) when the two diverge so the override is self-explaining.
*/
private _warnIfClientMaskingShadowsServer;
private get _canvasResolutionScale();
private get _canvasRecording();
private get _isConsoleLogCaptureEnabled();
private get _networkPayloadCapture();
private _gatherRRWebPlugins;
private _stripUrlHash;
private _maskReplayUrl;
private _maskUrl;
private _tryRRWebMethod;
private _tryAddCustomEvent;
private _canCaptureJsonLd;
private _tryAddJsonLdEvent;
private _scheduleJsonLdScan;
private _pageViewFallBack;
private _processQueuedEvents;
private _tryTakeFullSnapshot;
private get _fullSnapshotIntervalMillis();
private _scheduleFullSnapshot;
private _onTriggerActivated;
private _pauseRecording;
private _resumeRecording;
private _activateTrigger;
get isStarted(): boolean;
get _remoteConfig(): SessionRecordingPersistedConfig | undefined;
private _checkOverride;
start(startReason?: SessionStartReason): void;
private _onSessionIdCallback;
private _teardown;
private _invalidateCompressionQueue;
private _stopRecordingProducers;
private _stopAfterCompressionQueueDrains;
stop(): void;
private _releaseHoldAfterStop;
flushBeforeIdentityReset(): void;
private _isRestartingForSessionIdChange;
private _restartForSessionIdChange;
private _setFlushHold;
private _releaseHoldAndFlush;
discard({ discardProducerEvents }?: {
discardProducerEvents?: boolean;
}): void;
private _captureProcessedEvent;
private _safeTrackFullSnapshotCost;
private _trackFullSnapshotCost;
private _ensureFullSnapshotForSession;
private _finishQueuedCompressionEvent;
private _captureQueuedCompressionEvent;
private _processQueuedCompressionEventSync;
private _drainCompressionQueueSync;
private _enqueueCompression;
onRRwebEmit(rawEvent: eventWithTime): void;
get status(): SessionRecordingStatus;
log(message: string, level?: 'log' | 'warn' | 'error'): void;
overrideLinkedFlag(): void;
/**
* this ignores the sampling config and (if other conditions are met) causes capture to start
*
* It is not usual to call this directly,
* instead call `posthog.startSessionRecording({sampling: true})`
* */
overrideSampling(): void;
/**
* this ignores the URL/Event trigger config and (if other conditions are met) causes capture to start
*
* It is not usual to call this directly,
* instead call `posthog.startSessionRecording({trigger: 'url' | 'event'})`
* */
overrideTrigger(triggerType: TriggerType): void;
private _currentMaskedHostname;
private _clearFlushBufferTimer;
private _scheduleFlushBuffer;
private _wouldOpenRecordingWithMarkersOnly;
/**
* Names the trigger conditions that are keeping the session in BUFFERING, so diagnostics can
* identify which leg failed instead of only reporting an unexplained "buffering". A URL trigger
* that never matches under the default AND matching otherwise looks like a session that is about
* to record.
*/
private _describePendingTriggerConditions;
private _lastLoggedBufferingReason;
private _maybeLogBufferingReason;
private _canParkPendingBuffer;
/**
* Parks the buffer for the next page in this tab. A timing gate holds the buffer for a retry
* that an unloading page never runs, so without this the snapshots die with the page and the
* recording opens partway through the session.
*/
private _parkBufferForNextPage;
private _restorePendingBuffer;
private _flushBuffer;
private _hasPassedMinimumDuration;
private _getBufferDuration;
private _isBelowMinimumDuration;
private _captureSnapshotBuffered;
private _captureSnapshot;
private get _sessionDuration();
private _clearBufferBeforeMostRecentMeta;
private _clearBuffer;
private _onBeforeUnload;
private _onPageHide;
private _onOffline;
private _onOnline;
private _onVisibilityChange;
private _reportStarted;
private _isInteractiveEvent;
private _updateWindowAndSessionIds;
private _clearConditionalRecordingPersistence;
get sdkDebugProperties(): Properties;
/**
* whether rrweb is observing the page, not merely constructed. rrweb returns its
* stop handler synchronously even when it defers init() to a document event, so a
* recorder that never observed anything would otherwise report itself as attached.
*/
private get _rrwebAttached();
private _startRecorder;
tryAddCustomEvent(tag: string, payload: any): boolean;
}