Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions bottlecap/src/lifecycle/invocation/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,13 @@ impl Processor {
self.runtime = Some(runtime);
}

self.dynamic_tags
.insert(String::from("cold_start"), cold_start.to_string());
// Skip cold_start tag in Managed Instance mode
// We don't want to send this tag for spans, as the experience
// won't look good due to the time gap in the flame graph.
if !self.aws_config.is_managed_instance_mode() {
self.dynamic_tags
.insert(String::from("cold_start"), cold_start.to_string());
}

if proactive_initialization {
self.dynamic_tags.insert(
Expand Down Expand Up @@ -305,6 +310,14 @@ impl Processor {
return;
};

// Skip creating cold start span in Managed Instances
// Although the telemetry is correct, we instead decide
// to not send it since the flame graph would show a big
// gap between the init and the first invocation.
if self.aws_config.is_managed_instance_mode() {
return;
}

// Create a cold start span
let mut cold_start_span = create_empty_span(
String::from("aws.lambda.cold_start"),
Expand Down
19 changes: 14 additions & 5 deletions integration-tests/tests/lmi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,31 @@ describe('LMI Integration Tests', () => {
expect(awsLambdaSpan?.attributes.custom.init_type).toBe('lambda-managed-instances')
})
// SVLS-8232
it('aws.lambda.span should have cold_start set to false if no cold_start operation', () => {
// In Managed Instance mode, cold_start span and tag are not sent by bottlecap
// because the concept is less meaningful with concurrent invocations
// and it would create a poor flame graph experience due to time gaps.
//
// Note: Node and Python tracers (dd-trace-js, dd-trace-py) set their own cold_start
// attribute on spans independently, so we skip the tag check for those runtimes.
it('aws.lambda.span should NOT have cold_start span or tag in LMI mode', () => {
const trace = results[runtime].traces![0];

// The presence of 'aws.lambda.cold_start' span indicates a cold start
// Verify no 'aws.lambda.cold_start' span exists in LMI mode
const coldStartSpan = trace.spans.find((span: any) =>
span.attributes.operation_name === 'aws.lambda.cold_start'
);
expect(coldStartSpan).toBeUndefined();

const awsLambdaSpan = trace.spans.find((span: any) =>
span.attributes.operation_name === 'aws.lambda'
);
expect(awsLambdaSpan).toBeDefined(); // Ensure span exists before checking attributes

// Only check cold_start attribute when no dedicated cold_start span exists
if (!coldStartSpan) {
expect(awsLambdaSpan?.attributes.custom.cold_start).toBe('false');
// Skip cold_start tag check for Node and Python since their tracer libraries
// (dd-trace-js, dd-trace-py) set the cold_start attribute independently.
// Only verify for Java and dotnet where bottlecap controls the span.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is our plan to fix this for Node and Python runtimes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be done separately until fixed, there's no way of checking this until its fixed there

if (runtime !== 'node' && runtime !== 'python') {
expect(awsLambdaSpan?.attributes.custom.cold_start).toBeUndefined();
}
})

Expand Down
Loading