Files
openclaw/src/logging/message-lifecycle.ts
Peter Steinberger baab4cf045 refactor(logging): share diagnostic message lifecycle
Refactor diagnostic queued/state/processed emission into a shared helper used by dispatch and isolated cron turns.

Preserve dispatch processed-event behavior, cron queue-depth symmetry, and final cron session-id adoption while adding focused helper coverage and reviewer comments for the non-obvious invariants.
2026-05-25 19:48:45 +01:00

95 lines
2.7 KiB
TypeScript

import { logMessageProcessed, logMessageQueued, logSessionStateChange } from "./diagnostic.js";
type MessageLifecycleRef = {
sessionId?: string;
sessionKey?: string;
};
type MessageLifecycleOutcome = "completed" | "skipped" | "error";
type MessageLifecycleProcessedOptions = MessageLifecycleRef & {
durationMs?: number;
reason?: string;
error?: string;
};
export function createDiagnosticMessageLifecycle(
params: MessageLifecycleRef & {
enabled: boolean;
channel: string;
source: string;
chatId?: number | string;
messageId?: number | string;
processingReason?: string;
startedAtMs?: number;
trackSessionState: boolean;
},
) {
const startedAtMs = params.startedAtMs ?? Date.now();
const resolveRef = (override?: MessageLifecycleRef): MessageLifecycleRef => ({
sessionId: override?.sessionId ?? params.sessionId,
sessionKey: override?.sessionKey ?? params.sessionKey,
});
const hasSessionRef = (ref: MessageLifecycleRef): boolean =>
Boolean(ref.sessionId || ref.sessionKey);
// Processed events still matter without a session ref; queue-depth/state events do not.
const canTrackSessionState = (ref: MessageLifecycleRef): boolean =>
params.enabled && params.trackSessionState && hasSessionRef(ref);
return {
markProcessing(override?: MessageLifecycleRef): void {
const ref = resolveRef(override);
if (!canTrackSessionState(ref)) {
return;
}
logMessageQueued({
sessionId: ref.sessionId,
sessionKey: ref.sessionKey,
channel: params.channel,
source: params.source,
});
logSessionStateChange({
sessionId: ref.sessionId,
sessionKey: ref.sessionKey,
state: "processing",
reason: params.processingReason,
});
},
markIdle(reason?: string, override?: MessageLifecycleRef): void {
const ref = resolveRef(override);
if (!canTrackSessionState(ref)) {
return;
}
logSessionStateChange({
sessionId: ref.sessionId,
sessionKey: ref.sessionKey,
state: "idle",
reason,
});
},
markProcessed(
outcome: MessageLifecycleOutcome,
options?: MessageLifecycleProcessedOptions,
): void {
if (!params.enabled) {
return;
}
const ref = resolveRef(options);
logMessageProcessed({
channel: params.channel,
chatId: params.chatId,
messageId: params.messageId,
sessionId: ref.sessionId,
sessionKey: ref.sessionKey,
durationMs: options?.durationMs ?? Date.now() - startedAtMs,
outcome,
reason: options?.reason,
error: options?.error,
});
},
};
}