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,279 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkUZEJV2YD_cjs = require('./chunk-UZEJV2YD.cjs');
|
|
4
|
+
var chunkQ3DMMQ7K_cjs = require('./chunk-Q3DMMQ7K.cjs');
|
|
5
|
+
require('./chunk-JEQ2X3Z6.cjs');
|
|
6
|
+
var autotel = require('autotel');
|
|
7
|
+
var api = require('@opentelemetry/api');
|
|
8
|
+
|
|
9
|
+
function injectEventBridgeContext(detail) {
|
|
10
|
+
const carrier = {};
|
|
11
|
+
api.propagation.inject(api.context.active(), carrier);
|
|
12
|
+
if (!carrier.traceparent) {
|
|
13
|
+
return detail;
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
...detail,
|
|
17
|
+
_traceContext: {
|
|
18
|
+
traceparent: carrier.traceparent,
|
|
19
|
+
...carrier.tracestate && { tracestate: carrier.tracestate },
|
|
20
|
+
...carrier.baggage && { baggage: carrier.baggage }
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function extractEventBridgeContext(event) {
|
|
25
|
+
if (!event.detail || typeof event.detail !== "object") {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
const traceContext = event.detail._traceContext;
|
|
29
|
+
if (!traceContext?.traceparent) {
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
const carrier = {
|
|
33
|
+
traceparent: traceContext.traceparent,
|
|
34
|
+
...traceContext.tracestate && { tracestate: traceContext.tracestate },
|
|
35
|
+
...traceContext.baggage && { baggage: traceContext.baggage }
|
|
36
|
+
};
|
|
37
|
+
const extractedContext = api.propagation.extract(api.context.active(), carrier);
|
|
38
|
+
const span = extractedContext.getValue(Symbol.for("OpenTelemetry Context Key SPAN"));
|
|
39
|
+
if (span && typeof span === "object") {
|
|
40
|
+
if ("spanContext" in span && typeof span.spanContext === "function") {
|
|
41
|
+
return span.spanContext();
|
|
42
|
+
}
|
|
43
|
+
if ("traceId" in span && "spanId" in span) {
|
|
44
|
+
return span;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return void 0;
|
|
48
|
+
}
|
|
49
|
+
function stripEventBridgeContext(detail) {
|
|
50
|
+
const { _traceContext: _, ...rest } = detail;
|
|
51
|
+
return rest;
|
|
52
|
+
}
|
|
53
|
+
function traceEventBridge(config) {
|
|
54
|
+
return function wrapper(fn) {
|
|
55
|
+
return autotel.trace(
|
|
56
|
+
`eventbridge.${config.detailType}`,
|
|
57
|
+
(ctx) => async (...args) => {
|
|
58
|
+
ctx.setAttributes(
|
|
59
|
+
chunkQ3DMMQ7K_cjs.buildEventBridgeAttributes({
|
|
60
|
+
eventBus: config.eventBus,
|
|
61
|
+
source: config.source,
|
|
62
|
+
detailType: config.detailType
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
const handler = fn(ctx);
|
|
66
|
+
return handler(...args);
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
var EventBridgePublisher = class {
|
|
72
|
+
client;
|
|
73
|
+
config;
|
|
74
|
+
constructor(client, config) {
|
|
75
|
+
this.client = chunkUZEJV2YD_cjs.wrapSDKClient(client, config.service);
|
|
76
|
+
this.config = {
|
|
77
|
+
eventBusName: "default",
|
|
78
|
+
injectTraceContext: true,
|
|
79
|
+
...config
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Publish a single event to EventBridge
|
|
84
|
+
*
|
|
85
|
+
* @param event - Event to publish
|
|
86
|
+
* @returns Promise with event ID (if successful)
|
|
87
|
+
*/
|
|
88
|
+
async putEvent(event) {
|
|
89
|
+
return autotel.trace(`eventbridge.PutEvents`, async (ctx) => {
|
|
90
|
+
ctx.setAttributes(
|
|
91
|
+
chunkQ3DMMQ7K_cjs.buildEventBridgeAttributes({
|
|
92
|
+
eventBus: this.config.eventBusName || "default",
|
|
93
|
+
source: this.config.source,
|
|
94
|
+
detailType: event.detailType
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
const detail = this.config.injectTraceContext ? injectEventBridgeContext(event.detail) : event.detail;
|
|
98
|
+
const entry = {
|
|
99
|
+
EventBusName: this.config.eventBusName,
|
|
100
|
+
Source: this.config.source,
|
|
101
|
+
DetailType: event.detailType,
|
|
102
|
+
Detail: JSON.stringify(detail),
|
|
103
|
+
Resources: event.resources,
|
|
104
|
+
Time: event.time,
|
|
105
|
+
TraceHeader: event.traceHeader
|
|
106
|
+
};
|
|
107
|
+
try {
|
|
108
|
+
const { PutEventsCommand } = await import('@aws-sdk/client-eventbridge');
|
|
109
|
+
const result = await this.client.send(
|
|
110
|
+
new PutEventsCommand({ Entries: [entry] })
|
|
111
|
+
);
|
|
112
|
+
const firstEntry = result.Entries?.[0];
|
|
113
|
+
if (firstEntry?.EventId) {
|
|
114
|
+
ctx.setAttribute("aws.eventbridge.event_id", firstEntry.EventId);
|
|
115
|
+
}
|
|
116
|
+
if (result.FailedEntryCount && result.FailedEntryCount > 0) {
|
|
117
|
+
ctx.setStatus({
|
|
118
|
+
code: api.SpanStatusCode.ERROR,
|
|
119
|
+
message: firstEntry?.ErrorMessage || "PutEvents failed"
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
ctx.setStatus({ code: api.SpanStatusCode.OK });
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
eventId: firstEntry?.EventId,
|
|
126
|
+
failedEntryCount: result.FailedEntryCount
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
ctx.setStatus({
|
|
130
|
+
code: api.SpanStatusCode.ERROR,
|
|
131
|
+
message: error instanceof Error ? error.message : "PutEvents failed"
|
|
132
|
+
});
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Publish multiple events in a batch
|
|
139
|
+
*
|
|
140
|
+
* @param events - Array of events to publish (max 10 per API call)
|
|
141
|
+
* @returns Promise with successful and failed event results
|
|
142
|
+
*/
|
|
143
|
+
async putEvents(events) {
|
|
144
|
+
return autotel.trace(`eventbridge.PutEvents.batch`, async (ctx) => {
|
|
145
|
+
ctx.setAttributes(
|
|
146
|
+
chunkQ3DMMQ7K_cjs.buildEventBridgeAttributes({
|
|
147
|
+
eventBus: this.config.eventBusName || "default",
|
|
148
|
+
source: this.config.source,
|
|
149
|
+
detailType: "batch"
|
|
150
|
+
})
|
|
151
|
+
);
|
|
152
|
+
ctx.setAttribute("aws.eventbridge.batch_size", events.length);
|
|
153
|
+
const entries = events.map((event) => {
|
|
154
|
+
const detail = this.config.injectTraceContext ? injectEventBridgeContext(event.detail) : event.detail;
|
|
155
|
+
return {
|
|
156
|
+
EventBusName: this.config.eventBusName,
|
|
157
|
+
Source: this.config.source,
|
|
158
|
+
DetailType: event.detailType,
|
|
159
|
+
Detail: JSON.stringify(detail),
|
|
160
|
+
Resources: event.resources,
|
|
161
|
+
Time: event.time,
|
|
162
|
+
TraceHeader: event.traceHeader
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
try {
|
|
166
|
+
const { PutEventsCommand } = await import('@aws-sdk/client-eventbridge');
|
|
167
|
+
const result = await this.client.send(
|
|
168
|
+
new PutEventsCommand({ Entries: entries })
|
|
169
|
+
);
|
|
170
|
+
const successful = [];
|
|
171
|
+
const failed = [];
|
|
172
|
+
if (result.Entries) {
|
|
173
|
+
for (const [index, entry] of result.Entries.entries()) {
|
|
174
|
+
const typedEntry = entry;
|
|
175
|
+
if (typedEntry.EventId) {
|
|
176
|
+
successful.push({
|
|
177
|
+
eventId: typedEntry.EventId,
|
|
178
|
+
detailType: events[index].detailType
|
|
179
|
+
});
|
|
180
|
+
} else {
|
|
181
|
+
failed.push({
|
|
182
|
+
errorCode: typedEntry.ErrorCode,
|
|
183
|
+
errorMessage: typedEntry.ErrorMessage,
|
|
184
|
+
detailType: events[index].detailType
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
ctx.setAttribute("aws.eventbridge.successful_count", successful.length);
|
|
190
|
+
ctx.setAttribute("aws.eventbridge.failed_count", failed.length);
|
|
191
|
+
if (failed.length > 0) {
|
|
192
|
+
ctx.setStatus({
|
|
193
|
+
code: api.SpanStatusCode.ERROR,
|
|
194
|
+
message: `${failed.length} events failed`
|
|
195
|
+
});
|
|
196
|
+
} else {
|
|
197
|
+
ctx.setStatus({ code: api.SpanStatusCode.OK });
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
successful,
|
|
201
|
+
failed,
|
|
202
|
+
failedEntryCount: result.FailedEntryCount || 0
|
|
203
|
+
};
|
|
204
|
+
} catch (error) {
|
|
205
|
+
ctx.setStatus({
|
|
206
|
+
code: api.SpanStatusCode.ERROR,
|
|
207
|
+
message: error instanceof Error ? error.message : "PutEvents batch failed"
|
|
208
|
+
});
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Publish event with override source
|
|
215
|
+
*
|
|
216
|
+
* Use when you need to publish to a different source than the default.
|
|
217
|
+
*
|
|
218
|
+
* @param event - Event with source override
|
|
219
|
+
* @returns Promise with event ID
|
|
220
|
+
*/
|
|
221
|
+
async putEventWithSource(event) {
|
|
222
|
+
return autotel.trace(`eventbridge.PutEvents`, async (ctx) => {
|
|
223
|
+
ctx.setAttributes(
|
|
224
|
+
chunkQ3DMMQ7K_cjs.buildEventBridgeAttributes({
|
|
225
|
+
eventBus: this.config.eventBusName || "default",
|
|
226
|
+
source: event.source,
|
|
227
|
+
detailType: event.detailType
|
|
228
|
+
})
|
|
229
|
+
);
|
|
230
|
+
const detail = this.config.injectTraceContext ? injectEventBridgeContext(event.detail) : event.detail;
|
|
231
|
+
const entry = {
|
|
232
|
+
EventBusName: this.config.eventBusName,
|
|
233
|
+
Source: event.source,
|
|
234
|
+
// Use override source
|
|
235
|
+
DetailType: event.detailType,
|
|
236
|
+
Detail: JSON.stringify(detail),
|
|
237
|
+
Resources: event.resources,
|
|
238
|
+
Time: event.time,
|
|
239
|
+
TraceHeader: event.traceHeader
|
|
240
|
+
};
|
|
241
|
+
try {
|
|
242
|
+
const { PutEventsCommand } = await import('@aws-sdk/client-eventbridge');
|
|
243
|
+
const result = await this.client.send(
|
|
244
|
+
new PutEventsCommand({ Entries: [entry] })
|
|
245
|
+
);
|
|
246
|
+
const firstEntry = result.Entries?.[0];
|
|
247
|
+
if (firstEntry?.EventId) {
|
|
248
|
+
ctx.setAttribute("aws.eventbridge.event_id", firstEntry.EventId);
|
|
249
|
+
}
|
|
250
|
+
if (result.FailedEntryCount && result.FailedEntryCount > 0) {
|
|
251
|
+
ctx.setStatus({
|
|
252
|
+
code: api.SpanStatusCode.ERROR,
|
|
253
|
+
message: firstEntry?.ErrorMessage || "PutEvents failed"
|
|
254
|
+
});
|
|
255
|
+
} else {
|
|
256
|
+
ctx.setStatus({ code: api.SpanStatusCode.OK });
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
eventId: firstEntry?.EventId,
|
|
260
|
+
failedEntryCount: result.FailedEntryCount
|
|
261
|
+
};
|
|
262
|
+
} catch (error) {
|
|
263
|
+
ctx.setStatus({
|
|
264
|
+
code: api.SpanStatusCode.ERROR,
|
|
265
|
+
message: error instanceof Error ? error.message : "PutEvents failed"
|
|
266
|
+
});
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
exports.EventBridgePublisher = EventBridgePublisher;
|
|
274
|
+
exports.extractEventBridgeContext = extractEventBridgeContext;
|
|
275
|
+
exports.injectEventBridgeContext = injectEventBridgeContext;
|
|
276
|
+
exports.stripEventBridgeContext = stripEventBridgeContext;
|
|
277
|
+
exports.traceEventBridge = traceEventBridge;
|
|
278
|
+
//# sourceMappingURL=eventbridge.cjs.map
|
|
279
|
+
//# sourceMappingURL=eventbridge.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/eventbridge/index.ts"],"names":["propagation","context","trace","buildEventBridgeAttributes","wrapSDKClient","SpanStatusCode"],"mappings":"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","file":"eventbridge.cjs","sourcesContent":["/**\n * EventBridge instrumentation\n *\n * Provides helpers for tracing Amazon EventBridge operations with\n * automatic W3C Trace Context propagation for distributed tracing.\n *\n * @example Publish events with trace context\n * ```typescript\n * import { EventBridgePublisher } from 'autotel-aws/eventbridge';\n * import { EventBridgeClient } from '@aws-sdk/client-eventbridge';\n *\n * const client = new EventBridgeClient({ region: 'us-east-1' });\n * const publisher = new EventBridgePublisher(client, {\n * eventBusName: 'my-event-bus',\n * source: 'com.myapp.orders'\n * });\n *\n * // Publish with automatic trace context injection\n * await publisher.putEvent({\n * detailType: 'OrderCreated',\n * detail: { orderId: '123', customerId: 'abc' }\n * });\n * ```\n *\n * @example Extract context in Lambda triggered by EventBridge\n * ```typescript\n * import { extractEventBridgeContext } from 'autotel-aws/eventbridge';\n * import { wrapHandler } from 'autotel-aws/lambda';\n *\n * export const handler = wrapHandler(async (event) => {\n * // Extract trace context from EventBridge event detail\n * const parentContext = extractEventBridgeContext(event);\n *\n * // Process the event\n * const { orderId, customerId } = event.detail;\n * await processOrder(orderId, customerId);\n *\n * return { statusCode: 200 };\n * });\n * ```\n *\n * @example Trace EventBridge operations with helper\n * ```typescript\n * import { traceEventBridge } from 'autotel-aws/eventbridge';\n *\n * export const publishOrderEvent = traceEventBridge({\n * eventBus: 'orders-bus',\n * source: 'order-service',\n * detailType: 'OrderCreated'\n * })(ctx => async (order: Order) => {\n * ctx.setAttribute('order.id', order.id);\n * await eventBridge.send(new PutEventsCommand({\n * Entries: [{\n * EventBusName: 'orders-bus',\n * Source: 'order-service',\n * DetailType: 'OrderCreated',\n * Detail: JSON.stringify(injectEventBridgeContext(order))\n * }]\n * }));\n * });\n * ```\n */\n\nimport { trace, type TraceContext } from 'autotel';\nimport { context, propagation, SpanStatusCode } from '@opentelemetry/api';\nimport type { SpanContext } from '@opentelemetry/api';\nimport { buildEventBridgeAttributes } from '../attributes';\nimport { wrapSDKClient } from '../common/sdk-wrapper';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * EventBridge operation configuration for traceEventBridge helper\n */\nexport interface TraceEventBridgeConfig {\n /**\n * Event bus name or ARN\n */\n eventBus: string;\n\n /**\n * Event source (e.g., 'com.myapp.orders')\n */\n source: string;\n\n /**\n * Event detail type (e.g., 'OrderCreated')\n */\n detailType: string;\n}\n\n/**\n * Configuration for EventBridgePublisher\n */\nexport interface EventBridgePublisherConfig {\n /**\n * Event bus name or ARN\n * @default 'default' (the account's default event bus)\n */\n eventBusName?: string;\n\n /**\n * Event source (e.g., 'com.myapp.orders')\n */\n source: string;\n\n /**\n * Inject W3C Trace Context into event detail\n * @default true\n */\n injectTraceContext?: boolean;\n\n /**\n * Optional service name for tracing\n */\n service?: string;\n}\n\n/**\n * Event to publish via EventBridgePublisher\n */\nexport interface EventBridgeEvent<T = Record<string, unknown>> {\n /**\n * Event detail type (e.g., 'OrderCreated', 'UserSignedUp')\n */\n detailType: string;\n\n /**\n * Event detail (the actual payload)\n */\n detail: T;\n\n /**\n * Optional resources ARNs associated with the event\n */\n resources?: string[];\n\n /**\n * Optional time for the event (defaults to current time)\n */\n time?: Date;\n\n /**\n * Optional trace header (for X-Ray integration)\n */\n traceHeader?: string;\n}\n\n/**\n * Trace context fields injected into EventBridge detail\n */\ninterface TraceContextFields {\n _traceContext?: {\n traceparent: string;\n tracestate?: string;\n baggage?: string;\n };\n}\n\n/**\n * EventBridge event structure (Lambda event format)\n */\nexport interface EventBridgeLambdaEvent {\n version?: string;\n id?: string;\n 'detail-type'?: string;\n source?: string;\n account?: string;\n time?: string;\n region?: string;\n resources?: string[];\n detail?: Record<string, unknown> & TraceContextFields;\n}\n\n// ============================================================================\n// Context Propagation Helpers\n// ============================================================================\n\n/**\n * Inject W3C Trace Context into EventBridge event detail\n *\n * Adds `_traceContext` field with traceparent, tracestate, and baggage.\n * This enables distributed tracing from the publisher to all event consumers.\n *\n * @param detail - The event detail object\n * @returns Detail with trace context injected\n *\n * @example\n * ```typescript\n * const detail = { orderId: '123', status: 'created' };\n * const detailWithContext = injectEventBridgeContext(detail);\n * // { orderId: '123', status: 'created', _traceContext: { traceparent: '...' } }\n *\n * await eventBridge.send(new PutEventsCommand({\n * Entries: [{\n * EventBusName: 'my-bus',\n * Source: 'my-app',\n * DetailType: 'OrderCreated',\n * Detail: JSON.stringify(detailWithContext)\n * }]\n * }));\n * ```\n */\nexport function injectEventBridgeContext<T extends Record<string, unknown>>(\n detail: T,\n): T & TraceContextFields {\n const carrier: Record<string, string> = {};\n propagation.inject(context.active(), carrier);\n\n if (!carrier.traceparent) {\n return detail;\n }\n\n return {\n ...detail,\n _traceContext: {\n traceparent: carrier.traceparent,\n ...(carrier.tracestate && { tracestate: carrier.tracestate }),\n ...(carrier.baggage && { baggage: carrier.baggage }),\n },\n };\n}\n\n/**\n * Extract W3C Trace Context from EventBridge Lambda event\n *\n * Extracts the `_traceContext` field from the event detail.\n * Works with the Lambda event format from EventBridge rules.\n *\n * @param event - EventBridge Lambda event\n * @returns SpanContext if trace context was found, undefined otherwise\n *\n * @example\n * ```typescript\n * // In a Lambda triggered by EventBridge\n * export const handler = async (event: EventBridgeLambdaEvent) => {\n * const parentContext = extractEventBridgeContext(event);\n * // Use parentContext to link traces...\n *\n * // Access detail without trace context\n * const cleanDetail = stripEventBridgeContext(event.detail);\n * };\n * ```\n */\nexport function extractEventBridgeContext(\n event: EventBridgeLambdaEvent,\n): SpanContext | undefined {\n if (!event.detail || typeof event.detail !== 'object') {\n return undefined;\n }\n\n const traceContext = event.detail._traceContext;\n if (!traceContext?.traceparent) {\n return undefined;\n }\n\n // Use W3C Trace Context propagator to extract\n const carrier: Record<string, string> = {\n traceparent: traceContext.traceparent,\n ...(traceContext.tracestate && { tracestate: traceContext.tracestate }),\n ...(traceContext.baggage && { baggage: traceContext.baggage }),\n };\n\n const extractedContext = propagation.extract(context.active(), carrier);\n const span = extractedContext.getValue(Symbol.for('OpenTelemetry Context Key SPAN'));\n\n // Handle both Span and SpanContext\n if (span && typeof span === 'object') {\n if ('spanContext' in span && typeof span.spanContext === 'function') {\n return span.spanContext() as SpanContext;\n }\n // Might already be a SpanContext\n if ('traceId' in span && 'spanId' in span) {\n return span as SpanContext;\n }\n }\n\n return undefined;\n}\n\n/**\n * Strip trace context fields from EventBridge event detail\n *\n * Returns the detail without `_traceContext` field for cleaner processing.\n *\n * @param detail - EventBridge event detail with optional trace context\n * @returns Detail without trace context fields\n *\n * @example\n * ```typescript\n * const detail = { orderId: '123', _traceContext: { ... } };\n * const cleanDetail = stripEventBridgeContext(detail);\n * // { orderId: '123' }\n * ```\n */\nexport function stripEventBridgeContext<T extends Record<string, unknown>>(\n detail: T,\n): Omit<T, '_traceContext'> {\n const { _traceContext: _, ...rest } = detail as T & TraceContextFields;\n return rest as Omit<T, '_traceContext'>;\n}\n\n// ============================================================================\n// Trace Helper (Original API)\n// ============================================================================\n\n/**\n * Trace EventBridge operations with semantic attributes\n *\n * Creates a traced function that automatically sets EventBridge attributes.\n *\n * @param config - EventBridge operation configuration\n * @returns A higher-order function that wraps your EventBridge operation with tracing\n *\n * @remarks\n * Semantic attributes set automatically:\n * - `aws.eventbridge.event_bus` - Event bus name\n * - `aws.eventbridge.source` - Event source\n * - `aws.eventbridge.detail_type` - Event detail type\n *\n * @example\n * ```typescript\n * export const publishOrderEvent = traceEventBridge({\n * eventBus: 'orders-bus',\n * source: 'order-service',\n * detailType: 'OrderCreated'\n * })(ctx => async (order: Order) => {\n * ctx.setAttribute('order.id', order.id);\n *\n * const detail = injectEventBridgeContext(order);\n * await eventBridge.send(new PutEventsCommand({\n * Entries: [{\n * EventBusName: 'orders-bus',\n * Source: 'order-service',\n * DetailType: 'OrderCreated',\n * Detail: JSON.stringify(detail)\n * }]\n * }));\n * });\n * ```\n */\nexport function traceEventBridge(config: TraceEventBridgeConfig) {\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 `eventbridge.${config.detailType}`,\n (ctx: TraceContext) =>\n async (...args: TArgs): Promise<TReturn> => {\n // Set EventBridge semantic attributes\n ctx.setAttributes(\n buildEventBridgeAttributes({\n eventBus: config.eventBus,\n source: config.source,\n detailType: config.detailType,\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\n// ============================================================================\n// EventBridgePublisher Class\n// ============================================================================\n\n/**\n * EventBridge Publisher with automatic trace context injection\n *\n * Wraps an EventBridge client to automatically:\n * - Create spans for PutEvents operations\n * - Inject W3C Trace Context into event detail\n * - Set proper semantic attributes\n *\n * @example Basic usage\n * ```typescript\n * import { EventBridgePublisher } from 'autotel-aws/eventbridge';\n * import { EventBridgeClient } from '@aws-sdk/client-eventbridge';\n *\n * const client = new EventBridgeClient({ region: 'us-east-1' });\n * const publisher = new EventBridgePublisher(client, {\n * eventBusName: 'my-event-bus',\n * source: 'com.myapp.orders'\n * });\n *\n * // Publish single event\n * const result = await publisher.putEvent({\n * detailType: 'OrderCreated',\n * detail: { orderId: '123', customerId: 'abc' }\n * });\n * console.log('Event ID:', result.eventId);\n * ```\n *\n * @example Batch publish multiple events\n * ```typescript\n * const results = await publisher.putEvents([\n * { detailType: 'OrderCreated', detail: { orderId: '1' } },\n * { detailType: 'OrderCreated', detail: { orderId: '2' } },\n * { detailType: 'OrderCreated', detail: { orderId: '3' } }\n * ]);\n *\n * console.log(`Published ${results.successful.length} events`);\n * console.log(`Failed ${results.failed.length} events`);\n * ```\n *\n * @example Multiple sources\n * ```typescript\n * // Create publishers for different event sources\n * const ordersPublisher = new EventBridgePublisher(client, {\n * source: 'com.myapp.orders'\n * });\n *\n * const usersPublisher = new EventBridgePublisher(client, {\n * source: 'com.myapp.users'\n * });\n *\n * await ordersPublisher.putEvent({ detailType: 'OrderCreated', detail: {...} });\n * await usersPublisher.putEvent({ detailType: 'UserSignedUp', detail: {...} });\n * ```\n */\nexport class EventBridgePublisher<\n \n TClient extends { send: (command: any) => Promise<any> } = any,\n> {\n private client: TClient;\n private config: Required<Pick<EventBridgePublisherConfig, 'source'>> &\n EventBridgePublisherConfig;\n\n constructor(client: TClient, config: EventBridgePublisherConfig) {\n this.client = wrapSDKClient(client as any, config.service) as TClient;\n this.config = {\n eventBusName: 'default',\n injectTraceContext: true,\n ...config,\n };\n }\n\n /**\n * Publish a single event to EventBridge\n *\n * @param event - Event to publish\n * @returns Promise with event ID (if successful)\n */\n async putEvent<T extends Record<string, unknown>>(\n event: EventBridgeEvent<T>,\n ): Promise<{\n eventId?: string;\n failedEntryCount?: number;\n }> {\n return trace(`eventbridge.PutEvents`, async (ctx: TraceContext) => {\n ctx.setAttributes(\n buildEventBridgeAttributes({\n eventBus: this.config.eventBusName || 'default',\n source: this.config.source,\n detailType: event.detailType,\n }),\n );\n\n // Optionally inject trace context\n const detail = this.config.injectTraceContext\n ? injectEventBridgeContext(event.detail)\n : event.detail;\n\n const entry = {\n EventBusName: this.config.eventBusName,\n Source: this.config.source,\n DetailType: event.detailType,\n Detail: JSON.stringify(detail),\n Resources: event.resources,\n Time: event.time,\n TraceHeader: event.traceHeader,\n };\n\n try {\n const { PutEventsCommand } = await import('@aws-sdk/client-eventbridge');\n const result = await this.client.send(\n new PutEventsCommand({ Entries: [entry] }),\n );\n\n const firstEntry = result.Entries?.[0];\n if (firstEntry?.EventId) {\n ctx.setAttribute('aws.eventbridge.event_id', firstEntry.EventId);\n }\n\n if (result.FailedEntryCount && result.FailedEntryCount > 0) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: firstEntry?.ErrorMessage || 'PutEvents failed',\n });\n } else {\n ctx.setStatus({ code: SpanStatusCode.OK });\n }\n\n return {\n eventId: firstEntry?.EventId,\n failedEntryCount: result.FailedEntryCount,\n };\n } catch (error) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : 'PutEvents failed',\n });\n throw error;\n }\n });\n }\n\n /**\n * Publish multiple events in a batch\n *\n * @param events - Array of events to publish (max 10 per API call)\n * @returns Promise with successful and failed event results\n */\n async putEvents<T extends Record<string, unknown>>(\n events: EventBridgeEvent<T>[],\n ): Promise<{\n successful: Array<{ eventId?: string; detailType: string }>;\n failed: Array<{ errorCode?: string; errorMessage?: string; detailType: string }>;\n failedEntryCount: number;\n }> {\n return trace(`eventbridge.PutEvents.batch`, async (ctx: TraceContext) => {\n ctx.setAttributes(\n buildEventBridgeAttributes({\n eventBus: this.config.eventBusName || 'default',\n source: this.config.source,\n detailType: 'batch',\n }),\n );\n ctx.setAttribute('aws.eventbridge.batch_size', events.length);\n\n const entries = events.map((event) => {\n const detail = this.config.injectTraceContext\n ? injectEventBridgeContext(event.detail)\n : event.detail;\n\n return {\n EventBusName: this.config.eventBusName,\n Source: this.config.source,\n DetailType: event.detailType,\n Detail: JSON.stringify(detail),\n Resources: event.resources,\n Time: event.time,\n TraceHeader: event.traceHeader,\n };\n });\n\n try {\n const { PutEventsCommand } = await import('@aws-sdk/client-eventbridge');\n const result = await this.client.send(\n new PutEventsCommand({ Entries: entries }),\n );\n\n const successful: Array<{ eventId?: string; detailType: string }> = [];\n const failed: Array<{ errorCode?: string; errorMessage?: string; detailType: string }> =\n [];\n\n if (result.Entries) {\n for (const [index, entry] of result.Entries.entries()) {\n const typedEntry = entry as {\n EventId?: string;\n ErrorCode?: string;\n ErrorMessage?: string;\n };\n if (typedEntry.EventId) {\n successful.push({\n eventId: typedEntry.EventId,\n detailType: events[index].detailType,\n });\n } else {\n failed.push({\n errorCode: typedEntry.ErrorCode,\n errorMessage: typedEntry.ErrorMessage,\n detailType: events[index].detailType,\n });\n }\n }\n }\n\n ctx.setAttribute('aws.eventbridge.successful_count', successful.length);\n ctx.setAttribute('aws.eventbridge.failed_count', failed.length);\n\n if (failed.length > 0) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: `${failed.length} events failed`,\n });\n } else {\n ctx.setStatus({ code: SpanStatusCode.OK });\n }\n\n return {\n successful,\n failed,\n failedEntryCount: result.FailedEntryCount || 0,\n };\n } catch (error) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : 'PutEvents batch failed',\n });\n throw error;\n }\n });\n }\n\n /**\n * Publish event with override source\n *\n * Use when you need to publish to a different source than the default.\n *\n * @param event - Event with source override\n * @returns Promise with event ID\n */\n async putEventWithSource<T extends Record<string, unknown>>(\n event: EventBridgeEvent<T> & { source: string },\n ): Promise<{\n eventId?: string;\n failedEntryCount?: number;\n }> {\n return trace(`eventbridge.PutEvents`, async (ctx: TraceContext) => {\n ctx.setAttributes(\n buildEventBridgeAttributes({\n eventBus: this.config.eventBusName || 'default',\n source: event.source,\n detailType: event.detailType,\n }),\n );\n\n // Optionally inject trace context\n const detail = this.config.injectTraceContext\n ? injectEventBridgeContext(event.detail)\n : event.detail;\n\n const entry = {\n EventBusName: this.config.eventBusName,\n Source: event.source, // Use override source\n DetailType: event.detailType,\n Detail: JSON.stringify(detail),\n Resources: event.resources,\n Time: event.time,\n TraceHeader: event.traceHeader,\n };\n\n try {\n const { PutEventsCommand } = await import('@aws-sdk/client-eventbridge');\n const result = await this.client.send(\n new PutEventsCommand({ Entries: [entry] }),\n );\n\n const firstEntry = result.Entries?.[0];\n if (firstEntry?.EventId) {\n ctx.setAttribute('aws.eventbridge.event_id', firstEntry.EventId);\n }\n\n if (result.FailedEntryCount && result.FailedEntryCount > 0) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: firstEntry?.ErrorMessage || 'PutEvents failed',\n });\n } else {\n ctx.setStatus({ code: SpanStatusCode.OK });\n }\n\n return {\n eventId: firstEntry?.EventId,\n failedEntryCount: result.FailedEntryCount,\n };\n } catch (error) {\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : 'PutEvents failed',\n });\n throw error;\n }\n });\n }\n}\n"]}
|