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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Jag Reehal 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
# autotel-aws
|
|
2
|
+
|
|
3
|
+
OpenTelemetry instrumentation for AWS services - ergonomic, vendor-agnostic observability.
|
|
4
|
+
|
|
5
|
+
> **AWS X-Ray SDK Deprecation Notice**: AWS X-Ray SDKs enter maintenance mode on February 25, 2026 and reach end of support on February 25, 2027. AWS recommends migrating to OpenTelemetry. This package provides an ergonomic migration path.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Lambda Handler Instrumentation** - Automatic tracing with cold start detection
|
|
10
|
+
- **AWS SDK v3 Auto-Instrumentation** - Global patching or per-client wrapping
|
|
11
|
+
- **Service-Specific Semantic Helpers** - S3, DynamoDB, SQS, SNS, Kinesis, Step Functions, EventBridge
|
|
12
|
+
- **SQS Producer/Consumer Classes** - Built-in trace context propagation
|
|
13
|
+
- **SNS Publisher Class** - Automatic context injection for distributed tracing
|
|
14
|
+
- **Kinesis Producer/Consumer Classes** - Stream processing with context propagation
|
|
15
|
+
- **Step Functions Executor/Worker** - State machine orchestration with distributed tracing
|
|
16
|
+
- **EventBridge Publisher** - Event-driven architecture tracing
|
|
17
|
+
- **X-Ray Compatibility** - Annotation/metadata helpers for X-Ray users
|
|
18
|
+
- **Middy Middleware** - Full span lifecycle management for Middy users
|
|
19
|
+
- **Lambda Layer** - Pre-built layer for easy deployment
|
|
20
|
+
- **Vendor Agnostic** - Works with any OTLP backend (X-Ray, Honeycomb, Datadog, etc.)
|
|
21
|
+
- **Tree-Shakeable** - Per-service entry points for minimal bundle size
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install autotel-aws autotel
|
|
27
|
+
# or
|
|
28
|
+
pnpm add autotel-aws autotel
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
> **Note:** `autotel` is the core tracing library that provides `init()`, `trace()`, and other foundational APIs. `autotel-aws` extends it with AWS-specific instrumentation.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Lambda Handler
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { init } from 'autotel';
|
|
39
|
+
import { wrapHandler } from 'autotel-aws/lambda';
|
|
40
|
+
|
|
41
|
+
init({ service: 'my-lambda', endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT });
|
|
42
|
+
|
|
43
|
+
export const handler = wrapHandler(async (event, context) => {
|
|
44
|
+
// Your handler code - automatically traced
|
|
45
|
+
return { statusCode: 200 };
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Zero-Config Mode
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// IMPORTANT: Import this FIRST, before any AWS SDK imports
|
|
53
|
+
import 'autotel-aws/lambda/auto';
|
|
54
|
+
|
|
55
|
+
// Reads from OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_ENDPOINT
|
|
56
|
+
export const handler = async (event, context) => {
|
|
57
|
+
return { statusCode: 200 };
|
|
58
|
+
};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
> **Note:** The auto-import must be at the top of your file to ensure instrumentation is set up before any AWS SDK clients are created.
|
|
62
|
+
|
|
63
|
+
### AWS SDK Auto-Instrumentation
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { autoInstrumentAWS } from 'autotel-aws/sdk';
|
|
67
|
+
|
|
68
|
+
// Call at the top level of your file - all SDK clients are automatically traced
|
|
69
|
+
autoInstrumentAWS();
|
|
70
|
+
|
|
71
|
+
// All subsequent clients are instrumented
|
|
72
|
+
const s3 = new S3Client({ region: 'us-east-1' });
|
|
73
|
+
const dynamodb = new DynamoDBClient({ region: 'us-east-1' });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Per-Client Instrumentation
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { instrumentSDK, createTracedClient } from 'autotel-aws/sdk';
|
|
80
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
81
|
+
|
|
82
|
+
// Option A: Wrap existing client
|
|
83
|
+
const s3 = instrumentSDK(new S3Client({ region: 'us-east-1' }));
|
|
84
|
+
|
|
85
|
+
// Option B: Create pre-instrumented client
|
|
86
|
+
const s3 = createTracedClient(S3Client, { region: 'us-east-1' });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## SQS Producer/Consumer
|
|
90
|
+
|
|
91
|
+
End-to-end distributed tracing across message queues with **automatic context injection/extraction** - each message in a batch is correctly linked to its parent trace:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { SQSProducer, SQSConsumer } from 'autotel-aws/sqs';
|
|
95
|
+
import { SQSClient } from '@aws-sdk/client-sqs';
|
|
96
|
+
|
|
97
|
+
const sqs = new SQSClient({ region: 'us-east-1' });
|
|
98
|
+
|
|
99
|
+
// Producer - automatically injects trace context
|
|
100
|
+
const producer = new SQSProducer(sqs, {
|
|
101
|
+
queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/my-queue',
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await producer.send({ body: JSON.stringify({ orderId: '12345' }) });
|
|
105
|
+
|
|
106
|
+
// Batch send
|
|
107
|
+
await producer.sendBatch([
|
|
108
|
+
{ body: JSON.stringify({ orderId: '1' }), id: 'msg-1' },
|
|
109
|
+
{ body: JSON.stringify({ orderId: '2' }), id: 'msg-2' },
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
// Consumer - automatically extracts trace context
|
|
113
|
+
const consumer = new SQSConsumer(sqs, {
|
|
114
|
+
queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/my-queue',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await consumer.processMessages(async (message, ctx) => {
|
|
118
|
+
ctx.setAttribute('order.id', JSON.parse(message.body).orderId);
|
|
119
|
+
await processOrder(message.body);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Continuous polling
|
|
123
|
+
await consumer.poll(async (message, ctx) => {
|
|
124
|
+
return await processOrder(message.body);
|
|
125
|
+
}, { maxIterations: 100 });
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## SNS Publisher
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { SNSPublisher } from 'autotel-aws/sns';
|
|
132
|
+
import { SNSClient } from '@aws-sdk/client-sns';
|
|
133
|
+
|
|
134
|
+
const sns = new SNSClient({ region: 'us-east-1' });
|
|
135
|
+
const publisher = new SNSPublisher(sns, {
|
|
136
|
+
topicArn: 'arn:aws:sns:us-east-1:123456789:my-topic',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Single publish - trace context is automatically injected
|
|
140
|
+
await publisher.publish({
|
|
141
|
+
message: JSON.stringify({ event: 'ORDER_COMPLETED' }),
|
|
142
|
+
subject: 'Order Notification',
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Batch publish
|
|
146
|
+
await publisher.publishBatch([
|
|
147
|
+
{ message: JSON.stringify({ event: 'EVENT_1' }) },
|
|
148
|
+
{ message: JSON.stringify({ event: 'EVENT_2' }) },
|
|
149
|
+
{ message: JSON.stringify({ event: 'EVENT_3' }) },
|
|
150
|
+
]);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Kinesis Producer/Consumer
|
|
154
|
+
|
|
155
|
+
Stream processing with automatic trace context propagation:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { KinesisProducer, KinesisConsumer } from 'autotel-aws/kinesis';
|
|
159
|
+
import { KinesisClient } from '@aws-sdk/client-kinesis';
|
|
160
|
+
|
|
161
|
+
const kinesis = new KinesisClient({ region: 'us-east-1' });
|
|
162
|
+
|
|
163
|
+
// Producer - injects trace context into record data
|
|
164
|
+
const producer = new KinesisProducer(kinesis, {
|
|
165
|
+
streamName: 'my-stream',
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
await producer.putRecord({
|
|
169
|
+
data: { orderId: '123', action: 'created' },
|
|
170
|
+
partitionKey: 'order-123',
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Batch put
|
|
174
|
+
await producer.putRecords([
|
|
175
|
+
{ data: { id: '1' }, partitionKey: 'pk-1' },
|
|
176
|
+
{ data: { id: '2' }, partitionKey: 'pk-2' },
|
|
177
|
+
]);
|
|
178
|
+
|
|
179
|
+
// Consumer - extracts trace context from records
|
|
180
|
+
const consumer = new KinesisConsumer(kinesis, {
|
|
181
|
+
streamName: 'my-stream',
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const shardIterator = await consumer.getShardIterator('shardId-000000000000', 'TRIM_HORIZON');
|
|
185
|
+
|
|
186
|
+
await consumer.processRecords(shardIterator, async (record, ctx) => {
|
|
187
|
+
ctx.setAttribute('order.id', record.orderId);
|
|
188
|
+
await processRecord(record);
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Step Functions
|
|
193
|
+
|
|
194
|
+
Orchestrate workflows with distributed tracing across state machines:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { StepFunctionsExecutor, StepFunctionsActivityWorker } from 'autotel-aws/step-functions';
|
|
198
|
+
import { SFNClient } from '@aws-sdk/client-sfn';
|
|
199
|
+
|
|
200
|
+
const sfn = new SFNClient({ region: 'us-east-1' });
|
|
201
|
+
|
|
202
|
+
// Executor - starts workflows with trace context injection
|
|
203
|
+
const executor = new StepFunctionsExecutor(sfn, {
|
|
204
|
+
stateMachineArn: 'arn:aws:states:us-east-1:123456789:stateMachine:OrderProcessor',
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Start async execution
|
|
208
|
+
const result = await executor.startExecution({
|
|
209
|
+
input: { orderId: '123', items: ['item1', 'item2'] },
|
|
210
|
+
name: 'order-123-execution',
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Start sync execution (Express workflows)
|
|
214
|
+
const syncResult = await executor.startSyncExecution({
|
|
215
|
+
input: { orderId: '456' },
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Activity worker - processes tasks with trace context extraction
|
|
219
|
+
const worker = new StepFunctionsActivityWorker(sfn, {
|
|
220
|
+
activityArn: 'arn:aws:states:us-east-1:123456789:activity:ProcessPayment',
|
|
221
|
+
workerName: 'payment-worker-1',
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
await worker.poll(async (input, taskToken, ctx) => {
|
|
225
|
+
ctx.setAttribute('payment.amount', input.amount);
|
|
226
|
+
const result = await processPayment(input);
|
|
227
|
+
return result;
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Lambda Invoked by Step Functions
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { extractStepFunctionsContext, stripTraceContext } from 'autotel-aws/step-functions';
|
|
235
|
+
import { wrapHandler } from 'autotel-aws/lambda';
|
|
236
|
+
|
|
237
|
+
export const handler = wrapHandler(async (event) => {
|
|
238
|
+
// Extract parent trace context from Step Functions input
|
|
239
|
+
const parentContext = extractStepFunctionsContext(event);
|
|
240
|
+
|
|
241
|
+
// Process without trace context fields
|
|
242
|
+
const { orderId, items } = stripTraceContext(event);
|
|
243
|
+
await processOrder(orderId, items);
|
|
244
|
+
|
|
245
|
+
return { status: 'completed' };
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## EventBridge
|
|
250
|
+
|
|
251
|
+
Event-driven architecture with trace context propagation:
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { EventBridgePublisher } from 'autotel-aws/eventbridge';
|
|
255
|
+
import { EventBridgeClient } from '@aws-sdk/client-eventbridge';
|
|
256
|
+
|
|
257
|
+
const eventBridge = new EventBridgeClient({ region: 'us-east-1' });
|
|
258
|
+
const publisher = new EventBridgePublisher(eventBridge, {
|
|
259
|
+
eventBusName: 'my-event-bus',
|
|
260
|
+
source: 'com.myapp.orders',
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Single event - trace context injected into detail
|
|
264
|
+
await publisher.putEvent({
|
|
265
|
+
detailType: 'OrderCreated',
|
|
266
|
+
detail: { orderId: '123', customerId: 'abc' },
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Batch events
|
|
270
|
+
await publisher.putEvents([
|
|
271
|
+
{ detailType: 'OrderCreated', detail: { orderId: '1' } },
|
|
272
|
+
{ detailType: 'OrderCreated', detail: { orderId: '2' } },
|
|
273
|
+
{ detailType: 'OrderCreated', detail: { orderId: '3' } },
|
|
274
|
+
]);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Lambda Invoked by EventBridge
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
import { extractEventBridgeContext, stripEventBridgeContext } from 'autotel-aws/eventbridge';
|
|
281
|
+
import { wrapHandler } from 'autotel-aws/lambda';
|
|
282
|
+
|
|
283
|
+
export const handler = wrapHandler(async (event) => {
|
|
284
|
+
// Extract parent trace context from EventBridge detail
|
|
285
|
+
const parentContext = extractEventBridgeContext(event);
|
|
286
|
+
|
|
287
|
+
// Process without trace context fields
|
|
288
|
+
const cleanDetail = stripEventBridgeContext(event.detail);
|
|
289
|
+
await processEvent(cleanDetail);
|
|
290
|
+
|
|
291
|
+
return { statusCode: 200 };
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Middy Middleware
|
|
296
|
+
|
|
297
|
+
Full span lifecycle management for Middy users:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import middy from '@middy/core';
|
|
301
|
+
import { tracingMiddleware } from 'autotel-aws/lambda';
|
|
302
|
+
|
|
303
|
+
const baseHandler = async (event, context) => {
|
|
304
|
+
return { statusCode: 200 };
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
export const handler = middy(baseHandler)
|
|
308
|
+
.use(tracingMiddleware({ captureResponse: true }));
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Service-Specific Semantic Helpers
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
import { traceS3 } from 'autotel-aws/s3';
|
|
315
|
+
import { traceDynamoDB } from 'autotel-aws/dynamodb';
|
|
316
|
+
import { traceKinesis } from 'autotel-aws/kinesis';
|
|
317
|
+
import { traceStepFunction } from 'autotel-aws/step-functions';
|
|
318
|
+
import { traceEventBridge } from 'autotel-aws/eventbridge';
|
|
319
|
+
|
|
320
|
+
// S3 operations with semantic attributes
|
|
321
|
+
export const uploadFile = traceS3({
|
|
322
|
+
bucket: 'my-bucket',
|
|
323
|
+
operation: 'PutObject',
|
|
324
|
+
})(ctx => async (key: string, body: Buffer) => {
|
|
325
|
+
ctx.setAttribute('s3.key', key);
|
|
326
|
+
return await s3.send(new PutObjectCommand({ Bucket: 'my-bucket', Key: key, Body: body }));
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// DynamoDB operations with semantic attributes
|
|
330
|
+
export const getUser = traceDynamoDB({
|
|
331
|
+
table: 'users',
|
|
332
|
+
operation: 'GetItem',
|
|
333
|
+
})(ctx => async (userId: string) => {
|
|
334
|
+
return await dynamodb.send(new GetItemCommand({
|
|
335
|
+
TableName: 'users',
|
|
336
|
+
Key: { id: { S: userId } }
|
|
337
|
+
}));
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Kinesis with semantic attributes
|
|
341
|
+
export const publishEvent = traceKinesis({
|
|
342
|
+
streamName: 'events',
|
|
343
|
+
operation: 'PutRecord',
|
|
344
|
+
})(ctx => async (event: Event) => {
|
|
345
|
+
ctx.setAttribute('event.type', event.type);
|
|
346
|
+
return await kinesis.send(new PutRecordCommand({...}));
|
|
347
|
+
});
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## X-Ray Annotations
|
|
351
|
+
|
|
352
|
+
For users sending traces to AWS X-Ray, annotations are indexed for filtering:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { setXRayAnnotation, setXRayMetadata } from 'autotel-aws/xray';
|
|
356
|
+
|
|
357
|
+
export const handler = wrapHandler(async (event, context) => {
|
|
358
|
+
// Indexed in X-Ray (for filtering)
|
|
359
|
+
setXRayAnnotation('user.id', event.userId);
|
|
360
|
+
setXRayAnnotation('order.status', 'completed');
|
|
361
|
+
|
|
362
|
+
// Not indexed (for detailed data)
|
|
363
|
+
setXRayMetadata('request.payload', event);
|
|
364
|
+
|
|
365
|
+
return { statusCode: 200 };
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Lambda Layer
|
|
370
|
+
|
|
371
|
+
Build and deploy a Lambda Layer with autotel-aws and all dependencies:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
# Build the layer
|
|
375
|
+
pnpm --filter autotel-aws build:layer
|
|
376
|
+
|
|
377
|
+
# Deploy with AWS CLI
|
|
378
|
+
aws lambda publish-layer-version \
|
|
379
|
+
--layer-name autotel-aws \
|
|
380
|
+
--zip-file fileb://dist/layer/autotel-aws-layer.zip \
|
|
381
|
+
--compatible-runtimes nodejs18.x nodejs20.x nodejs22.x \
|
|
382
|
+
--compatible-architectures x86_64 arm64
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Then attach the layer to your Lambda function and import as normal:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { init } from 'autotel';
|
|
389
|
+
import { wrapHandler } from 'autotel-aws/lambda';
|
|
390
|
+
|
|
391
|
+
init({ service: 'my-service' });
|
|
392
|
+
|
|
393
|
+
export const handler = wrapHandler(async (event) => {
|
|
394
|
+
return { statusCode: 200 };
|
|
395
|
+
});
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Migration from AWS X-Ray SDK
|
|
401
|
+
|
|
402
|
+
### Why Migrate?
|
|
403
|
+
|
|
404
|
+
- X-Ray SDKs enter **maintenance mode** on February 25, 2026
|
|
405
|
+
- X-Ray SDKs reach **end of support** on February 25, 2027
|
|
406
|
+
- OpenTelemetry is AWS's recommended observability standard
|
|
407
|
+
- Vendor-agnostic: same instrumentation works with X-Ray, Honeycomb, Datadog, etc.
|
|
408
|
+
|
|
409
|
+
### Before (X-Ray SDK)
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import AWSXRay from 'aws-xray-sdk';
|
|
413
|
+
|
|
414
|
+
AWSXRay.config([AWSXRay.plugins.EC2Plugin]);
|
|
415
|
+
const s3 = AWSXRay.captureAWSv3Client(new S3Client({}));
|
|
416
|
+
|
|
417
|
+
export const handler = async (event, context) => {
|
|
418
|
+
const segment = AWSXRay.getSegment();
|
|
419
|
+
segment.addAnnotation('userId', event.userId);
|
|
420
|
+
|
|
421
|
+
await s3.send(new GetObjectCommand({ Bucket: 'x', Key: 'y' }));
|
|
422
|
+
return { statusCode: 200 };
|
|
423
|
+
};
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### After (autotel-aws)
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import { init } from 'autotel';
|
|
430
|
+
import { wrapHandler, setXRayAnnotation } from 'autotel-aws/lambda';
|
|
431
|
+
import { instrumentSDK } from 'autotel-aws/sdk';
|
|
432
|
+
|
|
433
|
+
init({ service: 'my-service' });
|
|
434
|
+
const s3 = instrumentSDK(new S3Client({}));
|
|
435
|
+
|
|
436
|
+
export const handler = wrapHandler(async (event, context) => {
|
|
437
|
+
setXRayAnnotation('userId', event.userId);
|
|
438
|
+
|
|
439
|
+
await s3.send(new GetObjectCommand({ Bucket: 'x', Key: 'y' }));
|
|
440
|
+
return { statusCode: 200 };
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Key Migration Points
|
|
445
|
+
|
|
446
|
+
| X-Ray SDK | autotel-aws | Notes |
|
|
447
|
+
|-----------|-------------|-------|
|
|
448
|
+
| `AWSXRay.captureAWSv3Client(client)` | `instrumentSDK(client)` or `autoInstrumentAWS()` | Global auto-instrumentation available |
|
|
449
|
+
| `AWSXRay.getSegment().addAnnotation()` | `setXRayAnnotation()` | Same X-Ray filtering capability |
|
|
450
|
+
| `AWSXRay.getSegment().addMetadata()` | `setXRayMetadata()` | Same X-Ray metadata storage |
|
|
451
|
+
| `new AWSXRay.Segment()` | `trace('name', ...)` or `wrapHandler()` | Automatic span management |
|
|
452
|
+
| X-Ray daemon | Any OTLP collector | X-Ray, CloudWatch Agent, or third-party |
|
|
453
|
+
|
|
454
|
+
### Environment Variables
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# For X-Ray via CloudWatch Agent or ADOT Collector
|
|
458
|
+
OTEL_SERVICE_NAME=my-service
|
|
459
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
460
|
+
|
|
461
|
+
# For Honeycomb
|
|
462
|
+
OTEL_SERVICE_NAME=my-service
|
|
463
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io
|
|
464
|
+
OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=YOUR_API_KEY
|
|
465
|
+
|
|
466
|
+
# For Datadog
|
|
467
|
+
OTEL_SERVICE_NAME=my-service
|
|
468
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
469
|
+
DD_API_KEY=YOUR_API_KEY
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## API Reference
|
|
475
|
+
|
|
476
|
+
### Entry Points
|
|
477
|
+
|
|
478
|
+
| Import | Description |
|
|
479
|
+
|--------|-------------|
|
|
480
|
+
| `autotel-aws/lambda` | Lambda handler wrappers + Middy middleware |
|
|
481
|
+
| `autotel-aws/lambda/auto` | Zero-config Lambda auto-init |
|
|
482
|
+
| `autotel-aws/sdk` | AWS SDK v3 instrumentation |
|
|
483
|
+
| `autotel-aws/s3` | S3 semantic helpers |
|
|
484
|
+
| `autotel-aws/dynamodb` | DynamoDB semantic helpers |
|
|
485
|
+
| `autotel-aws/sqs` | SQS helpers + Producer/Consumer |
|
|
486
|
+
| `autotel-aws/sns` | SNS helpers + Publisher |
|
|
487
|
+
| `autotel-aws/kinesis` | Kinesis helpers + Producer/Consumer |
|
|
488
|
+
| `autotel-aws/step-functions` | Step Functions Executor/Worker + context helpers |
|
|
489
|
+
| `autotel-aws/eventbridge` | EventBridge Publisher + context helpers |
|
|
490
|
+
| `autotel-aws/xray` | X-Ray annotation/metadata helpers |
|
|
491
|
+
| `autotel-aws/testing` | Test utilities for Lambda |
|
|
492
|
+
| `autotel-aws/attributes` | Semantic attribute builders |
|
|
493
|
+
|
|
494
|
+
### Semantic Attributes
|
|
495
|
+
|
|
496
|
+
All instrumentation follows [OpenTelemetry AWS Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/cloud-providers/aws-sdk/):
|
|
497
|
+
|
|
498
|
+
**Lambda:**
|
|
499
|
+
- `faas.name`, `faas.version`, `faas.invocation_id`
|
|
500
|
+
- `faas.coldstart`, `faas.trigger`
|
|
501
|
+
- `cloud.provider`, `cloud.region`, `cloud.account.id`
|
|
502
|
+
|
|
503
|
+
**AWS SDK:**
|
|
504
|
+
- `rpc.system` (aws-api), `rpc.service`, `rpc.method`
|
|
505
|
+
- `aws.request_id`, `http.status_code`
|
|
506
|
+
|
|
507
|
+
**Messaging (SQS/SNS/Kinesis):**
|
|
508
|
+
- `messaging.system`, `messaging.destination.name`
|
|
509
|
+
- `messaging.operation`, `messaging.message.id`
|
|
510
|
+
- `messaging.batch.message_count` (for batch operations)
|
|
511
|
+
|
|
512
|
+
**Database (DynamoDB):**
|
|
513
|
+
- `db.system`, `db.operation`, `db.name`
|
|
514
|
+
- `aws.dynamodb.table_names`
|
|
515
|
+
|
|
516
|
+
**Step Functions:**
|
|
517
|
+
- `aws.stepfunctions.state_machine_arn`
|
|
518
|
+
- `aws.stepfunctions.execution_arn`
|
|
519
|
+
- `aws.stepfunctions.activity_arn`
|
|
520
|
+
|
|
521
|
+
**EventBridge:**
|
|
522
|
+
- `aws.eventbridge.event_bus`
|
|
523
|
+
- `aws.eventbridge.source`
|
|
524
|
+
- `aws.eventbridge.detail_type`
|
|
525
|
+
|
|
526
|
+
## Testing
|
|
527
|
+
|
|
528
|
+
Integration tests require LocalStack:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# Start LocalStack
|
|
532
|
+
docker run -d -p 4566:4566 localstack/localstack
|
|
533
|
+
|
|
534
|
+
# Run integration tests
|
|
535
|
+
LOCALSTACK_ENDPOINT=http://localhost:4566 pnpm test:integration
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
## License
|
|
539
|
+
|
|
540
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkQ3DMMQ7K_cjs = require('./chunk-Q3DMMQ7K.cjs');
|
|
4
|
+
require('./chunk-JEQ2X3Z6.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "AWS_ATTRS", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkQ3DMMQ7K_cjs.AWS_ATTRS; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "buildDynamoDBAttributes", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildDynamoDBAttributes; }
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(exports, "buildEventBridgeAttributes", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildEventBridgeAttributes; }
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "buildKinesisAttributes", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildKinesisAttributes; }
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "buildLambdaAttributes", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildLambdaAttributes; }
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports, "buildS3Attributes", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildS3Attributes; }
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports, "buildSDKAttributes", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildSDKAttributes; }
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "buildSNSAttributes", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildSNSAttributes; }
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "buildSQSAttributes", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildSQSAttributes; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "buildStepFunctionsAttributes", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return chunkQ3DMMQ7K_cjs.buildStepFunctionsAttributes; }
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=attributes.cjs.map
|
|
49
|
+
//# sourceMappingURL=attributes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"attributes.cjs"}
|