Skip to content

Commit 0548d77

Browse files
authored
aj/fix lazy imports (#393)
* fix: fix lazily loaded imports * feat: Fix lazy loaded imports * fix: format
1 parent 16a0a03 commit 0548d77

File tree

5 files changed

+106
-7
lines changed

5 files changed

+106
-7
lines changed

src/runtime/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { load, loadSync } from "./user-function";
2-
export { subscribeToDC, getTraceTree, RequireNode } from "./require-tracer"
2+
export { subscribeToDC, getTraceTree, clearTraceTree, RequireNode } from "./require-tracer"

src/runtime/require-tracer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class RequireNode {
2222

2323
const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
2424
const moduleLoadEndChannel = dc.channel('dd-trace:moduleLoadEnd')
25-
const rootNodes: RequireNode[] = []
25+
let rootNodes: RequireNode[] = []
2626

2727
const requireStack: RequireNode[] = []
2828
const pushNode = (data: any) => {
@@ -56,3 +56,7 @@ export const subscribeToDC = () => {
5656
export const getTraceTree = (): RequireNode[] => {
5757
return rootNodes
5858
}
59+
60+
export const clearTraceTree = () => {
61+
rootNodes = []
62+
}

src/trace/cold-start-tracer.spec.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ describe("ColdStartTracer", () => {
7272
currentSpanStartTime: 500,
7373
minDuration: 1,
7474
ignoreLibs: "",
75+
isColdStart: true,
7576
};
7677
const coldStartTracer = new ColdStartTracer(coldStartConfig);
7778
coldStartTracer.trace(requireNodes);
@@ -162,6 +163,7 @@ describe("ColdStartTracer", () => {
162163
currentSpanStartTime: 500,
163164
minDuration: 1,
164165
ignoreLibs: "myChildModule,myCoreModule",
166+
isColdStart: true,
165167
};
166168
const coldStartTracer = new ColdStartTracer(coldStartConfig);
167169
coldStartTracer.trace(requireNodes);
@@ -194,4 +196,86 @@ describe("ColdStartTracer", () => {
194196
service: "aws.lambda",
195197
});
196198
});
199+
it("traces lazy imports", () => {
200+
const requireNodes: RequireNode[] = [
201+
{
202+
id: "handler",
203+
filename: "/var/task/handler.js",
204+
startTime: 1,
205+
endTime: 6,
206+
children: [
207+
{
208+
id: "myChildModule",
209+
filename: "/opt/nodejs/node_modules/my-child-module.js",
210+
startTime: 2,
211+
endTime: 3,
212+
},
213+
{
214+
id: "myCoreModule",
215+
filename: "http",
216+
startTime: 4,
217+
endTime: 5,
218+
},
219+
{
220+
id: "aws-sdk",
221+
filename: "/var/runtime/aws-sdk",
222+
startTime: 4,
223+
endTime: 5,
224+
},
225+
],
226+
} as any as RequireNode,
227+
];
228+
const coldStartConfig: ColdStartTracerConfig = {
229+
tracerWrapper: new TracerWrapper(),
230+
parentSpan: {
231+
span: {},
232+
name: "my-parent-span",
233+
} as any as SpanWrapper,
234+
lambdaFunctionName: "my-function-name",
235+
currentSpanStartTime: 500,
236+
minDuration: 1,
237+
ignoreLibs: "",
238+
isColdStart: false,
239+
};
240+
const coldStartTracer = new ColdStartTracer(coldStartConfig);
241+
coldStartTracer.trace(requireNodes);
242+
expect(mockStartSpan).toHaveBeenCalledTimes(4);
243+
expect(mockFinishSpan).toHaveBeenCalledTimes(4);
244+
const span1 = mockStartSpan.mock.calls[0];
245+
expect(span1[0]).toEqual("aws.lambda.require");
246+
expect(span1[1].tags).toEqual({
247+
operation_name: "aws.lambda.require",
248+
"resource.name": "handler",
249+
resource_names: "handler",
250+
service: "aws.lambda",
251+
filename: "/var/task/handler.js",
252+
});
253+
const span2 = mockStartSpan.mock.calls[1];
254+
expect(span2[0]).toEqual("aws.lambda.require_layer");
255+
expect(span2[1].tags).toEqual({
256+
filename: "/opt/nodejs/node_modules/my-child-module.js",
257+
operation_name: "aws.lambda.require_layer",
258+
"resource.name": "myChildModule",
259+
resource_names: "myChildModule",
260+
service: "aws.lambda",
261+
});
262+
const span3 = mockStartSpan.mock.calls[2];
263+
expect(span3[0]).toEqual("aws.lambda.require_core_module");
264+
expect(span3[1].tags).toEqual({
265+
filename: "http",
266+
operation_name: "aws.lambda.require_core_module",
267+
"resource.name": "myCoreModule",
268+
resource_names: "myCoreModule",
269+
service: "aws.lambda",
270+
});
271+
const span4 = mockStartSpan.mock.calls[3];
272+
expect(span4[0]).toEqual("aws.lambda.require_runtime");
273+
expect(span4[1].tags).toEqual({
274+
filename: "/var/runtime/aws-sdk",
275+
operation_name: "aws.lambda.require_runtime",
276+
"resource.name": "aws-sdk",
277+
resource_names: "aws-sdk",
278+
service: "aws.lambda",
279+
});
280+
});
197281
});

src/trace/cold-start-tracer.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface ColdStartTracerConfig {
99
currentSpanStartTime: number;
1010
minDuration: number;
1111
ignoreLibs: string;
12+
isColdStart: boolean;
1213
}
1314

1415
export class ColdStartTracer {
@@ -18,6 +19,7 @@ export class ColdStartTracer {
1819
private currentSpanStartTime: number;
1920
private minDuration: number;
2021
private ignoreLibs: string[];
22+
private isColdStart: boolean;
2123

2224
constructor(coldStartTracerConfig: ColdStartTracerConfig) {
2325
this.tracerWrapper = coldStartTracerConfig.tracerWrapper;
@@ -26,14 +28,21 @@ export class ColdStartTracer {
2628
this.currentSpanStartTime = coldStartTracerConfig.currentSpanStartTime;
2729
this.minDuration = coldStartTracerConfig.minDuration;
2830
this.ignoreLibs = coldStartTracerConfig.ignoreLibs.split(",");
31+
this.isColdStart = coldStartTracerConfig.isColdStart;
2932
}
3033

3134
trace(rootNodes: RequireNode[]) {
3235
const coldStartSpanStartTime = rootNodes[0]?.startTime;
3336
const coldStartSpanEndTime = Math.min(rootNodes[rootNodes.length - 1]?.endTime, this.currentSpanStartTime);
34-
const coldStartSpan = this.createColdStartSpan(coldStartSpanStartTime, coldStartSpanEndTime, this.parentSpan);
37+
let targetParentSpan: SpanWrapper | undefined;
38+
if (this.isColdStart) {
39+
const coldStartSpan = this.createColdStartSpan(coldStartSpanStartTime, coldStartSpanEndTime, this.parentSpan);
40+
targetParentSpan = coldStartSpan;
41+
} else {
42+
targetParentSpan = this.parentSpan;
43+
}
3544
for (const coldStartNode of rootNodes) {
36-
this.traceTree(coldStartNode, coldStartSpan);
45+
this.traceTree(coldStartNode, targetParentSpan);
3746
}
3847
}
3948

src/trace/listener.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { patchConsole } from "./patch-console";
1919
import { SpanContext, TraceOptions, TracerWrapper } from "./tracer-wrapper";
2020
import { SpanInferrer } from "./span-inferrer";
2121
import { SpanWrapper } from "./span-wrapper";
22-
import { getTraceTree } from "../runtime/index";
22+
import { getTraceTree, clearTraceTree } from "../runtime/index";
2323
export type TraceExtractor = (event: any, context: Context) => Promise<TraceContext> | TraceContext;
2424

2525
export interface TraceConfig {
@@ -157,17 +157,19 @@ export class TraceListener {
157157
tagObject(this.tracerWrapper.currentSpan, "function.response", result);
158158
}
159159
const coldStartNodes = getTraceTree();
160-
if (coldStartNodes.length > 0 && didFunctionColdStart()) {
160+
if (coldStartNodes.length > 0) {
161161
const coldStartConfig: ColdStartTracerConfig = {
162162
tracerWrapper: this.tracerWrapper,
163-
parentSpan: this.inferredSpan || this.wrappedCurrentSpan,
163+
parentSpan: didFunctionColdStart() ? this.inferredSpan || this.wrappedCurrentSpan : this.wrappedCurrentSpan,
164164
lambdaFunctionName: this.context?.functionName,
165165
currentSpanStartTime: this.wrappedCurrentSpan?.startTime(),
166166
minDuration: this.config.minColdStartTraceDuration,
167167
ignoreLibs: this.config.coldStartTraceSkipLib,
168+
isColdStart: didFunctionColdStart(),
168169
};
169170
const coldStartTracer = new ColdStartTracer(coldStartConfig);
170171
coldStartTracer.trace(coldStartNodes);
172+
clearTraceTree();
171173
}
172174
if (this.triggerTags) {
173175
const statusCode = extractHTTPStatusCodeTag(this.triggerTags, result, isResponseStreamFunction);

0 commit comments

Comments
 (0)