You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
duration_ms: emitted automatically on logEnd(step, result) using performance.now() delta from logStart(step).
error_class: passed explicitly by callers when throwing (logError(msg, { error_class: 'TRANSIENT', ... })).
End-of-run summary: each entrypoint script calls logSummary({ success, steps_completed, errors }) in a finally block.
Out:
External observability platform (no Datadog, no OpenTelemetry export).
Changes to log verbosity defaults (existing log lines must remain unchanged in shape).
🧪 Acceptance criteria
Functional
Every log line emitted after setLogContext() includes run_id, step, and attempt.
logStart('ai-call') / logEnd('ai-call', 'success') pair emits a line with duration_ms populated.
The final logSummary() call emits a line with { msg: 'run_summary', success: true|false, steps_completed, errors }.
Edge cases
Log lines emitted before setLogContext() is called (e.g., during secret validation) still emit without crashing — missing context fields are simply absent, not undefined literals.
If logEnd is called without a prior logStart for that step, it emits the line without duration_ms (no throw).
If the process exits via unhandledRejection, the summary is still emitted (hook into the existing handler in auto_fix_pr.mjs).
🎯 Goal
Make every run fully diagnosable from logs alone — no manual correlation across job outputs required.
📍 Context
scripts/lib/logger.mjs,scripts/auto_fix_pr.mjs,scripts/generate_issue_change.mjs🚀 Description
logger.mjsalready emits structured JSON lines — a solid foundation. The gaps are:run_idfield: log lines from a single run cannot be correlated across the multi-job workflow (load-labels→auto-fix→ commit step).stepfield: impossible to know which pipeline stage emitted a given log line.attemptfield: retry context is invisible in logs (Groq 429 retries do lograte_limit_retrywithattempt, but this is not standardized).duration_msfield: no per-step latency data.error_classfield:TRANSIENT/PERMANENT/UNKNOWN(from issue [FEATURE] Unified TRANSIENT/PERMANENT/UNKNOWN error taxonomy #109) never surfaces in logs.🧩 Scope
In:
scripts/lib/logger.mjs: add a module-level context object set once at startup:log()anderror()calls automatically merge this context into every emitted line.setLogContext({ run_id, step, attempt })so entrypoint scripts can set it at the top.run_id: useprocess.env.GITHUB_RUN_ID ?? crypto.randomUUID()(available in all GitHub Actions jobs).step: free-form string set by the caller ('ai-call','label-apply','comment-post', etc.).attempt: integer, set by the retry utility (issue [FEATURE] Bounded exponential retry with jitter for external calls #111) when retrying.duration_ms: emitted automatically onlogEnd(step, result)usingperformance.now()delta fromlogStart(step).error_class: passed explicitly by callers when throwing (logError(msg, { error_class: 'TRANSIENT', ... })).logSummary({ success, steps_completed, errors })in afinallyblock.Out:
🧪 Acceptance criteria
Functional
setLogContext()includesrun_id,step, andattempt.logStart('ai-call')/logEnd('ai-call', 'success')pair emits a line withduration_mspopulated.logSummary()call emits a line with{ msg: 'run_summary', success: true|false, steps_completed, errors }.Edge cases
setLogContext()is called (e.g., during secret validation) still emit without crashing — missing context fields are simply absent, notundefinedliterals.logEndis called without a priorlogStartfor that step, it emits the line withoutduration_ms(no throw).unhandledRejection, the summary is still emitted (hook into the existing handler inauto_fix_pr.mjs).Tests
log('foo')aftersetLogContext({ run_id: 'r1', step: 's1', attempt: 2 })emits{ run_id: 'r1', step: 's1', attempt: 2, msg: 'foo' }.logStart+logEndpair emits a line whereduration_msis a non-negative number.log('foo')before anysetLogContext()call does not throw and does not includerun_id.run_summaryline as the last structured log event.⚙️ Constraints
log()anderror()call sites must require zero changes (context is injected automatically).crypto.randomUUIDandperformance.noware built into Node 20).