






















@@ -612,6 +612,17 @@ export type DiagnosticTelemetryExporterEvent = DiagnosticBaseEvent & {
612612errorCategory?: string;
613613};
614614615+export type DiagnosticAsyncQueueDroppedEvent = DiagnosticBaseEvent & {
616+type: "diagnostic.async_queue.dropped";
617+droppedEvents: number;
618+droppedTrustedEvents?: number;
619+droppedUntrustedEvents?: number;
620+droppedPriorityEvents?: number;
621+queueLength: number;
622+maxQueueLength: number;
623+drainBatchSize: number;
624+};
625+615626export type DiagnosticEventPayload =
616627| DiagnosticUsageEvent
617628| DiagnosticWebhookReceivedEvent
@@ -660,6 +671,7 @@ export type DiagnosticEventPayload =
660671| DiagnosticPayloadLargeEvent
661672| DiagnosticLogRecordEvent
662673| DiagnosticTelemetryExporterEvent
674+| DiagnosticAsyncQueueDroppedEvent
663675| DiagnosticFailoverEvent;
664676665677export type DiagnosticEventInput = DiagnosticEventPayload extends infer Event
@@ -690,6 +702,10 @@ type DiagnosticEventsGlobalState = {
690702dispatchDepth: number;
691703asyncQueue: QueuedDiagnosticEvent[];
692704asyncDrainScheduled: boolean;
705+asyncDroppedEvents: number;
706+asyncDroppedTrustedEvents: number;
707+asyncDroppedUntrustedEvents: number;
708+asyncDroppedPriorityEvents: number;
693709};
694710695711const MAX_ASYNC_DIAGNOSTIC_EVENTS = 10_000;
@@ -731,6 +747,10 @@ function createDiagnosticEventsState(): DiagnosticEventsGlobalState {
731747dispatchDepth: 0,
732748asyncQueue: [],
733749asyncDrainScheduled: false,
750+asyncDroppedEvents: 0,
751+asyncDroppedTrustedEvents: 0,
752+asyncDroppedUntrustedEvents: 0,
753+asyncDroppedPriorityEvents: 0,
734754};
735755}
736756@@ -754,6 +774,10 @@ function getDiagnosticEventsState(): DiagnosticEventsGlobalState {
754774const globalRecord = globalThis as Record<PropertyKey, unknown>;
755775const existing = globalRecord[DIAGNOSTIC_EVENTS_STATE_KEY];
756776if (isDiagnosticEventsState(existing)) {
777+existing.asyncDroppedEvents ??= 0;
778+existing.asyncDroppedTrustedEvents ??= 0;
779+existing.asyncDroppedUntrustedEvents ??= 0;
780+existing.asyncDroppedPriorityEvents ??= 0;
757781return existing;
758782}
759783const state = createDiagnosticEventsState();
@@ -834,15 +858,31 @@ function isPriorityAsyncDiagnosticEvent(entry: QueuedDiagnosticEvent): boolean {
834858return entry.metadata.trusted && PRIORITY_ASYNC_DIAGNOSTIC_EVENT_TYPES.has(entry.event.type);
835859}
836860837-function makeRoomForPriorityAsyncDiagnosticEvent(state: DiagnosticEventsGlobalState): void {
861+function noteAsyncDiagnosticDrop(
862+state: DiagnosticEventsGlobalState,
863+entry: QueuedDiagnosticEvent,
864+): void {
865+state.asyncDroppedEvents += 1;
866+if (entry.metadata.trusted) {
867+state.asyncDroppedTrustedEvents += 1;
868+} else {
869+state.asyncDroppedUntrustedEvents += 1;
870+}
871+if (isPriorityAsyncDiagnosticEvent(entry)) {
872+state.asyncDroppedPriorityEvents += 1;
873+}
874+}
875+876+function makeRoomForPriorityAsyncDiagnosticEvent(
877+state: DiagnosticEventsGlobalState,
878+): QueuedDiagnosticEvent | undefined {
838879const nonPriorityIndex = state.asyncQueue.findIndex(
839880(entry) => !isPriorityAsyncDiagnosticEvent(entry),
840881);
841882if (nonPriorityIndex >= 0) {
842-state.asyncQueue.splice(nonPriorityIndex, 1);
843-return;
883+return state.asyncQueue.splice(nonPriorityIndex, 1)[0];
844884}
845-state.asyncQueue.shift();
885+return state.asyncQueue.shift();
846886}
847887848888function deepFreezeDiagnosticValue(value: unknown, seen = new WeakSet<object>()): unknown {
@@ -878,8 +918,35 @@ function scheduleAsyncDiagnosticDrain(state: DiagnosticEventsGlobalState): void
878918}
879919if (state.asyncQueue.length > 0) {
880920scheduleAsyncDiagnosticDrain(state);
921+return;
881922}
923+dispatchAsyncDiagnosticDropSummary(state);
924+});
925+}
926+927+function dispatchAsyncDiagnosticDropSummary(state: DiagnosticEventsGlobalState): void {
928+if (state.asyncDroppedEvents <= 0) {
929+return;
930+}
931+const droppedEvents = state.asyncDroppedEvents;
932+const droppedTrustedEvents = state.asyncDroppedTrustedEvents;
933+const droppedUntrustedEvents = state.asyncDroppedUntrustedEvents;
934+const droppedPriorityEvents = state.asyncDroppedPriorityEvents;
935+state.asyncDroppedEvents = 0;
936+state.asyncDroppedTrustedEvents = 0;
937+state.asyncDroppedUntrustedEvents = 0;
938+state.asyncDroppedPriorityEvents = 0;
939+const event = enrichDiagnosticEvent(state, {
940+type: "diagnostic.async_queue.dropped",
941+ droppedEvents,
942+ ...(droppedTrustedEvents > 0 ? { droppedTrustedEvents } : {}),
943+ ...(droppedUntrustedEvents > 0 ? { droppedUntrustedEvents } : {}),
944+ ...(droppedPriorityEvents > 0 ? { droppedPriorityEvents } : {}),
945+queueLength: state.asyncQueue.length,
946+maxQueueLength: MAX_ASYNC_DIAGNOSTIC_EVENTS,
947+drainBatchSize: MAX_ASYNC_DIAGNOSTIC_EVENTS_PER_TURN,
882948});
949+dispatchDiagnosticEvent(state, event, { trusted: false });
883950}
884951885952export async function waitForDiagnosticEventsDrained(): Promise<void> {
@@ -919,9 +986,13 @@ function emitDiagnosticEventWithTrust(event: DiagnosticEventInput, trusted: bool
919986if (ASYNC_DIAGNOSTIC_EVENT_TYPES.has(enriched.type)) {
920987if (state.asyncQueue.length >= MAX_ASYNC_DIAGNOSTIC_EVENTS) {
921988if (!trusted || !PRIORITY_ASYNC_DIAGNOSTIC_EVENT_TYPES.has(enriched.type)) {
989+noteAsyncDiagnosticDrop(state, { event: enriched, metadata });
922990return;
923991}
924-makeRoomForPriorityAsyncDiagnosticEvent(state);
992+const droppedEntry = makeRoomForPriorityAsyncDiagnosticEvent(state);
993+if (droppedEntry) {
994+noteAsyncDiagnosticDrop(state, droppedEntry);
995+}
925996}
926997state.asyncQueue.push({ event: enriched, metadata });
927998scheduleAsyncDiagnosticDrain(state);
@@ -999,4 +1070,8 @@ export function resetDiagnosticEventsForTest(): void {
9991070state.dispatchDepth = 0;
10001071state.asyncQueue = [];
10011072state.asyncDrainScheduled = false;
1073+state.asyncDroppedEvents = 0;
1074+state.asyncDroppedTrustedEvents = 0;
1075+state.asyncDroppedUntrustedEvents = 0;
1076+state.asyncDroppedPriorityEvents = 0;
10021077}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。