Skip to content

Commit da43624

Browse files
CEXT-5290: Commerce Automatic Correlation (#53)
* refactor: lookup openwhisk headers for context propagation OOTB * refactor: empty context if headers not found * test: add tests * docs: update docs * refactor: remove redundant attributes * feat: introduce integrations * feat: implement integrations fully * refactor: remove useless generics * refactor: fix type issues and inconsistencies * refactor: fix skip propagation condition and refactor for clarity * refactor: fix instrumentation and config tests relying a lot in mocking * test: add tests * refactor: remove unreachable path * chore: add changesets * refactor: fix jsdoc since tags * docs: documentation for integrations * test: fix rebase failing tests * fix: typo in word Co-authored-by: Daniel Del Carmen <del@adobe.com> * fix: missing comma Co-authored-by: Daniel Del Carmen <del@adobe.com> * docs: rephrase statement Co-authored-by: Daniel Del Carmen <del@adobe.com> * docs: fix typo Co-authored-by: Daniel Del Carmen <del@adobe.com> * refactor: fix wrong attribute assignment, correct typos and add licenses --------- Co-authored-by: Daniel Del Carmen <del@adobe.com>
1 parent fe0ba87 commit da43624

File tree

19 files changed

+1271
-280
lines changed

19 files changed

+1271
-280
lines changed

.changeset/cool-rockets-attack.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@adobe/aio-lib-telemetry": minor
3+
---
4+
5+
Add support for an `integrations` feature to easily integrate with external systems that require a specific configuration. Introduces a `commerceEvents` and a `commerceWebhooks` integrations that are available from `@adobe/aio-lib-telemetry/integrations` which can be used to automatically configure context propagation for requests or events coming from [Adobe Commerce Webhooks](https://developer-stage.adobe.com/commerce/extensibility/webhooks/) or [Adobe Commerce Events](https://developer-stage.adobe.com/commerce/extensibility/events/).

.changeset/quick-buckets-start.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@adobe/aio-lib-telemetry": minor
3+
---
4+
5+
Deprecate custom `x-telemetry-context` header. From now on, if invoking via HTTP requests, propagated context doesn't need to be nested inside that header. Following the W3C Trace Propagation spec, you can send the `traceparent` (and related) headers as normal headers. They will be picked from `__ow_headers` instead. **Note that this only applies for runtime actions invoked via HTTP requests**. When invoked via events you should still use the special `__telemetryContext` variables or specify yourself where to find the context carrier.

docs/usage.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,46 @@ Refer to the API reference documentation of this library for more information ab
124124
| `getPresetInstrumentations` | [API reference](./api-reference/functions/getPresetInstrumentations.md) |
125125
| `getAioRuntimeResource` | [API reference](./api-reference/functions/getAioRuntimeResource.md) |
126126

127+
### Integrations
128+
129+
Since version 1.1.0, this library supports an `integrations` feature that provides preconfigured patches for external systems. Integrations handle complex setup tasks like context propagation, span linking, and sampling decisions automatically.
130+
131+
Available integrations are imported from `@adobe/aio-lib-telemetry/integrations`:
132+
133+
```ts
134+
import { defineTelemetryConfig } from "@adobe/aio-lib-telemetry";
135+
import { commerceEvents } from "@adobe/aio-lib-telemetry/integrations";
136+
137+
const telemetryConfig = defineTelemetryConfig((params, isDev) => {
138+
return {
139+
integrations: [commerceEvents()],
140+
sdkConfig: {
141+
// Your OpenTelemetry SDK configuration
142+
},
143+
};
144+
});
145+
```
146+
147+
Integrations can be applied globally (in your telemetry configuration file), or per-action:
148+
149+
```ts
150+
// Override global integrations for specific actions
151+
export const main = instrumentEntrypoint(
152+
async function webhooksHandler(params) {
153+
// Your webhook handler code
154+
},
155+
{
156+
...telemetryConfig,
157+
integrations: [commerceWebhooks()],
158+
},
159+
);
160+
```
161+
162+
> [!IMPORTANT]
163+
> Integrations are configuration patches applied sequentially. Later integrations may override settings from earlier ones or your base configuration.
164+
165+
For detailed documentation and a complete list of available integrations, see the [integrations guide](./use-cases/integrations/README.md).
166+
127167
## How to Use
128168

129169
This section provides a comprehensive guide for instrumenting App Builder Runtime Actions and demonstrates how to leverage this module's API for streamlined telemetry implementation.
@@ -269,9 +309,13 @@ function callExternalInstrumentedService() {
269309

270310
When invoking an external service instrumented with this module (such as another runtime action), you can include the context carrier in your request or event. Upon receiving the request, the library will automatically attempt to deserialize the context by checking these locations in order:
271311

272-
1. The `x-telemetry-context` header, if you're invoking via HTTP requests
312+
> [!WARNING]
313+
> The `x-telemetry-context` header as a context propagation source is deprecated and will be removed in a future major release. You should always send the context information via HTTP headers following the [W3C Trace Context specification](https://www.w3.org/TR/trace-context/) (if you're instrumenting your code using OpenTelemetry, creating a context carrier following this specification is really simple with the [OpenTelemetry APIs](https://opentelemetry.io/docs/specs/otel/context/api-propagators/#propagators-distribution)).
314+
315+
1. **[DEPRECATED]** The `x-telemetry-context` header, if you're invoking via HTTP requests
273316
2. The `params.__telemetryContext` parameter when invoking runtime actions directly through Openwhisk or Event Ingress
274317
3. The `params.data.__telemetryContext` parameter - a convenience option for cases where parameters are nested under a `data` object
318+
4. **[NEW]** The OpenTelemetry W3C context information automatically extracted from the incoming HTTP request headers (if you're invoking via HTTP requests)
275319

276320
If you don't want this automatic behavior, you can opt-out by providing a `skip: true` option in the `propagation` configuration.
277321

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# Integrations
2+
3+
Since version 1.1.0, this library supports an `integrations` feature that facilitates integration with external systems that require specific telemetry configurations. Integrations are preconfigured patches that automatically handle complex setup tasks, such as context propagation, span linking, and sampling decisions.
4+
5+
> [!IMPORTANT]
6+
> Integrations are configuration patches applied sequentially to your telemetry configuration. Each integration can override or extend existing settings, so the order in which you apply them matters.
7+
8+
- [Integrations](#integrations)
9+
- [What are Integrations?](#what-are-integrations)
10+
- [How to Use Integrations](#how-to-use-integrations)
11+
- [Available Integrations](#available-integrations)
12+
13+
## What are Integrations?
14+
15+
Integrations are functions that return configuration patches for specific external systems. Instead of manually configuring context propagation, span links, and sampling strategies for each integration point, you can use these pre-built integrations to handle the complexity automatically.
16+
17+
Key characteristics:
18+
19+
- **Pre-configured**: Each integration encapsulates best practices for a specific external system
20+
- **Composable**: Can be applied at the global or per-action level
21+
- **Sequential**: Applied in order, with later integrations potentially overriding earlier ones
22+
- **Type-safe**: Full TypeScript support with documented options
23+
24+
## How to Use Integrations
25+
26+
### Global Configuration
27+
28+
Apply integrations to all runtime actions by including them in your global telemetry configuration:
29+
30+
```ts
31+
// telemetry.{js|ts}
32+
import { defineTelemetryConfig } from "@adobe/aio-lib-telemetry";
33+
import { commerceEvents } from "@adobe/aio-lib-telemetry/integrations";
34+
35+
const telemetryConfig = defineTelemetryConfig((params, isDev) => {
36+
return {
37+
sdkConfig: {
38+
// Your OpenTelemetry SDK configuration
39+
},
40+
integrations: [commerceEvents()],
41+
};
42+
});
43+
44+
export { telemetryConfig };
45+
```
46+
47+
### Per-Action Configuration
48+
49+
Override global integrations for specific actions:
50+
51+
> [!WARNING]
52+
> Integrations are applied on top of your base configuration. Some options you set manually may be overridden by the integrations you apply.
53+
54+
```ts
55+
// actions/my-webhook-handler/index.js
56+
import { instrumentEntrypoint } from "@adobe/aio-lib-telemetry";
57+
import { commerceWebhooks } from "@adobe/aio-lib-telemetry/integrations";
58+
import { telemetryConfig } from "../../telemetry";
59+
60+
export const main = instrumentEntrypoint(
61+
async function webhooksHandler(params) {
62+
// Your webhook handler code
63+
},
64+
{
65+
...telemetryConfig,
66+
// This overrides the global integrations
67+
integrations: [commerceWebhooks()],
68+
},
69+
);
70+
```
71+
72+
## Available Integrations
73+
74+
### Adobe Commerce Events
75+
76+
**Import**: `commerceEvents` from `@adobe/aio-lib-telemetry/integrations`
77+
78+
**Use Case**: Runtime actions that receive [Adobe Commerce Events](https://developer.adobe.com/commerce/extensibility/events/)
79+
80+
#### What it Does
81+
82+
Adobe Commerce Events are asynchronous event notifications sent from Commerce to your runtime actions. This integration:
83+
84+
1. **Extracts trace context** from the event's `data._metadata` field
85+
2. **Creates span links** to connect your action's trace with the Commerce event trace
86+
3. **Skips context propagation** since events are asynchronous (not part of the same execution trace)
87+
4. **Adds trace ID attribute** (`commerce.traceid`) for backends that don't fully support span links
88+
89+
#### Usage
90+
91+
```ts
92+
import { commerceEvents } from "@adobe/aio-lib-telemetry/integrations";
93+
94+
const telemetryConfig = defineTelemetryConfig((params, isDev) => {
95+
return {
96+
integrations: [commerceEvents()],
97+
};
98+
});
99+
```
100+
101+
#### Event Structure
102+
103+
Commerce Events include trace context in the `_metadata` field:
104+
105+
```json
106+
{
107+
"data": {
108+
"_metadata": {
109+
"traceparent": "00-traceId-spanId-01",
110+
"tracestate": "..."
111+
}
112+
113+
// Event payload
114+
}
115+
}
116+
```
117+
118+
The integration automatically extracts and processes the trace information.
119+
120+
#### When to Use
121+
122+
- Runtime actions registered as Commerce event subscribers
123+
- Actions that need to correlate their telemetry with Commerce event processing
124+
- Scenarios where you want to link asynchronous event handling to the originating Commerce operation
125+
126+
### Adobe Commerce Webhooks
127+
128+
**Import**: `commerceWebhooks` from `@adobe/aio-lib-telemetry/integrations`
129+
**Use Case**: Runtime actions that receive [Adobe Commerce Webhooks](https://developer.adobe.com/commerce/extensibility/webhooks/)
130+
131+
#### What it Does
132+
133+
Adobe Commerce Webhooks are HTTP requests sent from Commerce to your runtime actions. This integration:
134+
135+
1. **Extracts trace context** from HTTP headers following W3C Trace Context specification
136+
2. **Handles sampling decisions** intelligently based on Commerce's configuration
137+
3. **Creates new traces** when Commerce sends non-sampled context (configurable)
138+
4. **Preserves log correlation** by linking to the Commerce trace even when creating new traces
139+
140+
#### Usage
141+
142+
```ts
143+
import { commerceWebhooks } from "@adobe/aio-lib-telemetry/integrations";
144+
145+
// With default configuration
146+
const telemetryConfig = defineTelemetryConfig((params, isDev) => {
147+
return {
148+
integrations: [commerceWebhooks()],
149+
};
150+
});
151+
152+
// With custom configuration
153+
const telemetryConfig = defineTelemetryConfig((params, isDev) => {
154+
return {
155+
integrations: [
156+
commerceWebhooks({
157+
ensureSampling: false, // Disable automatic sampling override
158+
}),
159+
],
160+
};
161+
});
162+
```
163+
164+
#### Configuration Options
165+
166+
##### `ensureSampling`
167+
168+
**Type**: `boolean`
169+
**Default**: `true`
170+
**Since**: 1.1.0
171+
172+
Controls whether runtime actions should always create traces, regardless of Commerce's subscription configuration.
173+
174+
**Background**: Commerce integrations can be configured with:
175+
176+
- **Trace subscriptions**: Full distributed tracing (sampled traces)
177+
- **Log-only subscriptions**: No tracing, only logs (non-sampled traces)
178+
179+
With log-only subscriptions, Commerce propagates trace context marked as non-sampled (for log correlation). By default, OpenTelemetry's ParentBased sampler would cause your runtime action to also not sample, resulting in no trace data.
180+
181+
**When `true` (default)**:
182+
183+
- Runtime actions create their own sampled trace when Commerce's trace is non-sampled
184+
- Links to Commerce's trace for log correlation
185+
- Inherits Commerce's trace normally when it's sampled
186+
187+
**When `false`**:
188+
189+
- Runtime action tracing depends on Commerce's subscription configuration
190+
- No traces exported when Commerce uses log-only subscriptions
191+
192+
**Example**:
193+
194+
```ts
195+
// Ensure traces are always created (recommended)
196+
commerceWebhooks({ ensureSampling: true });
197+
198+
// Follow Commerce's sampling decision
199+
commerceWebhooks({ ensureSampling: false });
200+
```
201+
202+
#### When to Use
203+
204+
- Runtime actions registered as Commerce webhook endpoints
205+
- Actions that need distributed tracing with Commerce operations
206+
- Scenarios where you want flexible control over trace sampling

package-lock.json

Lines changed: 1 addition & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)