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.
Files changed (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +540 -0
  3. package/dist/attributes.cjs +49 -0
  4. package/dist/attributes.cjs.map +1 -0
  5. package/dist/attributes.d.cts +117 -0
  6. package/dist/attributes.d.ts +117 -0
  7. package/dist/attributes.js +4 -0
  8. package/dist/attributes.js.map +1 -0
  9. package/dist/chunk-35F3UBOO.cjs +48 -0
  10. package/dist/chunk-35F3UBOO.cjs.map +1 -0
  11. package/dist/chunk-4TGVGEUN.cjs +84 -0
  12. package/dist/chunk-4TGVGEUN.cjs.map +1 -0
  13. package/dist/chunk-CIGXV6HA.js +192 -0
  14. package/dist/chunk-CIGXV6HA.js.map +1 -0
  15. package/dist/chunk-D5INYMRP.cjs +350 -0
  16. package/dist/chunk-D5INYMRP.cjs.map +1 -0
  17. package/dist/chunk-DF5PT3JK.js +387 -0
  18. package/dist/chunk-DF5PT3JK.js.map +1 -0
  19. package/dist/chunk-DGUM43GV.js +10 -0
  20. package/dist/chunk-DGUM43GV.js.map +1 -0
  21. package/dist/chunk-DHHLKZHI.cjs +23 -0
  22. package/dist/chunk-DHHLKZHI.cjs.map +1 -0
  23. package/dist/chunk-FKZOELBT.js +78 -0
  24. package/dist/chunk-FKZOELBT.js.map +1 -0
  25. package/dist/chunk-HMTKKKKP.cjs +390 -0
  26. package/dist/chunk-HMTKKKKP.cjs.map +1 -0
  27. package/dist/chunk-I4CKQ4RD.js +153 -0
  28. package/dist/chunk-I4CKQ4RD.js.map +1 -0
  29. package/dist/chunk-JEQ2X3Z6.cjs +12 -0
  30. package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
  31. package/dist/chunk-JMSFE6FJ.js +24 -0
  32. package/dist/chunk-JMSFE6FJ.js.map +1 -0
  33. package/dist/chunk-KUIOI74B.cjs +394 -0
  34. package/dist/chunk-KUIOI74B.cjs.map +1 -0
  35. package/dist/chunk-NQ65Y5AI.cjs +195 -0
  36. package/dist/chunk-NQ65Y5AI.cjs.map +1 -0
  37. package/dist/chunk-OB4XTAVK.cjs +345 -0
  38. package/dist/chunk-OB4XTAVK.cjs.map +1 -0
  39. package/dist/chunk-OHFR7WX5.js +341 -0
  40. package/dist/chunk-OHFR7WX5.js.map +1 -0
  41. package/dist/chunk-PZGYL7XZ.js +40 -0
  42. package/dist/chunk-PZGYL7XZ.js.map +1 -0
  43. package/dist/chunk-Q3DMMQ7K.cjs +164 -0
  44. package/dist/chunk-Q3DMMQ7K.cjs.map +1 -0
  45. package/dist/chunk-UZEJV2YD.cjs +139 -0
  46. package/dist/chunk-UZEJV2YD.cjs.map +1 -0
  47. package/dist/chunk-V4IQWFYN.js +341 -0
  48. package/dist/chunk-V4IQWFYN.js.map +1 -0
  49. package/dist/chunk-VZHQH75L.cjs +26 -0
  50. package/dist/chunk-VZHQH75L.cjs.map +1 -0
  51. package/dist/chunk-X6BY6PCK.js +386 -0
  52. package/dist/chunk-X6BY6PCK.js.map +1 -0
  53. package/dist/chunk-YG56NRIO.js +131 -0
  54. package/dist/chunk-YG56NRIO.js.map +1 -0
  55. package/dist/chunk-ZPDRKCAR.js +21 -0
  56. package/dist/chunk-ZPDRKCAR.js.map +1 -0
  57. package/dist/config-C7zV8Zm6.d.cts +125 -0
  58. package/dist/config-DxjTT8jd.d.ts +125 -0
  59. package/dist/dynamodb.cjs +14 -0
  60. package/dist/dynamodb.cjs.map +1 -0
  61. package/dist/dynamodb.d.cts +93 -0
  62. package/dist/dynamodb.d.ts +93 -0
  63. package/dist/dynamodb.js +5 -0
  64. package/dist/dynamodb.js.map +1 -0
  65. package/dist/eventbridge.cjs +279 -0
  66. package/dist/eventbridge.cjs.map +1 -0
  67. package/dist/eventbridge.d.cts +360 -0
  68. package/dist/eventbridge.d.ts +360 -0
  69. package/dist/eventbridge.js +273 -0
  70. package/dist/eventbridge.js.map +1 -0
  71. package/dist/index.cjs +251 -0
  72. package/dist/index.cjs.map +1 -0
  73. package/dist/index.d.cts +126 -0
  74. package/dist/index.d.ts +126 -0
  75. package/dist/index.js +48 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/kinesis.cjs +23 -0
  78. package/dist/kinesis.cjs.map +1 -0
  79. package/dist/kinesis.d.cts +360 -0
  80. package/dist/kinesis.d.ts +360 -0
  81. package/dist/kinesis.js +6 -0
  82. package/dist/kinesis.js.map +1 -0
  83. package/dist/lambda-auto.cjs +19 -0
  84. package/dist/lambda-auto.cjs.map +1 -0
  85. package/dist/lambda-auto.d.cts +2 -0
  86. package/dist/lambda-auto.d.ts +2 -0
  87. package/dist/lambda-auto.js +17 -0
  88. package/dist/lambda-auto.js.map +1 -0
  89. package/dist/lambda.cjs +42 -0
  90. package/dist/lambda.cjs.map +1 -0
  91. package/dist/lambda.d.cts +231 -0
  92. package/dist/lambda.d.ts +231 -0
  93. package/dist/lambda.js +5 -0
  94. package/dist/lambda.js.map +1 -0
  95. package/dist/s3.cjs +14 -0
  96. package/dist/s3.cjs.map +1 -0
  97. package/dist/s3.d.cts +77 -0
  98. package/dist/s3.d.ts +77 -0
  99. package/dist/s3.js +5 -0
  100. package/dist/s3.js.map +1 -0
  101. package/dist/sdk.cjs +31 -0
  102. package/dist/sdk.cjs.map +1 -0
  103. package/dist/sdk.d.cts +155 -0
  104. package/dist/sdk.d.ts +155 -0
  105. package/dist/sdk.js +6 -0
  106. package/dist/sdk.js.map +1 -0
  107. package/dist/sns.cjs +19 -0
  108. package/dist/sns.cjs.map +1 -0
  109. package/dist/sns.d.cts +256 -0
  110. package/dist/sns.d.ts +256 -0
  111. package/dist/sns.js +6 -0
  112. package/dist/sns.js.map +1 -0
  113. package/dist/sqs.cjs +23 -0
  114. package/dist/sqs.cjs.map +1 -0
  115. package/dist/sqs.d.cts +384 -0
  116. package/dist/sqs.d.ts +384 -0
  117. package/dist/sqs.js +6 -0
  118. package/dist/sqs.js.map +1 -0
  119. package/dist/step-functions.cjs +35 -0
  120. package/dist/step-functions.cjs.map +1 -0
  121. package/dist/step-functions.d.cts +423 -0
  122. package/dist/step-functions.d.ts +423 -0
  123. package/dist/step-functions.js +6 -0
  124. package/dist/step-functions.js.map +1 -0
  125. package/dist/testing.cjs +61 -0
  126. package/dist/testing.cjs.map +1 -0
  127. package/dist/testing.d.cts +39 -0
  128. package/dist/testing.d.ts +39 -0
  129. package/dist/testing.js +58 -0
  130. package/dist/testing.js.map +1 -0
  131. package/dist/types-3_ak5jhy.d.cts +76 -0
  132. package/dist/types-3_ak5jhy.d.ts +76 -0
  133. package/dist/types-UiBv_I_M.d.ts +16 -0
  134. package/dist/types-kTFVdSqO.d.cts +16 -0
  135. package/dist/xray.cjs +26 -0
  136. package/dist/xray.cjs.map +1 -0
  137. package/dist/xray.d.cts +23 -0
  138. package/dist/xray.d.ts +23 -0
  139. package/dist/xray.js +5 -0
  140. package/dist/xray.js.map +1 -0
  141. package/package.json +184 -0
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ var chunkQ3DMMQ7K_cjs = require('./chunk-Q3DMMQ7K.cjs');
4
+ var autotel = require('autotel');
5
+ var api = require('@opentelemetry/api');
6
+
7
+ // src/common/error-handlers.ts
8
+ function classifyAWSError(error) {
9
+ if (!error || typeof error !== "object") {
10
+ return { isError: false };
11
+ }
12
+ const awsError = error;
13
+ const statusCode = awsError.$metadata?.httpStatusCode || awsError.StatusCode;
14
+ const isError = statusCode !== void 0 && statusCode >= 400;
15
+ return {
16
+ isError,
17
+ statusCode,
18
+ errorCode: awsError.Code || awsError.name
19
+ };
20
+ }
21
+ function extractErrorAttributes(error) {
22
+ if (!error || typeof error !== "object") {
23
+ return {};
24
+ }
25
+ const awsError = error;
26
+ const attrs = {};
27
+ if (awsError.name) {
28
+ attrs["error.type"] = awsError.name;
29
+ }
30
+ if (awsError.message) {
31
+ attrs["error.message"] = awsError.message;
32
+ }
33
+ if (awsError.Code) {
34
+ attrs["aws.error.code"] = awsError.Code;
35
+ }
36
+ if (awsError.$metadata?.requestId) {
37
+ attrs["aws.request_id"] = awsError.$metadata.requestId;
38
+ }
39
+ if (awsError.$metadata?.httpStatusCode) {
40
+ attrs["http.status_code"] = awsError.$metadata.httpStatusCode;
41
+ }
42
+ return attrs;
43
+ }
44
+
45
+ // src/common/request-builder.ts
46
+ function extractRequestMetadata(command, context) {
47
+ return {
48
+ clientName: context.clientName,
49
+ commandName: command.constructor.name
50
+ };
51
+ }
52
+ function extractServiceName(clientName) {
53
+ return clientName.replace(/Client$/, "");
54
+ }
55
+ function extractOperationName(commandName) {
56
+ return commandName.replace(/Command$/, "");
57
+ }
58
+
59
+ // src/common/response-builder.ts
60
+ function extractResponseMetadata(response) {
61
+ const metadata = response.$metadata || {};
62
+ return {
63
+ requestId: metadata.requestId,
64
+ httpStatusCode: metadata.httpStatusCode,
65
+ extendedRequestId: metadata.extendedRequestId,
66
+ cfId: metadata.cfId
67
+ };
68
+ }
69
+ function wrapSDKClient(client, serviceName) {
70
+ const clientName = client.constructor.name;
71
+ const resolvedServiceName = serviceName || extractServiceName(clientName);
72
+ return new Proxy(client, {
73
+ get(target, prop) {
74
+ if (prop === "send") {
75
+ return async function tracedSend(command) {
76
+ const metadata = extractRequestMetadata(command, { clientName });
77
+ const operationName = extractOperationName(metadata.commandName);
78
+ return autotel.trace(`aws.${resolvedServiceName}.${operationName}`, async (ctx) => {
79
+ ctx.setAttributes(
80
+ chunkQ3DMMQ7K_cjs.buildSDKAttributes({
81
+ service: resolvedServiceName,
82
+ operation: operationName
83
+ })
84
+ );
85
+ try {
86
+ const response = await target.send(command);
87
+ const responseMetadata = extractResponseMetadata(response);
88
+ if (responseMetadata.requestId) {
89
+ ctx.setAttribute("aws.request_id", responseMetadata.requestId);
90
+ }
91
+ if (responseMetadata.httpStatusCode) {
92
+ ctx.setAttribute("http.status_code", responseMetadata.httpStatusCode);
93
+ }
94
+ if (responseMetadata.extendedRequestId) {
95
+ ctx.setAttribute("aws.extended_request_id", responseMetadata.extendedRequestId);
96
+ }
97
+ if (responseMetadata.cfId) {
98
+ ctx.setAttribute("aws.cf_id", responseMetadata.cfId);
99
+ }
100
+ if (responseMetadata.httpStatusCode) {
101
+ if (responseMetadata.httpStatusCode >= 400) {
102
+ ctx.setStatus({
103
+ code: api.SpanStatusCode.ERROR,
104
+ message: `HTTP ${responseMetadata.httpStatusCode}`
105
+ });
106
+ } else {
107
+ ctx.setStatus({ code: api.SpanStatusCode.OK });
108
+ }
109
+ }
110
+ return response;
111
+ } catch (error) {
112
+ const errorInfo = classifyAWSError(error);
113
+ const errorAttrs = extractErrorAttributes(error);
114
+ ctx.setAttributes(errorAttrs);
115
+ if (errorInfo.isError) {
116
+ ctx.setStatus({
117
+ code: api.SpanStatusCode.ERROR,
118
+ message: errorInfo.errorCode || "AWS Error"
119
+ });
120
+ }
121
+ throw error;
122
+ }
123
+ });
124
+ };
125
+ }
126
+ return target[prop];
127
+ }
128
+ });
129
+ }
130
+
131
+ exports.classifyAWSError = classifyAWSError;
132
+ exports.extractErrorAttributes = extractErrorAttributes;
133
+ exports.extractOperationName = extractOperationName;
134
+ exports.extractRequestMetadata = extractRequestMetadata;
135
+ exports.extractResponseMetadata = extractResponseMetadata;
136
+ exports.extractServiceName = extractServiceName;
137
+ exports.wrapSDKClient = wrapSDKClient;
138
+ //# sourceMappingURL=chunk-UZEJV2YD.cjs.map
139
+ //# sourceMappingURL=chunk-UZEJV2YD.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/common/error-handlers.ts","../src/common/request-builder.ts","../src/common/response-builder.ts","../src/common/sdk-wrapper.ts"],"names":["trace","buildSDKAttributes","SpanStatusCode"],"mappings":"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","file":"chunk-UZEJV2YD.cjs","sourcesContent":["/**\n * AWS error classification and handling\n */\n\n/**\n * AWS error types\n */\nexport interface AWSError {\n name: string;\n message: string;\n $metadata?: {\n httpStatusCode?: number;\n requestId?: string;\n };\n Code?: string;\n StatusCode?: number;\n}\n\n/**\n * Classify AWS error for span status\n */\nexport function classifyAWSError(error: unknown): {\n isError: boolean;\n statusCode?: number;\n errorCode?: string;\n} {\n if (!error || typeof error !== 'object') {\n return { isError: false };\n }\n\n const awsError = error as AWSError;\n\n // Check for HTTP status code\n const statusCode = awsError.$metadata?.httpStatusCode || awsError.StatusCode;\n\n // Determine if it's an error (4xx or 5xx)\n const isError = statusCode !== undefined && statusCode >= 400;\n\n return {\n isError,\n statusCode,\n errorCode: awsError.Code || awsError.name,\n };\n}\n\n/**\n * Extract error attributes from AWS error\n */\nexport function extractErrorAttributes(error: unknown): Record<string, string | number> {\n if (!error || typeof error !== 'object') {\n return {};\n }\n\n const awsError = error as AWSError;\n const attrs: Record<string, string | number> = {};\n\n if (awsError.name) {\n attrs['error.type'] = awsError.name;\n }\n\n if (awsError.message) {\n attrs['error.message'] = awsError.message;\n }\n\n if (awsError.Code) {\n attrs['aws.error.code'] = awsError.Code;\n }\n\n if (awsError.$metadata?.requestId) {\n attrs['aws.request_id'] = awsError.$metadata.requestId;\n }\n\n if (awsError.$metadata?.httpStatusCode) {\n attrs['http.status_code'] = awsError.$metadata.httpStatusCode;\n }\n\n return attrs;\n}\n","/**\n * Request metadata extraction utilities\n */\n\nimport type { AWSCommandMetadata } from '../types';\n\n/**\n * Extract request metadata from AWS SDK v3 command\n */\nexport function extractRequestMetadata(\n command: { constructor: { name: string } },\n context: { clientName: string }\n): AWSCommandMetadata {\n return {\n clientName: context.clientName,\n commandName: command.constructor.name,\n };\n}\n\n/**\n * Extract service name from AWS SDK client\n */\nexport function extractServiceName(clientName: string): string {\n // Remove \"Client\" suffix if present\n return clientName.replace(/Client$/, '');\n}\n\n/**\n * Extract operation name from command\n */\nexport function extractOperationName(commandName: string): string {\n // Remove \"Command\" suffix if present\n return commandName.replace(/Command$/, '');\n}\n","/**\n * Response metadata extraction utilities\n */\n\nimport type { AWSCommandMetadata } from '../types';\n\n/**\n * Extract response metadata from AWS SDK v3 response\n */\nexport function extractResponseMetadata(\n response: { $metadata?: Record<string, unknown> }\n): Partial<AWSCommandMetadata> {\n const metadata = response.$metadata || {};\n return {\n requestId: metadata.requestId as string | undefined,\n httpStatusCode: metadata.httpStatusCode as number | undefined,\n extendedRequestId: metadata.extendedRequestId as string | undefined,\n cfId: metadata.cfId as string | undefined,\n };\n}\n","/**\n * Generic AWS SDK v3 client wrapper utilities\n */\n\n// Type-only imports from optional peer dependencies\n// @ts-expect-error - Optional peer dependency, may not be installed\nimport type { Client, Command } from '@aws-sdk/smithy-client';\nimport { extractRequestMetadata, extractServiceName, extractOperationName } from './request-builder';\nimport { extractResponseMetadata } from './response-builder';\nimport { classifyAWSError, extractErrorAttributes } from './error-handlers';\nimport { buildSDKAttributes } from '../attributes';\nimport { trace } from 'autotel';\nimport { SpanStatusCode } from '@opentelemetry/api';\n\n/**\n * Wrap AWS SDK v3 client with OpenTelemetry instrumentation\n */\nexport function wrapSDKClient<T extends Client<any, any, any, any>>(\n client: T,\n serviceName?: string\n): T {\n const clientName = (client.constructor as { name: string }).name;\n const resolvedServiceName = serviceName || extractServiceName(clientName);\n\n // Create a proxy that intercepts send() calls\n return new Proxy(client, {\n get(target, prop) {\n if (prop === 'send') {\n return async function tracedSend(command: Command<any, any, any, any, any>) {\n const metadata = extractRequestMetadata(command, { clientName });\n const operationName = extractOperationName(metadata.commandName);\n\n return trace(`aws.${resolvedServiceName}.${operationName}`, async (ctx) => {\n // Set request attributes\n ctx.setAttributes(\n buildSDKAttributes({\n service: resolvedServiceName,\n operation: operationName,\n })\n );\n\n try {\n const response = await target.send(command);\n\n // Extract and set response metadata\n const responseMetadata = extractResponseMetadata(response);\n if (responseMetadata.requestId) {\n ctx.setAttribute('aws.request_id', responseMetadata.requestId);\n }\n if (responseMetadata.httpStatusCode) {\n ctx.setAttribute('http.status_code', responseMetadata.httpStatusCode);\n }\n if (responseMetadata.extendedRequestId) {\n ctx.setAttribute('aws.extended_request_id', responseMetadata.extendedRequestId);\n }\n if (responseMetadata.cfId) {\n ctx.setAttribute('aws.cf_id', responseMetadata.cfId);\n }\n\n // Set span status based on HTTP status code\n if (responseMetadata.httpStatusCode) {\n if (responseMetadata.httpStatusCode >= 400) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: `HTTP ${responseMetadata.httpStatusCode}`,\n });\n } else {\n ctx.setStatus({ code: SpanStatusCode.OK });\n }\n }\n\n return response;\n } catch (error) {\n // Classify and handle error\n const errorInfo = classifyAWSError(error);\n const errorAttrs = extractErrorAttributes(error);\n\n ctx.setAttributes(errorAttrs);\n\n if (errorInfo.isError) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: errorInfo.errorCode || 'AWS Error',\n });\n }\n\n throw error;\n }\n });\n };\n }\n\n return (target as any)[prop];\n },\n }) as T;\n}\n"]}
@@ -0,0 +1,341 @@
1
+ import { buildLambdaAttributes } from './chunk-I4CKQ4RD.js';
2
+ import { propagation, context, trace, SpanStatusCode } from '@opentelemetry/api';
3
+ import { trace as trace$1 } from 'autotel';
4
+ import { AWSXRayPropagator } from '@opentelemetry/propagator-aws-xray';
5
+
6
+ function extractTraceContext(event) {
7
+ if (event.headers?.traceparent) {
8
+ const carrier = {};
9
+ if (event.headers.traceparent) carrier.traceparent = event.headers.traceparent;
10
+ if (event.headers.tracestate) carrier.tracestate = event.headers.tracestate;
11
+ if (event.headers.baggage) carrier.baggage = event.headers.baggage;
12
+ const extractedContext = propagation.extract(context.active(), carrier);
13
+ const spanContext = trace.getSpanContext(extractedContext);
14
+ return spanContext;
15
+ }
16
+ if (event.Records?.[0]?.messageAttributes?.traceparent) {
17
+ const record = event.Records[0];
18
+ if (!record.messageAttributes) return void 0;
19
+ const carrier = {};
20
+ if (record.messageAttributes.traceparent?.StringValue) {
21
+ carrier.traceparent = record.messageAttributes.traceparent.StringValue;
22
+ }
23
+ if (record.messageAttributes.tracestate?.StringValue) {
24
+ carrier.tracestate = record.messageAttributes.tracestate.StringValue;
25
+ }
26
+ if (record.messageAttributes.baggage?.StringValue) {
27
+ carrier.baggage = record.messageAttributes.baggage.StringValue;
28
+ }
29
+ const extractedContext = propagation.extract(context.active(), carrier);
30
+ const spanContext = trace.getSpanContext(extractedContext);
31
+ return spanContext;
32
+ }
33
+ if (event.Records?.[0]?.Sns?.MessageAttributes?.traceparent) {
34
+ const sns = event.Records[0].Sns;
35
+ if (!sns.MessageAttributes) return void 0;
36
+ const carrier = {};
37
+ if (sns.MessageAttributes.traceparent?.Value) {
38
+ carrier.traceparent = sns.MessageAttributes.traceparent.Value;
39
+ }
40
+ if (sns.MessageAttributes.tracestate?.Value) {
41
+ carrier.tracestate = sns.MessageAttributes.tracestate.Value;
42
+ }
43
+ if (sns.MessageAttributes.baggage?.Value) {
44
+ carrier.baggage = sns.MessageAttributes.baggage.Value;
45
+ }
46
+ const extractedContext = propagation.extract(context.active(), carrier);
47
+ const spanContext = trace.getSpanContext(extractedContext);
48
+ return spanContext;
49
+ }
50
+ if (event.headers?.["x-amzn-trace-id"]) {
51
+ const xrayPropagator = new AWSXRayPropagator();
52
+ const carrier = {
53
+ "x-amzn-trace-id": event.headers["x-amzn-trace-id"]
54
+ };
55
+ const getter = {
56
+ get(carrier2, key) {
57
+ return carrier2[key];
58
+ },
59
+ keys(carrier2) {
60
+ return Object.keys(carrier2);
61
+ }
62
+ };
63
+ const extractedContext = xrayPropagator.extract(context.active(), carrier, getter);
64
+ const spanContext = trace.getSpanContext(extractedContext);
65
+ return spanContext;
66
+ }
67
+ if (event._autotel_trace_context) {
68
+ return event._autotel_trace_context;
69
+ }
70
+ return void 0;
71
+ }
72
+ function detectTriggerType(event) {
73
+ if (event.headers || event.requestContext || event.httpMethod) {
74
+ return "http";
75
+ }
76
+ if (event.Records?.some((r) => r.messageAttributes || "messageId" in r)) {
77
+ return "pubsub";
78
+ }
79
+ if (event.Records?.some((r) => r.Sns)) {
80
+ return "pubsub";
81
+ }
82
+ if (event.Records?.some((r) => r.kinesis)) {
83
+ return "datasource";
84
+ }
85
+ if (event.source === "aws.events" || event["detail-type"]) {
86
+ return "timer";
87
+ }
88
+ return "other";
89
+ }
90
+
91
+ // src/lambda/handler.ts
92
+ var coldStartMap = /* @__PURE__ */ new Map();
93
+ var MAX_ERROR_MESSAGE_LENGTH = 500;
94
+ function createContextWithParent(parentSpanContext) {
95
+ const parentSpan = trace.wrapSpanContext(parentSpanContext);
96
+ return trace.setSpan(context.active(), parentSpan);
97
+ }
98
+ function truncateErrorMessage(message) {
99
+ if (message.length <= MAX_ERROR_MESSAGE_LENGTH) {
100
+ return message;
101
+ }
102
+ return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
103
+ }
104
+ function extractAccountIdFromArn(arn) {
105
+ const arnParts = arn.split(":");
106
+ if (arnParts.length >= 5) {
107
+ return arnParts[4];
108
+ }
109
+ return void 0;
110
+ }
111
+ function wrapHandler(handler, config) {
112
+ return async (event, lambdaContext) => {
113
+ const functionName = lambdaContext.functionName;
114
+ const isColdStart = !coldStartMap.has(functionName);
115
+ if (isColdStart) {
116
+ coldStartMap.set(functionName, true);
117
+ }
118
+ const shouldExtractContext = config?.extractTraceContext !== false;
119
+ const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : void 0;
120
+ const trigger = detectTriggerType(event);
121
+ const executeWithTracing = async () => {
122
+ return trace$1(
123
+ `lambda.${functionName}`,
124
+ async (ctx) => {
125
+ ctx.setAttributes(
126
+ buildLambdaAttributes({
127
+ awsRequestId: lambdaContext.awsRequestId,
128
+ functionName,
129
+ functionVersion: lambdaContext.functionVersion,
130
+ coldStart: isColdStart,
131
+ trigger
132
+ })
133
+ );
134
+ const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);
135
+ if (accountId) {
136
+ ctx.setAttribute("cloud.account.id", accountId);
137
+ }
138
+ const region = process.env.AWS_REGION;
139
+ if (region) {
140
+ ctx.setAttribute("cloud.region", region);
141
+ }
142
+ try {
143
+ const result = await handler(event, lambdaContext);
144
+ if (config?.captureResponse && result != null) {
145
+ try {
146
+ const responseJson = JSON.stringify(result);
147
+ if (responseJson.length <= 4096) {
148
+ ctx.setAttribute("lambda.response", responseJson);
149
+ } else {
150
+ ctx.setAttribute("lambda.response.truncated", true);
151
+ ctx.setAttribute("lambda.response.size", responseJson.length);
152
+ }
153
+ } catch {
154
+ ctx.setAttribute("lambda.response.serialization_failed", true);
155
+ }
156
+ }
157
+ return result;
158
+ } catch (error) {
159
+ const errorMessage = error instanceof Error ? error.message : String(error);
160
+ ctx.setStatus({
161
+ code: SpanStatusCode.ERROR,
162
+ message: truncateErrorMessage(errorMessage)
163
+ });
164
+ ctx.setAttribute("exception.type", error instanceof Error ? error.constructor.name : "Error");
165
+ ctx.setAttribute("exception.message", truncateErrorMessage(errorMessage));
166
+ if (error instanceof Error && error.stack) {
167
+ ctx.setAttribute("exception.stacktrace", error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH));
168
+ }
169
+ throw error;
170
+ }
171
+ }
172
+ );
173
+ };
174
+ if (parentSpanContext) {
175
+ const parentContext = createContextWithParent(parentSpanContext);
176
+ return context.with(parentContext, executeWithTracing);
177
+ }
178
+ return executeWithTracing();
179
+ };
180
+ }
181
+ function traceLambda(factory, config) {
182
+ return async (event, lambdaContext) => {
183
+ const functionName = lambdaContext.functionName;
184
+ const isColdStart = !coldStartMap.has(functionName);
185
+ if (isColdStart) {
186
+ coldStartMap.set(functionName, true);
187
+ }
188
+ const shouldExtractContext = config?.extractTraceContext !== false;
189
+ const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : void 0;
190
+ const trigger = detectTriggerType(event);
191
+ const executeWithTracing = async () => {
192
+ return trace$1(
193
+ `lambda.${functionName}`,
194
+ async (ctx) => {
195
+ ctx.setAttributes(
196
+ buildLambdaAttributes({
197
+ awsRequestId: lambdaContext.awsRequestId,
198
+ functionName,
199
+ functionVersion: lambdaContext.functionVersion,
200
+ coldStart: isColdStart,
201
+ trigger
202
+ })
203
+ );
204
+ const accountId = extractAccountIdFromArn(lambdaContext.invokedFunctionArn);
205
+ if (accountId) {
206
+ ctx.setAttribute("cloud.account.id", accountId);
207
+ }
208
+ const region = process.env.AWS_REGION;
209
+ if (region) {
210
+ ctx.setAttribute("cloud.region", region);
211
+ }
212
+ const handler = factory(ctx);
213
+ return handler(event, lambdaContext);
214
+ }
215
+ );
216
+ };
217
+ if (parentSpanContext) {
218
+ const parentContext = createContextWithParent(parentSpanContext);
219
+ return context.with(parentContext, executeWithTracing);
220
+ }
221
+ return executeWithTracing();
222
+ };
223
+ }
224
+ var SPAN_SYMBOL = Symbol.for("autotel-aws.span");
225
+ var CONTEXT_SYMBOL = Symbol.for("autotel-aws.context");
226
+ var coldStartMap2 = /* @__PURE__ */ new Map();
227
+ var MAX_ERROR_MESSAGE_LENGTH2 = 500;
228
+ function createContextWithParent2(parentSpanContext) {
229
+ const parentSpan = trace.wrapSpanContext(parentSpanContext);
230
+ return trace.setSpan(context.active(), parentSpan);
231
+ }
232
+ function truncateErrorMessage2(message) {
233
+ if (message.length <= MAX_ERROR_MESSAGE_LENGTH2) {
234
+ return message;
235
+ }
236
+ return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH2)}... (truncated)`;
237
+ }
238
+ function extractAccountIdFromArn2(arn) {
239
+ const arnParts = arn.split(":");
240
+ if (arnParts.length >= 5) {
241
+ return arnParts[4];
242
+ }
243
+ return void 0;
244
+ }
245
+ function tracingMiddleware(config) {
246
+ const tracer = trace.getTracer("autotel-aws");
247
+ return {
248
+ before: async (request) => {
249
+ const { event, context: lambdaContext } = request;
250
+ const functionName = lambdaContext.functionName;
251
+ const isColdStart = !coldStartMap2.has(functionName);
252
+ if (isColdStart) {
253
+ coldStartMap2.set(functionName, true);
254
+ }
255
+ const shouldExtractContext = config?.extractTraceContext !== false;
256
+ const parentSpanContext = shouldExtractContext ? extractTraceContext(event) : void 0;
257
+ const trigger = detectTriggerType(event);
258
+ let parentContext = context.active();
259
+ if (parentSpanContext) {
260
+ parentContext = createContextWithParent2(parentSpanContext);
261
+ }
262
+ const span = tracer.startSpan(
263
+ `lambda.${functionName}`,
264
+ {
265
+ attributes: buildLambdaAttributes({
266
+ awsRequestId: lambdaContext.awsRequestId,
267
+ functionName,
268
+ functionVersion: lambdaContext.functionVersion,
269
+ coldStart: isColdStart,
270
+ trigger
271
+ })
272
+ },
273
+ parentContext
274
+ );
275
+ const accountId = extractAccountIdFromArn2(lambdaContext.invokedFunctionArn);
276
+ if (accountId) {
277
+ span.setAttribute("cloud.account.id", accountId);
278
+ }
279
+ const region = process.env.AWS_REGION;
280
+ if (region) {
281
+ span.setAttribute("cloud.region", region);
282
+ }
283
+ request[SPAN_SYMBOL] = span;
284
+ request[CONTEXT_SYMBOL] = trace.setSpan(parentContext, span);
285
+ return new Promise((resolve) => {
286
+ context.with(request[CONTEXT_SYMBOL], () => {
287
+ resolve();
288
+ });
289
+ });
290
+ },
291
+ after: async (request) => {
292
+ const span = request[SPAN_SYMBOL];
293
+ if (!span) return;
294
+ if (config?.captureResponse && request.response != null) {
295
+ try {
296
+ const responseJson = JSON.stringify(request.response);
297
+ if (responseJson.length <= 4096) {
298
+ span.setAttribute("lambda.response", responseJson);
299
+ } else {
300
+ span.setAttribute("lambda.response.truncated", true);
301
+ span.setAttribute("lambda.response.size", responseJson.length);
302
+ }
303
+ } catch {
304
+ span.setAttribute("lambda.response.serialization_failed", true);
305
+ }
306
+ }
307
+ span.setStatus({ code: SpanStatusCode.OK });
308
+ span.end();
309
+ },
310
+ onError: async (request) => {
311
+ const span = request[SPAN_SYMBOL];
312
+ if (!span) return;
313
+ const error = request.error;
314
+ if (error) {
315
+ const errorMessage = error.message || String(error);
316
+ span.setStatus({
317
+ code: SpanStatusCode.ERROR,
318
+ message: truncateErrorMessage2(errorMessage)
319
+ });
320
+ span.setAttribute("exception.type", error.name || "Error");
321
+ span.setAttribute("exception.message", truncateErrorMessage2(errorMessage));
322
+ if (error.stack) {
323
+ span.setAttribute("exception.stacktrace", error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH2));
324
+ }
325
+ span.recordException(error);
326
+ }
327
+ span.end();
328
+ }
329
+ };
330
+ }
331
+ var LambdaMiddleware = tracingMiddleware;
332
+ function getSpanFromRequest(request) {
333
+ return request[SPAN_SYMBOL];
334
+ }
335
+ function getContextFromRequest(request) {
336
+ return request[CONTEXT_SYMBOL];
337
+ }
338
+
339
+ export { LambdaMiddleware, detectTriggerType, extractTraceContext, getContextFromRequest, getSpanFromRequest, traceLambda, tracingMiddleware, wrapHandler };
340
+ //# sourceMappingURL=chunk-V4IQWFYN.js.map
341
+ //# sourceMappingURL=chunk-V4IQWFYN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lambda/context-extractor.ts","../src/lambda/handler.ts","../src/lambda/middleware.ts"],"names":["carrier","otelTrace","context","autotelTrace","coldStartMap","MAX_ERROR_MESSAGE_LENGTH","createContextWithParent","truncateErrorMessage","extractAccountIdFromArn","SpanStatusCode"],"mappings":"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","file":"chunk-V4IQWFYN.js","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"]}
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var chunkQ3DMMQ7K_cjs = require('./chunk-Q3DMMQ7K.cjs');
4
+ var autotel = require('autotel');
5
+
6
+ function traceDynamoDB(config) {
7
+ return function wrapper(fn) {
8
+ return autotel.trace(
9
+ `dynamodb.${config.operation}`,
10
+ (ctx) => async (...args) => {
11
+ ctx.setAttributes(
12
+ chunkQ3DMMQ7K_cjs.buildDynamoDBAttributes({
13
+ tableName: config.table,
14
+ operation: config.operation
15
+ })
16
+ );
17
+ const handler = fn(ctx);
18
+ return handler(...args);
19
+ }
20
+ );
21
+ };
22
+ }
23
+
24
+ exports.traceDynamoDB = traceDynamoDB;
25
+ //# sourceMappingURL=chunk-VZHQH75L.cjs.map
26
+ //# sourceMappingURL=chunk-VZHQH75L.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dynamodb/index.ts"],"names":["trace","buildDynamoDBAttributes"],"mappings":";;;;;AA6FO,SAAS,cAAc,MAAA,EAA6B;AACzD,EAAA,OAAO,SAAS,QACd,EAAA,EACsC;AAEtC,IAAA,OAAOA,aAAA;AAAA,MACL,CAAA,SAAA,EAAY,OAAO,SAAS,CAAA,CAAA;AAAA,MAC5B,CAAC,GAAA,KACC,OAAA,GAAU,IAAA,KAAkC;AAE1C,QAAA,GAAA,CAAI,aAAA;AAAA,UACFC,yCAAA,CAAwB;AAAA,YACtB,WAAW,MAAA,CAAO,KAAA;AAAA,YAClB,WAAW,MAAA,CAAO;AAAA,WACnB;AAAA,SACH;AAGA,QAAA,MAAM,OAAA,GAAU,GAAG,GAAG,CAAA;AACtB,QAAA,OAAO,OAAA,CAAQ,GAAG,IAAI,CAAA;AAAA,MACxB;AAAA,KACJ;AAAA,EACF,CAAA;AACF","file":"chunk-VZHQH75L.cjs","sourcesContent":["/**\n * DynamoDB-specific instrumentation\n *\n * Provides semantic helpers for tracing DynamoDB operations with proper OpenTelemetry\n * semantic conventions. Automatically sets `db.*` and `aws.dynamodb.*` attributes.\n *\n * @example Basic usage with factory pattern\n * ```typescript\n * import { traceDynamoDB } from 'autotel-aws/dynamodb';\n * import { DynamoDBClient, GetItemCommand } from '@aws-sdk/client-dynamodb';\n *\n * const dynamodb = new DynamoDBClient({});\n *\n * export const getUser = traceDynamoDB({\n * operation: 'GetItem',\n * table: 'users'\n * })(ctx => async (userId: string) => {\n * ctx.setAttribute('db.statement', 'GetItem WHERE id = :id');\n * return await dynamodb.send(new GetItemCommand({\n * TableName: 'users',\n * Key: { id: { S: userId } }\n * }));\n * });\n *\n * // Usage: await getUser('user-123');\n * ```\n *\n * @example Query with consumed capacity tracking\n * ```typescript\n * export const queryOrders = traceDynamoDB({\n * operation: 'Query',\n * table: 'orders'\n * })(ctx => async (customerId: string, limit: number) => {\n * const result = await dynamodb.send(new QueryCommand({\n * TableName: 'orders',\n * KeyConditionExpression: 'customerId = :cid',\n * ExpressionAttributeValues: { ':cid': { S: customerId } },\n * Limit: limit,\n * ReturnConsumedCapacity: 'TOTAL'\n * }));\n *\n * if (result.ConsumedCapacity?.CapacityUnits) {\n * ctx.setAttribute('aws.dynamodb.consumed_capacity', result.ConsumedCapacity.CapacityUnits);\n * }\n *\n * return result.Items;\n * });\n * ```\n */\n\nimport { trace, type TraceContext } from 'autotel';\nimport { buildDynamoDBAttributes } from '../attributes';\n\n/**\n * DynamoDB operation configuration\n */\nexport interface TraceDynamoDBConfig {\n /**\n * DynamoDB operation name (e.g., 'GetItem', 'PutItem', 'Query', 'Scan')\n * Used to generate the span name: `dynamodb.{operation}`\n */\n operation: string;\n\n /**\n * DynamoDB table name.\n * Sets `db.name` and `aws.dynamodb.table_names` attributes.\n */\n table: string;\n}\n\n/**\n * Trace DynamoDB operations with semantic attributes\n *\n * Creates a traced function that automatically sets DynamoDB semantic attributes\n * following OpenTelemetry database semantic conventions.\n *\n * @param config - DynamoDB operation configuration\n * @returns A higher-order function that wraps your DynamoDB operation with tracing\n *\n * @remarks\n * Semantic attributes set automatically:\n * - `db.system` - 'dynamodb'\n * - `db.operation` - The operation name (GetItem, PutItem, etc.)\n * - `db.name` - Table name\n * - `aws.dynamodb.table_names` - Array containing the table name\n *\n * Additional attributes you should set in your handler:\n * - `db.statement` - Query/operation description\n * - `aws.dynamodb.consumed_capacity` - Consumed capacity units\n * - `aws.dynamodb.index_name` - GSI/LSI name if applicable\n *\n * @see https://opentelemetry.io/docs/specs/semconv/database/dynamodb/\n */\nexport function traceDynamoDB(config: TraceDynamoDBConfig) {\n return function wrapper<TArgs extends unknown[], TReturn>(\n fn: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): (...args: TArgs) => Promise<TReturn> {\n // Use autotel's trace() which properly handles the factory pattern\n return trace(\n `dynamodb.${config.operation}`,\n (ctx: TraceContext) =>\n async (...args: TArgs): Promise<TReturn> => {\n // Set DynamoDB semantic attributes\n ctx.setAttributes(\n buildDynamoDBAttributes({\n tableName: config.table,\n operation: config.operation,\n }),\n );\n\n // Get the user's handler and execute with forwarded arguments\n const handler = fn(ctx);\n return handler(...args);\n },\n );\n };\n}\n"]}