Skip to content

Commit 5626043

Browse files
joe4devclaude
andcommitted
Emit INIT_REPORT for successful provisioned-concurrency init
On-demand cold-start inits fold their duration into the first invocation's REPORT line, but provisioned-concurrency / Managed Instances environments initialize ahead of time and their invokes omit "Init Duration". AWS instead emits a standalone INIT_REPORT line in the invoke-serving log stream carrying only the duration -- no Phase, Status, or Error Type (those appear only on failed or timed-out init lines). SendInitReport previously emitted nothing for these successful non-on-demand inits, so LocalStack's log stream diverged from AWS. Add the bare INIT_REPORT line for that case and update the unit test accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 4e2f91e commit 5626043

2 files changed

Lines changed: 23 additions & 7 deletions

File tree

cmd/localstack/events.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ import (
1616
// - START is emitted on SendInvokeStart, which rapid fires after any inline (suppressed)
1717
// init and before the runtime handles the invocation — so a re-run init's logs land
1818
// before START, matching AWS.
19-
// - INIT_REPORT is emitted on SendInitReport for failed or timed-out inits, with rapid's
20-
// authoritative duration and phase (init for the eager cold-start init, invoke for a
21-
// suppressed init folded into an invocation). AWS logs no INIT_REPORT for successful
22-
// inits; a successful on-demand cold-start init instead surfaces as the first
23-
// invocation's REPORT "Init Duration" (see TakeColdStartInitDuration).
19+
// - INIT_REPORT is emitted on SendInitReport for failed or timed-out inits (carrying a
20+
// Status and, for failures, an Error Type) and for successful provisioned-concurrency /
21+
// Managed Instances inits (a bare line carrying only the duration and phase). It uses
22+
// rapid's authoritative duration and phase (init for the eager cold-start init, invoke for
23+
// a suppressed init folded into an invocation). A successful on-demand cold-start init logs
24+
// no INIT_REPORT; its duration surfaces as the first invocation's REPORT "Init Duration"
25+
// instead (see TakeColdStartInitDuration).
2426
// - The scrubbed fatal error type of the most recent failed init (e.g. Runtime.ExitError,
2527
// Runtime.Unknown) is recorded for the invoke handler's REPORT Status/Error Type line and
2628
// for the init-failure report to LocalStack (see InitErrorType).
@@ -121,6 +123,13 @@ func (e *LocalStackEventsAPI) SendInitReport(data interop.InitReportData) error
121123
// REPORT "Init Duration" instead of an INIT_REPORT line.
122124
e.coldStartInitDuration = data.Metrics.DurationMs
123125
e.hasColdStartInitDuration = true
126+
case data.Phase == lambdatelemetry.InitInsideInitPhase:
127+
// Successful provisioned-concurrency / Managed Instances init (non-on-demand). Those
128+
// environments initialize ahead of time, so the duration cannot fold into a first
129+
// invocation's REPORT (their invokes omit Init Duration); AWS instead emits a bare
130+
// INIT_REPORT carrying only the duration — no Phase, Status, or Error Type (those
131+
// fields appear only on the failed/timed-out init lines above).
132+
line = fmt.Sprintf("INIT_REPORT Init Duration: %.2f ms\n", data.Metrics.DurationMs)
124133
}
125134
e.mu.Unlock()
126135
if line != "" {

cmd/localstack/events_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,22 @@ func TestEventsAPI_SuccessfulOnDemandInit_NoInitReportLine_DurationTakenOnce(t *
4848
assert.Empty(t, e.InitErrorType())
4949
}
5050

51-
func TestEventsAPI_SuccessfulProvisionedInit_NoDurationRecorded(t *testing.T) {
51+
func TestEventsAPI_SuccessfulProvisionedInit_RendersBareInitReport(t *testing.T) {
5252
logs := NewLogCollector()
5353
e := NewLocalStackEventsAPI(logs, false)
5454

5555
sendInit(t, e, "init", "success", "", 123.45)
5656

57-
// AWS omits Init Duration from provisioned-concurrency invokes' REPORT lines.
57+
// A successful provisioned-concurrency init emits a bare INIT_REPORT: only the duration,
58+
// with no Phase/Status/Error Type (those appear for failed or timed-out inits).
59+
assert.Equal(t,
60+
"INIT_REPORT Init Duration: 123.45 ms\n",
61+
logs.getLogs().Logs)
62+
// AWS omits Init Duration from provisioned-concurrency invokes' REPORT lines, so the
63+
// duration is not buffered for a first-invocation REPORT.
5864
_, ok := e.TakeColdStartInitDuration()
5965
assert.False(t, ok)
66+
assert.Empty(t, e.InitErrorType())
6067
}
6168

6269
func TestEventsAPI_FailedInit_RendersInitReportAndRecordsErrorType(t *testing.T) {

0 commit comments

Comments
 (0)