import type { RumEvent, RumEventDomainContext, RumInitConfiguration, RumResourceEventDomainContext, } from '@datadog/browser-rum'; import type { ApplicationBeforeSendHandler, ServiceBeforeSendHandler } from './before-send'; import { enrichEvent } from './enrich-event'; import { handleResource } from './handle-resource'; import type { State } from './types'; function applyBuiltIn(event: RumEvent, context: RumEventDomainContext): void { if (event.type === 'resource') { handleResource(event, context as RumResourceEventDomainContext); } enrichEvent(event, context); } function callApplicationHandler( handler: ApplicationBeforeSendHandler, event: RumEvent, context: RumEventDomainContext ): boolean { try { return handler(event, context) !== false; } catch { return true; } } function callServiceHandler( handler: ServiceBeforeSendHandler, event: RumEvent, context: RumEventDomainContext ): void { try { handler(event, context); } catch { // Fail-open: a service handler may not drop or block events. } } function applyApplication(state: State, event: RumEvent, context: RumEventDomainContext): boolean { if (state.applicationBeforeSend) { return callApplicationHandler(state.applicationBeforeSend, event, context); } return true; } function applyServiceSpecific(state: State, event: RumEvent, context: RumEventDomainContext): void { const serviceKey = event.service; if (!serviceKey) { return; } const entry = state.services.get(serviceKey); if (!entry) { return; } if (entry.beforeSend) { callServiceHandler(entry.beforeSend, event, context); } if (entry.context) { event.context = { ...event.context, ...entry.context }; } } export function buildBeforeSend(state: State): NonNullable { return function (event: RumEvent, context: RumEventDomainContext) { try { applyBuiltIn(event, context); if (!applyApplication(state, event, context)) { return false; } applyServiceSpecific(state, event, context); return true; } catch { // Fail-open: prefer noisy data over no data. return true; } }; }