Skip to content

Commit b49fe16

Browse files
improvement(logs): show Redacting status while PII masking runs (#5855)
* improvement(logs): show Redacting status while log-persist PII masking runs Log-stage PII redaction happens at persist time and can take minutes on large payloads, during which the Logs page showed the run as Running long after execution finished. The persist path now flips the log row to 'redacting' (guarded on 'running' so a concurrent cancellation is never clobbered) right before the masking work starts — only when the logs redaction stage is actually enabled — and the terminal update overwrites it with the final status. The Logs UI renders an amber non-filterable Redacting badge (row + details sidebar via the shared STATUS_CONFIG), keeps polling the detail query during the phase, and keeps resolving live progress markers. No migration: status is a free-text column, and the contract already types it as string. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1JYstmLHk9qMGyBDqYRcJ * fix(logs): never let the cosmetic redacting write abort log finalization Review finding: the status flip was awaited without failure isolation, so a transient DB error there rejected applyPiiRedaction before masking and the terminal update never ran. The write is display-only; catch and warn instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1JYstmLHk9qMGyBDqYRcJ --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent fad9728 commit b49fe16

4 files changed

Lines changed: 44 additions & 4 deletions

File tree

apps/sim/app/workspace/[workspaceId]/logs/logs.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,9 @@ export default function Logs() {
302302
(query: { state: { data?: WorkflowLogDetail } }) => {
303303
if (!isLive) return false
304304
const status = query.state.data?.status
305-
return status === 'running' || status === 'pending' ? ACTIVE_RUN_DETAIL_REFRESH_MS : false
305+
return status === 'running' || status === 'pending' || status === 'redacting'
306+
? ACTIVE_RUN_DETAIL_REFRESH_MS
307+
: false
306308
},
307309
[isLive]
308310
)

apps/sim/app/workspace/[workspaceId]/logs/utils.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@ export const LOG_COLUMNS = {
1818

1919
export const DELETED_WORKFLOW_LABEL = 'Deleted Workflow'
2020

21-
export type LogStatus = 'error' | 'pending' | 'running' | 'info' | 'cancelled' | 'cancelling'
21+
export type LogStatus =
22+
| 'error'
23+
| 'pending'
24+
| 'running'
25+
| 'redacting'
26+
| 'info'
27+
| 'cancelled'
28+
| 'cancelling'
2229

2330
/**
2431
* Maps raw status string to LogStatus for display.
@@ -29,6 +36,8 @@ export function getDisplayStatus(status: string | null | undefined): LogStatus {
2936
switch (status) {
3037
case 'running':
3138
return 'running'
39+
case 'redacting':
40+
return 'redacting'
3241
case 'pending':
3342
return 'pending'
3443
case 'cancelling':
@@ -55,6 +64,7 @@ export const STATUS_CONFIG: Record<
5564
error: { variant: 'red', label: 'Error', color: 'var(--text-error)', filterable: true },
5665
pending: { variant: 'amber', label: 'Pending', color: '#f59e0b', filterable: true },
5766
running: { variant: 'amber', label: 'Running', color: '#f59e0b', filterable: true },
67+
redacting: { variant: 'amber', label: 'Redacting', color: '#f59e0b', filterable: false },
5868
cancelling: { variant: 'amber', label: 'Cancelling...', color: '#f59e0b', filterable: false },
5969
cancelled: { variant: 'orange', label: 'Cancelled', color: '#f97316', filterable: true },
6070
info: {

apps/sim/lib/logs/execution/logger.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,8 @@ export class ExecutionLogger implements IExecutionLoggerService {
645645
private async applyPiiRedaction(
646646
workspaceId: string | null,
647647
payload: RedactablePayload,
648-
storeContext: { workflowId?: string | null; executionId: string; userId?: string | null }
648+
storeContext: { workflowId?: string | null; executionId: string; userId?: string | null },
649+
onRedactionStart?: () => Promise<void>
649650
): Promise<RedactablePayload> {
650651
if (!workspaceId) return payload
651652

@@ -666,6 +667,10 @@ export class ExecutionLogger implements IExecutionLoggerService {
666667
const config = resolveEffectivePiiRedaction({ orgSettings: row.orgSettings, workspaceId }).logs
667668
if (!config.enabled) return payload
668669

670+
// Masking large payloads can take a while; let the caller surface the phase
671+
// (e.g. flip the log row to 'redacting') before the slow work starts.
672+
await onRedactionStart?.()
673+
669674
// The string redactor can't reach values already offloaded to large-value
670675
// storage (>8MB refs). Always hydrate → mask → re-store them under the LOGS
671676
// policy, even if the block-output stage already masked before offload: that
@@ -867,6 +872,29 @@ export class ExecutionLogger implements IExecutionLoggerService {
867872
workflowId: existingLog?.workflowId ?? null,
868873
executionId,
869874
userId: actorUserId,
875+
},
876+
async () => {
877+
// Execution is done but the log payload is still being masked — surface
878+
// that as 'redacting' so the Logs UI doesn't show a stale 'running'.
879+
// Guarded on 'running' so a concurrent cancellation is never clobbered;
880+
// the terminal update below overwrites with the final status either way.
881+
// Purely cosmetic: a failed write must never abort masking/finalization.
882+
try {
883+
await db
884+
.update(workflowExecutionLogs)
885+
.set({ status: 'redacting' })
886+
.where(
887+
and(
888+
eq(workflowExecutionLogs.executionId, executionId),
889+
eq(workflowExecutionLogs.status, 'running')
890+
)
891+
)
892+
} catch (error) {
893+
logger.warn('Failed to set redacting status on execution log', {
894+
executionId,
895+
error: getErrorMessage(error),
896+
})
897+
}
870898
}
871899
)
872900

apps/sim/lib/logs/fetch-log-detail.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export async function fetchLogDetail({
176176
)
177177

178178
const liveMarkers =
179-
log.status === 'running' || log.status === 'pending'
179+
log.status === 'running' || log.status === 'pending' || log.status === 'redacting'
180180
? ((await getProgressMarkers(log.executionId)) ?? {})
181181
: {}
182182
const rowMarkers = (executionData ?? {}) as ExecutionProgressMarkers

0 commit comments

Comments
 (0)