autotel-aws 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +540 -0
- package/dist/attributes.cjs +49 -0
- package/dist/attributes.cjs.map +1 -0
- package/dist/attributes.d.cts +117 -0
- package/dist/attributes.d.ts +117 -0
- package/dist/attributes.js +4 -0
- package/dist/attributes.js.map +1 -0
- package/dist/chunk-35F3UBOO.cjs +48 -0
- package/dist/chunk-35F3UBOO.cjs.map +1 -0
- package/dist/chunk-4TGVGEUN.cjs +84 -0
- package/dist/chunk-4TGVGEUN.cjs.map +1 -0
- package/dist/chunk-CIGXV6HA.js +192 -0
- package/dist/chunk-CIGXV6HA.js.map +1 -0
- package/dist/chunk-D5INYMRP.cjs +350 -0
- package/dist/chunk-D5INYMRP.cjs.map +1 -0
- package/dist/chunk-DF5PT3JK.js +387 -0
- package/dist/chunk-DF5PT3JK.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-DHHLKZHI.cjs +23 -0
- package/dist/chunk-DHHLKZHI.cjs.map +1 -0
- package/dist/chunk-FKZOELBT.js +78 -0
- package/dist/chunk-FKZOELBT.js.map +1 -0
- package/dist/chunk-HMTKKKKP.cjs +390 -0
- package/dist/chunk-HMTKKKKP.cjs.map +1 -0
- package/dist/chunk-I4CKQ4RD.js +153 -0
- package/dist/chunk-I4CKQ4RD.js.map +1 -0
- package/dist/chunk-JEQ2X3Z6.cjs +12 -0
- package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
- package/dist/chunk-JMSFE6FJ.js +24 -0
- package/dist/chunk-JMSFE6FJ.js.map +1 -0
- package/dist/chunk-KUIOI74B.cjs +394 -0
- package/dist/chunk-KUIOI74B.cjs.map +1 -0
- package/dist/chunk-NQ65Y5AI.cjs +195 -0
- package/dist/chunk-NQ65Y5AI.cjs.map +1 -0
- package/dist/chunk-OB4XTAVK.cjs +345 -0
- package/dist/chunk-OB4XTAVK.cjs.map +1 -0
- package/dist/chunk-OHFR7WX5.js +341 -0
- package/dist/chunk-OHFR7WX5.js.map +1 -0
- package/dist/chunk-PZGYL7XZ.js +40 -0
- package/dist/chunk-PZGYL7XZ.js.map +1 -0
- package/dist/chunk-Q3DMMQ7K.cjs +164 -0
- package/dist/chunk-Q3DMMQ7K.cjs.map +1 -0
- package/dist/chunk-UZEJV2YD.cjs +139 -0
- package/dist/chunk-UZEJV2YD.cjs.map +1 -0
- package/dist/chunk-V4IQWFYN.js +341 -0
- package/dist/chunk-V4IQWFYN.js.map +1 -0
- package/dist/chunk-VZHQH75L.cjs +26 -0
- package/dist/chunk-VZHQH75L.cjs.map +1 -0
- package/dist/chunk-X6BY6PCK.js +386 -0
- package/dist/chunk-X6BY6PCK.js.map +1 -0
- package/dist/chunk-YG56NRIO.js +131 -0
- package/dist/chunk-YG56NRIO.js.map +1 -0
- package/dist/chunk-ZPDRKCAR.js +21 -0
- package/dist/chunk-ZPDRKCAR.js.map +1 -0
- package/dist/config-C7zV8Zm6.d.cts +125 -0
- package/dist/config-DxjTT8jd.d.ts +125 -0
- package/dist/dynamodb.cjs +14 -0
- package/dist/dynamodb.cjs.map +1 -0
- package/dist/dynamodb.d.cts +93 -0
- package/dist/dynamodb.d.ts +93 -0
- package/dist/dynamodb.js +5 -0
- package/dist/dynamodb.js.map +1 -0
- package/dist/eventbridge.cjs +279 -0
- package/dist/eventbridge.cjs.map +1 -0
- package/dist/eventbridge.d.cts +360 -0
- package/dist/eventbridge.d.ts +360 -0
- package/dist/eventbridge.js +273 -0
- package/dist/eventbridge.js.map +1 -0
- package/dist/index.cjs +251 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +126 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/kinesis.cjs +23 -0
- package/dist/kinesis.cjs.map +1 -0
- package/dist/kinesis.d.cts +360 -0
- package/dist/kinesis.d.ts +360 -0
- package/dist/kinesis.js +6 -0
- package/dist/kinesis.js.map +1 -0
- package/dist/lambda-auto.cjs +19 -0
- package/dist/lambda-auto.cjs.map +1 -0
- package/dist/lambda-auto.d.cts +2 -0
- package/dist/lambda-auto.d.ts +2 -0
- package/dist/lambda-auto.js +17 -0
- package/dist/lambda-auto.js.map +1 -0
- package/dist/lambda.cjs +42 -0
- package/dist/lambda.cjs.map +1 -0
- package/dist/lambda.d.cts +231 -0
- package/dist/lambda.d.ts +231 -0
- package/dist/lambda.js +5 -0
- package/dist/lambda.js.map +1 -0
- package/dist/s3.cjs +14 -0
- package/dist/s3.cjs.map +1 -0
- package/dist/s3.d.cts +77 -0
- package/dist/s3.d.ts +77 -0
- package/dist/s3.js +5 -0
- package/dist/s3.js.map +1 -0
- package/dist/sdk.cjs +31 -0
- package/dist/sdk.cjs.map +1 -0
- package/dist/sdk.d.cts +155 -0
- package/dist/sdk.d.ts +155 -0
- package/dist/sdk.js +6 -0
- package/dist/sdk.js.map +1 -0
- package/dist/sns.cjs +19 -0
- package/dist/sns.cjs.map +1 -0
- package/dist/sns.d.cts +256 -0
- package/dist/sns.d.ts +256 -0
- package/dist/sns.js +6 -0
- package/dist/sns.js.map +1 -0
- package/dist/sqs.cjs +23 -0
- package/dist/sqs.cjs.map +1 -0
- package/dist/sqs.d.cts +384 -0
- package/dist/sqs.d.ts +384 -0
- package/dist/sqs.js +6 -0
- package/dist/sqs.js.map +1 -0
- package/dist/step-functions.cjs +35 -0
- package/dist/step-functions.cjs.map +1 -0
- package/dist/step-functions.d.cts +423 -0
- package/dist/step-functions.d.ts +423 -0
- package/dist/step-functions.js +6 -0
- package/dist/step-functions.js.map +1 -0
- package/dist/testing.cjs +61 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +39 -0
- package/dist/testing.d.ts +39 -0
- package/dist/testing.js +58 -0
- package/dist/testing.js.map +1 -0
- package/dist/types-3_ak5jhy.d.cts +76 -0
- package/dist/types-3_ak5jhy.d.ts +76 -0
- package/dist/types-UiBv_I_M.d.ts +16 -0
- package/dist/types-kTFVdSqO.d.cts +16 -0
- package/dist/xray.cjs +26 -0
- package/dist/xray.cjs.map +1 -0
- package/dist/xray.d.cts +23 -0
- package/dist/xray.d.ts +23 -0
- package/dist/xray.js +5 -0
- package/dist/xray.js.map +1 -0
- package/package.json +184 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkQ3DMMQ7K_cjs = require('./chunk-Q3DMMQ7K.cjs');
|
|
4
|
+
var api = require('@opentelemetry/api');
|
|
5
|
+
var autotel = require('autotel');
|
|
6
|
+
var propagatorAwsXray = require('@opentelemetry/propagator-aws-xray');
|
|
7
|
+
|
|
8
|
+
function extractTraceContext(event) {
|
|
9
|
+
if (event.headers?.traceparent) {
|
|
10
|
+
const carrier = {};
|
|
11
|
+
if (event.headers.traceparent) carrier.traceparent = event.headers.traceparent;
|
|
12
|
+
if (event.headers.tracestate) carrier.tracestate = event.headers.tracestate;
|
|
13
|
+
if (event.headers.baggage) carrier.baggage = event.headers.baggage;
|
|
14
|
+
const extractedContext = api.propagation.extract(api.context.active(), carrier);
|
|
15
|
+
const spanContext = api.trace.getSpanContext(extractedContext);
|
|
16
|
+
return spanContext;
|
|
17
|
+
}
|
|
18
|
+
if (event.Records?.[0]?.messageAttributes?.traceparent) {
|
|
19
|
+
const record = event.Records[0];
|
|
20
|
+
if (!record.messageAttributes) return void 0;
|
|
21
|
+
const carrier = {};
|
|
22
|
+
if (record.messageAttributes.traceparent?.StringValue) {
|
|
23
|
+
carrier.traceparent = record.messageAttributes.traceparent.StringValue;
|
|
24
|
+
}
|
|
25
|
+
if (record.messageAttributes.tracestate?.StringValue) {
|
|
26
|
+
carrier.tracestate = record.messageAttributes.tracestate.StringValue;
|
|
27
|
+
}
|
|
28
|
+
if (record.messageAttributes.baggage?.StringValue) {
|
|
29
|
+
carrier.baggage = record.messageAttributes.baggage.StringValue;
|
|
30
|
+
}
|
|
31
|
+
const extractedContext = api.propagation.extract(api.context.active(), carrier);
|
|
32
|
+
const spanContext = api.trace.getSpanContext(extractedContext);
|
|
33
|
+
return spanContext;
|
|
34
|
+
}
|
|
35
|
+
if (event.Records?.[0]?.Sns?.MessageAttributes?.traceparent) {
|
|
36
|
+
const sns = event.Records[0].Sns;
|
|
37
|
+
if (!sns.MessageAttributes) return void 0;
|
|
38
|
+
const carrier = {};
|
|
39
|
+
if (sns.MessageAttributes.traceparent?.Value) {
|
|
40
|
+
carrier.traceparent = sns.MessageAttributes.traceparent.Value;
|
|
41
|
+
}
|
|
42
|
+
if (sns.MessageAttributes.tracestate?.Value) {
|
|
43
|
+
carrier.tracestate = sns.MessageAttributes.tracestate.Value;
|
|
44
|
+
}
|
|
45
|
+
if (sns.MessageAttributes.baggage?.Value) {
|
|
46
|
+
carrier.baggage = sns.MessageAttributes.baggage.Value;
|
|
47
|
+
}
|
|
48
|
+
const extractedContext = api.propagation.extract(api.context.active(), carrier);
|
|
49
|
+
const spanContext = api.trace.getSpanContext(extractedContext);
|
|
50
|
+
return spanContext;
|
|
51
|
+
}
|
|
52
|
+
if (event.headers?.["x-amzn-trace-id"]) {
|
|
53
|
+
const xrayPropagator = new propagatorAwsXray.AWSXRayPropagator();
|
|
54
|
+
const carrier = {
|
|
55
|
+
"x-amzn-trace-id": event.headers["x-amzn-trace-id"]
|
|
56
|
+
};
|
|
57
|
+
const getter = {
|
|
58
|
+
get(carrier2, key) {
|
|
59
|
+
return carrier2[key];
|
|
60
|
+
},
|
|
61
|
+
keys(carrier2) {
|
|
62
|
+
return Object.keys(carrier2);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const extractedContext = xrayPropagator.extract(api.context.active(), carrier, getter);
|
|
66
|
+
const spanContext = api.trace.getSpanContext(extractedContext);
|
|
67
|
+
return spanContext;
|
|
68
|
+
}
|
|
69
|
+
if (event._autotel_trace_context) {
|
|
70
|
+
return event._autotel_trace_context;
|
|
71
|
+
}
|
|
72
|
+
return void 0;
|
|
73
|
+
}
|
|
74
|
+
function detectTriggerType(event) {
|
|
75
|
+
if (event.headers || event.requestContext || event.httpMethod) {
|
|
76
|
+
return "http";
|
|
77
|
+
}
|
|
78
|
+
if (event.Records?.some((r) => r.messageAttributes || "messageId" in r)) {
|
|
79
|
+
return "pubsub";
|
|
80
|
+
}
|
|
81
|
+
if (event.Records?.some((r) => r.Sns)) {
|
|
82
|
+
return "pubsub";
|
|
83
|
+
}
|
|
84
|
+
if (event.Records?.some((r) => r.kinesis)) {
|
|
85
|
+
return "datasource";
|
|
86
|
+
}
|
|
87
|
+
if (event.source === "aws.events" || event["detail-type"]) {
|
|
88
|
+
return "timer";
|
|
89
|
+
}
|
|
90
|
+
return "other";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/lambda/handler.ts
|
|
94
|
+
var coldStartMap = /* @__PURE__ */ new Map();
|
|
95
|
+
var MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
96
|
+
function createContextWithParent(parentSpanContext) {
|
|
97
|
+
const parentSpan = api.trace.wrapSpanContext(parentSpanContext);
|
|
98
|
+
return api.trace.setSpan(api.context.active(), parentSpan);
|
|
99
|
+
}
|
|
100
|
+
function truncateErrorMessage(message) {
|
|
101
|
+
if (message.length <= MAX_ERROR_MESSAGE_LENGTH) {
|
|
102
|
+
return message;
|
|
103
|
+
}
|
|
104
|
+
return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
|
|
105
|
+
}
|
|
106
|
+
function extractAccountIdFromArn(arn) {
|
|
107
|
+
const arnParts = arn.split(":");
|
|
108
|
+
if (arnParts.length >= 5) {
|
|
109
|
+
return arnParts[4];
|
|
110
|
+
}
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
function wrapHandler(handler, config) {
|
|
114
|
+
return async (event, lambdaContext) => {
|
|
115
|
+
const functionName = lambdaContext.functionName;
|
|
116
|
+
const isColdStart = !coldStartMap.has(functionName);
|
|
117
|
+
if (isColdStart) {
|
|
118
|
+
coldStartMap.set(functionName, true);
|
|
119
|
+
}
|
|
120
|
+
const shouldExtractContext = config?.extractTraceContext !== false;
|
|
121
|
+
const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : void 0;
|
|
122
|
+
const trigger = detectTriggerType(event);
|
|
123
|
+
const executeWithTracing = async () => {
|
|
124
|
+
return autotel.trace(
|
|
125
|
+
`lambda.${functionName}`,
|
|
126
|
+
async (ctx) => {
|
|
127
|
+
ctx.setAttributes(
|
|
128
|
+
chunkQ3DMMQ7K_cjs.buildLambdaAttributes({
|
|
129
|
+
awsRequestId: lambdaContext.awsRequestId,
|
|
130
|
+
functionName,
|
|
131
|
+
functionVersion: lambdaContext.functionVersion,
|
|
132
|
+
coldStart: isColdStart,
|
|
133
|
+
trigger
|
|
134
|
+
})
|
|
135
|
+
);
|
|
136
|
+
const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);
|
|
137
|
+
if (accountId) {
|
|
138
|
+
ctx.setAttribute("cloud.account.id", accountId);
|
|
139
|
+
}
|
|
140
|
+
const region = process.env.AWS_REGION;
|
|
141
|
+
if (region) {
|
|
142
|
+
ctx.setAttribute("cloud.region", region);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const result = await handler(event, lambdaContext);
|
|
146
|
+
if (config?.captureResponse && result != null) {
|
|
147
|
+
try {
|
|
148
|
+
const responseJson = JSON.stringify(result);
|
|
149
|
+
if (responseJson.length <= 4096) {
|
|
150
|
+
ctx.setAttribute("lambda.response", responseJson);
|
|
151
|
+
} else {
|
|
152
|
+
ctx.setAttribute("lambda.response.truncated", true);
|
|
153
|
+
ctx.setAttribute("lambda.response.size", responseJson.length);
|
|
154
|
+
}
|
|
155
|
+
} catch {
|
|
156
|
+
ctx.setAttribute("lambda.response.serialization_failed", true);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
162
|
+
ctx.setStatus({
|
|
163
|
+
code: api.SpanStatusCode.ERROR,
|
|
164
|
+
message: truncateErrorMessage(errorMessage)
|
|
165
|
+
});
|
|
166
|
+
ctx.setAttribute("exception.type", error instanceof Error ? error.constructor.name : "Error");
|
|
167
|
+
ctx.setAttribute("exception.message", truncateErrorMessage(errorMessage));
|
|
168
|
+
if (error instanceof Error && error.stack) {
|
|
169
|
+
ctx.setAttribute("exception.stacktrace", error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH));
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
if (parentSpanContext) {
|
|
177
|
+
const parentContext = createContextWithParent(parentSpanContext);
|
|
178
|
+
return api.context.with(parentContext, executeWithTracing);
|
|
179
|
+
}
|
|
180
|
+
return executeWithTracing();
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function traceLambda(factory, config) {
|
|
184
|
+
return async (event, lambdaContext) => {
|
|
185
|
+
const functionName = lambdaContext.functionName;
|
|
186
|
+
const isColdStart = !coldStartMap.has(functionName);
|
|
187
|
+
if (isColdStart) {
|
|
188
|
+
coldStartMap.set(functionName, true);
|
|
189
|
+
}
|
|
190
|
+
const shouldExtractContext = config?.extractTraceContext !== false;
|
|
191
|
+
const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : void 0;
|
|
192
|
+
const trigger = detectTriggerType(event);
|
|
193
|
+
const executeWithTracing = async () => {
|
|
194
|
+
return autotel.trace(
|
|
195
|
+
`lambda.${functionName}`,
|
|
196
|
+
async (ctx) => {
|
|
197
|
+
ctx.setAttributes(
|
|
198
|
+
chunkQ3DMMQ7K_cjs.buildLambdaAttributes({
|
|
199
|
+
awsRequestId: lambdaContext.awsRequestId,
|
|
200
|
+
functionName,
|
|
201
|
+
functionVersion: lambdaContext.functionVersion,
|
|
202
|
+
coldStart: isColdStart,
|
|
203
|
+
trigger
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);
|
|
207
|
+
if (accountId) {
|
|
208
|
+
ctx.setAttribute("cloud.account.id", accountId);
|
|
209
|
+
}
|
|
210
|
+
const region = process.env.AWS_REGION;
|
|
211
|
+
if (region) {
|
|
212
|
+
ctx.setAttribute("cloud.region", region);
|
|
213
|
+
}
|
|
214
|
+
const handler = factory(ctx);
|
|
215
|
+
return handler(event, lambdaContext);
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
if (parentSpanContext) {
|
|
220
|
+
const parentContext = createContextWithParent(parentSpanContext);
|
|
221
|
+
return api.context.with(parentContext, executeWithTracing);
|
|
222
|
+
}
|
|
223
|
+
return executeWithTracing();
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
var SPAN_SYMBOL = Symbol.for("autotel-aws.span");
|
|
227
|
+
var CONTEXT_SYMBOL = Symbol.for("autotel-aws.context");
|
|
228
|
+
var coldStartMap2 = /* @__PURE__ */ new Map();
|
|
229
|
+
var MAX_ERROR_MESSAGE_LENGTH2 = 500;
|
|
230
|
+
function createContextWithParent2(parentSpanContext) {
|
|
231
|
+
const parentSpan = api.trace.wrapSpanContext(parentSpanContext);
|
|
232
|
+
return api.trace.setSpan(api.context.active(), parentSpan);
|
|
233
|
+
}
|
|
234
|
+
function truncateErrorMessage2(message) {
|
|
235
|
+
if (message.length <= MAX_ERROR_MESSAGE_LENGTH2) {
|
|
236
|
+
return message;
|
|
237
|
+
}
|
|
238
|
+
return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH2)}... (truncated)`;
|
|
239
|
+
}
|
|
240
|
+
function extractAccountIdFromArn2(arn) {
|
|
241
|
+
const arnParts = arn.split(":");
|
|
242
|
+
if (arnParts.length >= 5) {
|
|
243
|
+
return arnParts[4];
|
|
244
|
+
}
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
function tracingMiddleware(config) {
|
|
248
|
+
const tracer = api.trace.getTracer("autotel-aws");
|
|
249
|
+
return {
|
|
250
|
+
before: async (request) => {
|
|
251
|
+
const { event, context: lambdaContext } = request;
|
|
252
|
+
const functionName = lambdaContext.functionName;
|
|
253
|
+
const isColdStart = !coldStartMap2.has(functionName);
|
|
254
|
+
if (isColdStart) {
|
|
255
|
+
coldStartMap2.set(functionName, true);
|
|
256
|
+
}
|
|
257
|
+
const shouldExtractContext = config?.extractTraceContext !== false;
|
|
258
|
+
const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : void 0;
|
|
259
|
+
const trigger = detectTriggerType(event);
|
|
260
|
+
let parentContext = api.context.active();
|
|
261
|
+
if (parentSpanContext) {
|
|
262
|
+
parentContext = createContextWithParent2(parentSpanContext);
|
|
263
|
+
}
|
|
264
|
+
const span = tracer.startSpan(
|
|
265
|
+
`lambda.${functionName}`,
|
|
266
|
+
{
|
|
267
|
+
attributes: chunkQ3DMMQ7K_cjs.buildLambdaAttributes({
|
|
268
|
+
awsRequestId: lambdaContext.awsRequestId,
|
|
269
|
+
functionName,
|
|
270
|
+
functionVersion: lambdaContext.functionVersion,
|
|
271
|
+
coldStart: isColdStart,
|
|
272
|
+
trigger
|
|
273
|
+
})
|
|
274
|
+
},
|
|
275
|
+
parentContext
|
|
276
|
+
);
|
|
277
|
+
const accountId = extractAccountIdFromArn2(lambdaContext.invokedFunctionArn);
|
|
278
|
+
if (accountId) {
|
|
279
|
+
span.setAttribute("cloud.account.id", accountId);
|
|
280
|
+
}
|
|
281
|
+
const region = process.env.AWS_REGION;
|
|
282
|
+
if (region) {
|
|
283
|
+
span.setAttribute("cloud.region", region);
|
|
284
|
+
}
|
|
285
|
+
request[SPAN_SYMBOL] = span;
|
|
286
|
+
request[CONTEXT_SYMBOL] = api.trace.setSpan(parentContext, span);
|
|
287
|
+
return new Promise((resolve) => {
|
|
288
|
+
api.context.with(request[CONTEXT_SYMBOL], () => {
|
|
289
|
+
resolve();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
after: async (request) => {
|
|
294
|
+
const span = request[SPAN_SYMBOL];
|
|
295
|
+
if (!span) return;
|
|
296
|
+
if (config?.captureResponse && request.response != null) {
|
|
297
|
+
try {
|
|
298
|
+
const responseJson = JSON.stringify(request.response);
|
|
299
|
+
if (responseJson.length <= 4096) {
|
|
300
|
+
span.setAttribute("lambda.response", responseJson);
|
|
301
|
+
} else {
|
|
302
|
+
span.setAttribute("lambda.response.truncated", true);
|
|
303
|
+
span.setAttribute("lambda.response.size", responseJson.length);
|
|
304
|
+
}
|
|
305
|
+
} catch {
|
|
306
|
+
span.setAttribute("lambda.response.serialization_failed", true);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
310
|
+
span.end();
|
|
311
|
+
},
|
|
312
|
+
onError: async (request) => {
|
|
313
|
+
const span = request[SPAN_SYMBOL];
|
|
314
|
+
if (!span) return;
|
|
315
|
+
const error = request.error;
|
|
316
|
+
if (error) {
|
|
317
|
+
const errorMessage = error.message || String(error);
|
|
318
|
+
span.setStatus({
|
|
319
|
+
code: api.SpanStatusCode.ERROR,
|
|
320
|
+
message: truncateErrorMessage2(errorMessage)
|
|
321
|
+
});
|
|
322
|
+
span.setAttribute("exception.type", error.name || "Error");
|
|
323
|
+
span.setAttribute("exception.message", truncateErrorMessage2(errorMessage));
|
|
324
|
+
if (error.stack) {
|
|
325
|
+
span.setAttribute("exception.stacktrace", error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH2));
|
|
326
|
+
}
|
|
327
|
+
span.recordException(error);
|
|
328
|
+
}
|
|
329
|
+
span.end();
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
var LambdaMiddleware = tracingMiddleware;
|
|
334
|
+
function getSpanFromRequest(request) {
|
|
335
|
+
return request[SPAN_SYMBOL];
|
|
336
|
+
}
|
|
337
|
+
function getContextFromRequest(request) {
|
|
338
|
+
return request[CONTEXT_SYMBOL];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
exports.LambdaMiddleware = LambdaMiddleware;
|
|
342
|
+
exports.detectTriggerType = detectTriggerType;
|
|
343
|
+
exports.extractTraceContext = extractTraceContext;
|
|
344
|
+
exports.getContextFromRequest = getContextFromRequest;
|
|
345
|
+
exports.getSpanFromRequest = getSpanFromRequest;
|
|
346
|
+
exports.traceLambda = traceLambda;
|
|
347
|
+
exports.tracingMiddleware = tracingMiddleware;
|
|
348
|
+
exports.wrapHandler = wrapHandler;
|
|
349
|
+
//# sourceMappingURL=chunk-D5INYMRP.cjs.map
|
|
350
|
+
//# sourceMappingURL=chunk-D5INYMRP.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lambda/context-extractor.ts","../src/lambda/handler.ts","../src/lambda/middleware.ts"],"names":["propagation","context","trace","AWSXRayPropagator","carrier","otelTrace","autotelTrace","buildLambdaAttributes","SpanStatusCode","coldStartMap","MAX_ERROR_MESSAGE_LENGTH","createContextWithParent","truncateErrorMessage","extractAccountIdFromArn"],"mappings":"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","file":"chunk-D5INYMRP.cjs","sourcesContent":["/**\n * Extract trace context from Lambda events\n */\n\nimport { context, propagation, trace } from '@opentelemetry/api';\nimport type { SpanContext } from '@opentelemetry/api';\nimport type { LambdaEvent } from '../types';\nimport { AWSXRayPropagator } from '@opentelemetry/propagator-aws-xray';\n\n/**\n * Extract trace context from Lambda event\n *\n * Supports:\n * - API Gateway (W3C Trace Context headers)\n * - SQS (message attributes)\n * - SNS (message attributes)\n * - X-Ray header (Lambda integration)\n * - Step Functions (payload context)\n */\nexport function extractTraceContext(event: LambdaEvent): SpanContext | undefined {\n // API Gateway - W3C Trace Context\n if (event.headers?.traceparent) {\n const carrier: Record<string, string> = {};\n if (event.headers.traceparent) carrier.traceparent = event.headers.traceparent;\n if (event.headers.tracestate) carrier.tracestate = event.headers.tracestate;\n if (event.headers.baggage) carrier.baggage = event.headers.baggage;\n\n const extractedContext = propagation.extract(context.active(), carrier);\n const spanContext = trace.getSpanContext(extractedContext);\n return spanContext;\n }\n\n // SQS - message attributes\n if (event.Records?.[0]?.messageAttributes?.traceparent) {\n const record = event.Records[0];\n if (!record.messageAttributes) return undefined;\n \n const carrier: Record<string, string> = {};\n if (record.messageAttributes.traceparent?.StringValue) {\n carrier.traceparent = record.messageAttributes.traceparent.StringValue;\n }\n if (record.messageAttributes.tracestate?.StringValue) {\n carrier.tracestate = record.messageAttributes.tracestate.StringValue;\n }\n if (record.messageAttributes.baggage?.StringValue) {\n carrier.baggage = record.messageAttributes.baggage.StringValue;\n }\n\n const extractedContext = propagation.extract(context.active(), carrier);\n const spanContext = trace.getSpanContext(extractedContext);\n return spanContext;\n }\n\n // SNS - message attributes\n if (event.Records?.[0]?.Sns?.MessageAttributes?.traceparent) {\n const sns = event.Records[0].Sns;\n if (!sns.MessageAttributes) return undefined;\n \n const carrier: Record<string, string> = {};\n if (sns.MessageAttributes.traceparent?.Value) {\n carrier.traceparent = sns.MessageAttributes.traceparent.Value;\n }\n if (sns.MessageAttributes.tracestate?.Value) {\n carrier.tracestate = sns.MessageAttributes.tracestate.Value;\n }\n if (sns.MessageAttributes.baggage?.Value) {\n carrier.baggage = sns.MessageAttributes.baggage.Value;\n }\n\n const extractedContext = propagation.extract(context.active(), carrier);\n const spanContext = trace.getSpanContext(extractedContext);\n return spanContext;\n }\n\n // X-Ray header (Lambda integration)\n if (event.headers?.['x-amzn-trace-id']) {\n const xrayPropagator = new AWSXRayPropagator();\n const carrier: Record<string, string> = {\n 'x-amzn-trace-id': event.headers['x-amzn-trace-id'],\n };\n\n // AWSXRayPropagator.extract() requires a getter function\n // Use a simple getter for Record<string, string>\n const getter = {\n get(carrier: Record<string, string>, key: string): string | string[] | undefined {\n return carrier[key];\n },\n keys(carrier: Record<string, string>): string[] {\n return Object.keys(carrier);\n },\n };\n\n const extractedContext = xrayPropagator.extract(context.active(), carrier, getter);\n const spanContext = trace.getSpanContext(extractedContext);\n return spanContext;\n }\n\n // Step Functions - payload context\n if (event._autotel_trace_context) {\n return event._autotel_trace_context as SpanContext;\n }\n\n return undefined;\n}\n\n/**\n * Detect Lambda trigger type from event\n */\nexport function detectTriggerType(event: LambdaEvent): 'http' | 'pubsub' | 'datasource' | 'timer' | 'other' {\n // API Gateway / ALB\n if (event.headers || event.requestContext || event.httpMethod) {\n return 'http';\n }\n\n // SQS\n if (event.Records?.some((r) => r.messageAttributes || 'messageId' in r)) {\n return 'pubsub';\n }\n\n // SNS\n if (event.Records?.some((r) => r.Sns)) {\n return 'pubsub';\n }\n\n // Kinesis\n if (event.Records?.some((r) => r.kinesis)) {\n return 'datasource';\n }\n\n // EventBridge / Scheduled\n if (event.source === 'aws.events' || event['detail-type']) {\n return 'timer';\n }\n\n return 'other';\n}\n","/**\n * Lambda handler wrappers\n *\n * Provides instrumentation wrappers for AWS Lambda handlers with automatic\n * trace context extraction from various event sources (API Gateway, SQS, SNS, etc.).\n *\n * @example Simple wrapper\n * ```typescript\n * import { wrapHandler } from 'autotel-aws/lambda';\n *\n * export const handler = wrapHandler(async (event, context) => {\n * return { statusCode: 200 };\n * });\n * ```\n *\n * @example With context access\n * ```typescript\n * import { traceLambda } from 'autotel-aws/lambda';\n *\n * export const handler = traceLambda(ctx => async (event, context) => {\n * ctx.setAttribute('user.id', event.userId);\n * return { statusCode: 200 };\n * });\n * ```\n */\n\nimport { context, trace as otelTrace, SpanStatusCode } from '@opentelemetry/api';\nimport type { SpanContext, Context } from '@opentelemetry/api';\nimport { trace as autotelTrace, type TraceContext } from 'autotel';\nimport type { LambdaHandler } from './types';\nimport type { LambdaEvent, LambdaContext } from '../types';\nimport { extractTraceContext, detectTriggerType } from './context-extractor';\nimport { buildLambdaAttributes } from '../attributes';\nimport type { LambdaInstrumentationConfig } from '../config';\n\n// Track cold starts per function instance\n// Using WeakMap-like pattern to avoid memory leaks in long-running containers\nconst coldStartMap = new Map<string, boolean>();\n\n/**\n * Maximum error message length to prevent span attribute bloat\n */\nconst MAX_ERROR_MESSAGE_LENGTH = 500;\n\n/**\n * Create an OpenTelemetry context with the given span context as parent\n *\n * This properly sets up the parent-child relationship for distributed tracing\n * by creating a context that contains the extracted span context.\n */\nfunction createContextWithParent(parentSpanContext: SpanContext): Context {\n // Create a non-recording span that carries the parent context\n // This is the standard OTel pattern for context propagation\n const parentSpan = otelTrace.wrapSpanContext(parentSpanContext);\n return otelTrace.setSpan(context.active(), parentSpan);\n}\n\n/**\n * Truncate error message to prevent span bloat\n */\nfunction truncateErrorMessage(message: string): string {\n if (message.length <= MAX_ERROR_MESSAGE_LENGTH) {\n return message;\n }\n return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;\n}\n\n/**\n * Extract AWS account ID from Lambda ARN\n */\nfunction extractAccountIdFromArn(arn: string): string | undefined {\n // ARN format: arn:aws:lambda:region:account-id:function:name\n const arnParts = arn.split(':');\n if (arnParts.length >= 5) {\n return arnParts[4];\n }\n return undefined;\n}\n\n/**\n * Wrap Lambda handler with OpenTelemetry instrumentation\n *\n * Automatically extracts trace context from incoming events and creates\n * a root span for the Lambda invocation with proper semantic attributes.\n *\n * @param handler - The Lambda handler function to wrap\n * @param config - Optional instrumentation configuration\n * @returns Wrapped handler with automatic tracing\n *\n * @example Basic usage\n * ```typescript\n * export const handler = wrapHandler(async (event, context) => {\n * // Your handler code - automatically traced\n * return { statusCode: 200 };\n * });\n * ```\n *\n * @example With configuration\n * ```typescript\n * export const handler = wrapHandler(\n * async (event, context) => {\n * return { statusCode: 200, body: JSON.stringify({ result: 'ok' }) };\n * },\n * { captureResponse: true, extractTraceContext: true }\n * );\n * ```\n *\n * @remarks\n * Semantic attributes set automatically:\n * - `faas.name` - Function name\n * - `faas.version` - Function version\n * - `faas.invocation_id` - AWS request ID\n * - `faas.coldstart` - Whether this is a cold start\n * - `faas.trigger` - Trigger type (http, pubsub, datasource, timer, other)\n * - `cloud.provider` - 'aws'\n * - `cloud.region` - AWS region\n * - `cloud.account.id` - AWS account ID (extracted from ARN)\n */\nexport function wrapHandler<TEvent = LambdaEvent, TResult = unknown>(\n handler: LambdaHandler<TEvent, TResult>,\n config?: LambdaInstrumentationConfig,\n): LambdaHandler<TEvent, TResult> {\n // Return the wrapped handler\n return async (event: TEvent, lambdaContext: LambdaContext): Promise<TResult> => {\n const functionName = lambdaContext.functionName;\n\n // Detect cold start (first invocation for this function instance)\n const isColdStart = !coldStartMap.has(functionName);\n if (isColdStart) {\n coldStartMap.set(functionName, true);\n }\n\n // Extract parent trace context from event (if enabled, default: true)\n const shouldExtractContext = config?.extractTraceContext !== false;\n const parentSpanContext = shouldExtractContext\n ? extractTraceContext(event as LambdaEvent)\n : undefined;\n\n // Detect trigger type for semantic attributes\n const trigger = detectTriggerType(event as LambdaEvent);\n\n // Core tracing logic\n const executeWithTracing = async (): Promise<TResult> => {\n return autotelTrace(\n `lambda.${functionName}`,\n async (ctx: TraceContext): Promise<TResult> => {\n // Set Lambda semantic attributes\n ctx.setAttributes(\n buildLambdaAttributes({\n awsRequestId: lambdaContext.awsRequestId,\n functionName,\n functionVersion: lambdaContext.functionVersion,\n coldStart: isColdStart,\n trigger,\n }),\n );\n\n // Extract and set account ID from ARN\n const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);\n if (accountId) {\n ctx.setAttribute('cloud.account.id', accountId);\n }\n\n // Set region from environment\n const region = process.env.AWS_REGION;\n if (region) {\n ctx.setAttribute('cloud.region', region);\n }\n\n try {\n const result = await handler(event, lambdaContext);\n\n // Capture response if configured (be careful with large payloads)\n if (config?.captureResponse && result != null) {\n try {\n const responseJson = JSON.stringify(result);\n // Only capture if not too large\n if (responseJson.length <= 4096) {\n ctx.setAttribute('lambda.response', responseJson);\n } else {\n ctx.setAttribute('lambda.response.truncated', true);\n ctx.setAttribute('lambda.response.size', responseJson.length);\n }\n } catch {\n // Ignore serialization errors (circular references, etc.)\n ctx.setAttribute('lambda.response.serialization_failed', true);\n }\n }\n\n return result;\n } catch (error) {\n // Record error details\n const errorMessage = error instanceof Error ? error.message : String(error);\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: truncateErrorMessage(errorMessage),\n });\n\n // Add exception attributes\n ctx.setAttribute('exception.type', error instanceof Error ? error.constructor.name : 'Error');\n ctx.setAttribute('exception.message', truncateErrorMessage(errorMessage));\n\n if (error instanceof Error && error.stack) {\n ctx.setAttribute('exception.stacktrace', error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH));\n }\n\n throw error;\n }\n },\n );\n };\n\n // Execute with proper parent context if available\n if (parentSpanContext) {\n const parentContext = createContextWithParent(parentSpanContext);\n return context.with(parentContext, executeWithTracing);\n }\n\n return executeWithTracing();\n };\n}\n\n/**\n * Functional API for Lambda with trace context access\n *\n * Similar to `wrapHandler`, but provides access to the trace context\n * for setting custom attributes during handler execution.\n *\n * @param factory - Factory function that receives trace context and returns a handler\n * @param config - Optional instrumentation configuration\n * @returns Wrapped handler with automatic tracing\n *\n * @example\n * ```typescript\n * export const handler = traceLambda(ctx => async (event, context) => {\n * // Access trace context for custom attributes\n * ctx.setAttribute('user.id', event.userId);\n * ctx.setAttribute('order.id', event.orderId);\n *\n * // Use X-Ray annotations for indexed attributes\n * setXRayAnnotation('user.tier', event.userTier);\n *\n * const result = await processOrder(event);\n * ctx.setAttribute('order.status', result.status);\n *\n * return { statusCode: 200, body: JSON.stringify(result) };\n * });\n * ```\n *\n * @remarks\n * The trace context (`ctx`) provides:\n * - `setAttribute(key, value)` - Set a single attribute\n * - `setAttributes(attrs)` - Set multiple attributes\n * - `setStatus(status)` - Set span status\n * - `recordException(error)` - Record an exception\n * - `traceId`, `spanId` - Trace identifiers\n */\nexport function traceLambda<TEvent = LambdaEvent, TResult = unknown>(\n factory: (ctx: TraceContext) => LambdaHandler<TEvent, TResult>,\n config?: LambdaInstrumentationConfig,\n): LambdaHandler<TEvent, TResult> {\n return async (event: TEvent, lambdaContext: LambdaContext): Promise<TResult> => {\n const functionName = lambdaContext.functionName;\n\n // Detect cold start\n const isColdStart = !coldStartMap.has(functionName);\n if (isColdStart) {\n coldStartMap.set(functionName, true);\n }\n\n // Extract parent trace context\n const shouldExtractContext = config?.extractTraceContext !== false;\n const parentSpanContext = shouldExtractContext\n ? extractTraceContext(event as LambdaEvent)\n : undefined;\n\n // Detect trigger type\n const trigger = detectTriggerType(event as LambdaEvent);\n\n // Core tracing logic\n const executeWithTracing = async (): Promise<TResult> => {\n return autotelTrace(\n `lambda.${functionName}`,\n async (ctx: TraceContext): Promise<TResult> => {\n // Set Lambda semantic attributes\n ctx.setAttributes(\n buildLambdaAttributes({\n awsRequestId: lambdaContext.awsRequestId,\n functionName,\n functionVersion: lambdaContext.functionVersion,\n coldStart: isColdStart,\n trigger,\n }),\n );\n\n // Extract and set account ID from ARN\n const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);\n if (accountId) {\n ctx.setAttribute('cloud.account.id', accountId);\n }\n\n // Set region from environment\n const region = process.env.AWS_REGION;\n if (region) {\n ctx.setAttribute('cloud.region', region);\n }\n\n // Create handler with context access and execute\n const handler = factory(ctx);\n return handler(event, lambdaContext);\n },\n );\n };\n\n // Execute with proper parent context if available\n if (parentSpanContext) {\n const parentContext = createContextWithParent(parentSpanContext);\n return context.with(parentContext, executeWithTracing);\n }\n\n return executeWithTracing();\n };\n}\n","/**\n * Middy-compatible Lambda middleware for OpenTelemetry instrumentation\n *\n * Provides full span lifecycle management for Lambda handlers using Middy.\n *\n * @example Basic usage\n * ```typescript\n * import middy from '@middy/core';\n * import { tracingMiddleware } from 'autotel-aws/lambda';\n *\n * const baseHandler = async (event, context) => {\n * return { statusCode: 200 };\n * };\n *\n * export const handler = middy(baseHandler)\n * .use(tracingMiddleware());\n * ```\n *\n * @example With configuration\n * ```typescript\n * export const handler = middy(baseHandler)\n * .use(tracingMiddleware({\n * captureResponse: true,\n * extractTraceContext: true\n * }));\n * ```\n *\n * @example Combined with other middleware\n * ```typescript\n * export const handler = middy(baseHandler)\n * .use(tracingMiddleware())\n * .use(jsonBodyParser())\n * .use(httpErrorHandler());\n * ```\n */\n\nimport type { MiddlewareObj, Request } from '@middy/core';\nimport type { Context as AWSLambdaContext } from 'aws-lambda';\nimport { context, trace as otelTrace, SpanStatusCode } from '@opentelemetry/api';\nimport type { Span, SpanContext, Context as OtelContext } from '@opentelemetry/api';\nimport type { LambdaEvent } from '../types';\nimport type { LambdaInstrumentationConfig } from '../config';\nimport { extractTraceContext, detectTriggerType } from './context-extractor';\nimport { buildLambdaAttributes } from '../attributes';\n\n// Symbol to store span on request object\nconst SPAN_SYMBOL = Symbol.for('autotel-aws.span');\nconst CONTEXT_SYMBOL = Symbol.for('autotel-aws.context');\n\n// Track cold starts per function instance\nconst coldStartMap = new Map<string, boolean>();\n\n/**\n * Maximum error message length to prevent span attribute bloat\n */\nconst MAX_ERROR_MESSAGE_LENGTH = 500;\n\n/**\n * Create an OpenTelemetry context with the given span context as parent\n */\nfunction createContextWithParent(parentSpanContext: SpanContext): OtelContext {\n const parentSpan = otelTrace.wrapSpanContext(parentSpanContext);\n return otelTrace.setSpan(context.active(), parentSpan);\n}\n\n/**\n * Truncate error message to prevent span bloat\n */\nfunction truncateErrorMessage(message: string): string {\n if (message.length <= MAX_ERROR_MESSAGE_LENGTH) {\n return message;\n }\n return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;\n}\n\n/**\n * Extract AWS account ID from Lambda ARN\n */\nfunction extractAccountIdFromArn(arn: string): string | undefined {\n const arnParts = arn.split(':');\n if (arnParts.length >= 5) {\n return arnParts[4];\n }\n return undefined;\n}\n\n// Extended request type with our symbols\ninterface TracingRequest<TEvent = LambdaEvent, TResult = unknown>\n extends Request<TEvent, TResult, Error, AWSLambdaContext> {\n [SPAN_SYMBOL]?: Span;\n [CONTEXT_SYMBOL]?: OtelContext;\n}\n\n/**\n * Middy middleware for Lambda instrumentation with full span lifecycle\n *\n * Creates a span that wraps the entire handler execution, including:\n * - Trace context extraction from incoming events\n * - Cold start detection\n * - Semantic attributes for Lambda (faas.*, cloud.*)\n * - Error recording and status\n * - Response capture (optional)\n *\n * @param config - Optional instrumentation configuration\n * @returns Middy middleware object\n *\n * @remarks\n * This middleware uses Middy's before/after/onError hooks to manage\n * the span lifecycle. The span is created in `before`, ended in `after`\n * or `onError`.\n *\n * Semantic attributes set automatically:\n * - `faas.name` - Function name\n * - `faas.version` - Function version\n * - `faas.invocation_id` - AWS request ID\n * - `faas.coldstart` - Whether this is a cold start\n * - `faas.trigger` - Trigger type (http, pubsub, datasource, timer, other)\n * - `cloud.provider` - 'aws'\n * - `cloud.region` - AWS region\n * - `cloud.account.id` - AWS account ID (extracted from ARN)\n */\nexport function tracingMiddleware(\n config?: LambdaInstrumentationConfig,\n): MiddlewareObj<LambdaEvent, unknown, Error, AWSLambdaContext> {\n const tracer = otelTrace.getTracer('autotel-aws');\n\n return {\n before: async (request: TracingRequest) => {\n const { event, context: lambdaContext } = request;\n const functionName = lambdaContext.functionName;\n\n // Detect cold start\n const isColdStart = !coldStartMap.has(functionName);\n if (isColdStart) {\n coldStartMap.set(functionName, true);\n }\n\n // Extract parent trace context from event\n const shouldExtractContext = config?.extractTraceContext !== false;\n const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : undefined;\n\n // Detect trigger type\n const trigger = detectTriggerType(event);\n\n // Create parent context if available\n let parentContext = context.active();\n if (parentSpanContext) {\n parentContext = createContextWithParent(parentSpanContext);\n }\n\n // Start span with parent context\n const span = tracer.startSpan(\n `lambda.${functionName}`,\n {\n attributes: buildLambdaAttributes({\n awsRequestId: lambdaContext.awsRequestId,\n functionName,\n functionVersion: lambdaContext.functionVersion,\n coldStart: isColdStart,\n trigger,\n }),\n },\n parentContext,\n );\n\n // Extract and set account ID from ARN\n const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);\n if (accountId) {\n span.setAttribute('cloud.account.id', accountId);\n }\n\n // Set region from environment\n const region = process.env.AWS_REGION;\n if (region) {\n span.setAttribute('cloud.region', region);\n }\n\n // Store span and context on request for later use\n request[SPAN_SYMBOL] = span;\n request[CONTEXT_SYMBOL] = otelTrace.setSpan(parentContext, span);\n\n // Set the context as active for the handler execution\n // This ensures child spans created during handler execution are linked\n return new Promise<void>((resolve) => {\n context.with(request[CONTEXT_SYMBOL]!, () => {\n resolve();\n });\n });\n },\n\n after: async (request: TracingRequest) => {\n const span = request[SPAN_SYMBOL];\n if (!span) return;\n\n // Capture response if configured\n if (config?.captureResponse && request.response != null) {\n try {\n const responseJson = JSON.stringify(request.response);\n if (responseJson.length <= 4096) {\n span.setAttribute('lambda.response', responseJson);\n } else {\n span.setAttribute('lambda.response.truncated', true);\n span.setAttribute('lambda.response.size', responseJson.length);\n }\n } catch {\n span.setAttribute('lambda.response.serialization_failed', true);\n }\n }\n\n // Set success status\n span.setStatus({ code: SpanStatusCode.OK });\n\n // End the span\n span.end();\n },\n\n onError: async (request: TracingRequest) => {\n const span = request[SPAN_SYMBOL];\n if (!span) return;\n\n const error = request.error;\n if (error) {\n // Record error details\n const errorMessage = error.message || String(error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: truncateErrorMessage(errorMessage),\n });\n\n // Add exception attributes\n span.setAttribute('exception.type', error.name || 'Error');\n span.setAttribute('exception.message', truncateErrorMessage(errorMessage));\n\n if (error.stack) {\n span.setAttribute('exception.stacktrace', error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH));\n }\n\n // Record exception event\n span.recordException(error);\n }\n\n // End the span\n span.end();\n },\n };\n}\n\n/**\n * @deprecated Use tracingMiddleware instead. LambdaMiddleware is an alias for backwards compatibility.\n */\nexport const LambdaMiddleware = tracingMiddleware;\n\n/**\n * Get the current span from a Middy request object\n *\n * Useful for setting custom attributes within your handler when using\n * the tracing middleware.\n *\n * @param request - Middy request object\n * @returns The active span, or undefined if not available\n *\n * @example\n * ```typescript\n * const baseHandler = async (event, context) => {\n * const span = getSpanFromRequest(request);\n * if (span) {\n * span.setAttribute('user.id', event.userId);\n * }\n * return { statusCode: 200 };\n * };\n * ```\n */\nexport function getSpanFromRequest(request: Request<any, any, any, any>): Span | undefined {\n return (request as TracingRequest)[SPAN_SYMBOL];\n}\n\n/**\n * Get the OpenTelemetry context from a Middy request object\n *\n * @param request - Middy request object\n * @returns The active context, or undefined if not available\n */\nexport function getContextFromRequest(request: Request<any, any, any, any>): OtelContext | undefined {\n return (request as TracingRequest)[CONTEXT_SYMBOL];\n}\n"]}
|