| name | aio-telemetry-setup |
| description | Interactive setup guide for adding OpenTelemetry observability to Adobe App Builder runtime actions using @adobe/aio-lib-telemetry. Use when the user wants to: (1) add telemetry/observability to an App Builder action, (2) instrument runtime actions with traces, metrics, or logs, (3) configure an observability backend (Grafana, New Relic, Datadog, etc.) for App Builder, (4) set up distributed tracing across actions, (5) add Commerce event/webhook integrations, or (6) understand how to setup @adobe/aio-lib-telemetry. Triggers on: "add telemetry", "instrument my action", "set up tracing", "configure observability", "export traces/metrics/logs", "OpenTelemetry for App Builder".
|
@adobe/aio-lib-telemetry Setup
Interactive setup guide. Gather user requirements through conversation, then generate the right configuration.
Interactive Flow
Ask only for missing inputs: project state, backend, desired signals, any commerceEvents() or commerceWebhooks() integration, whether traces must continue downstream, and whether local development needs Docker or tunneling. If the user already gives these, generate the implementation in one pass.
For fixed-choice questions, use the runtime's selectable-question tool.
Generate incrementally unless the user asks for concrete files.
Setup Steps
Step 1: Install
npm install @adobe/aio-lib-telemetry
Step 2: Enable telemetry
In app.config.yaml, add ENABLE_TELEMETRY: true as input to each action (or at package level for all actions).
runtimeManifest:
packages:
my-package:
actions:
my-action:
function: actions/my-action/index.js
inputs:
ENABLE_TELEMETRY: true
CRITICAL: Without this env var set to true, telemetry silently does nothing. This is the #1 setup mistake.
Step 3: Create telemetry config
Create a telemetry.{ts,js} file.
Minimal config (no backend yet):
import {
defineTelemetryConfig,
getPresetInstrumentations,
getAioRuntimeResource,
} from "@adobe/aio-lib-telemetry";
export const telemetryConfig = defineTelemetryConfig((params, isDev) => {
return {
sdkConfig: {
serviceName: "my-app-builder-app",
instrumentations: getPresetInstrumentations("simple"),
resource: getAioRuntimeResource(),
},
};
});
For backend-specific exporter configuration, read the appropriate reference:
Use params or isDev inside one shared defineTelemetryConfig for environment-specific behavior. Separate config files are rare.
Step 4: Instrument entrypoint
Wrap the action's main function:
import { instrumentEntrypoint } from "@adobe/aio-lib-telemetry";
import { telemetryConfig } from "./telemetry";
function main(params) {
}
const instrumentedMain = instrumentEntrypoint(main, telemetryConfig);
export { instrumentedMain as main };
If using integrations, merge them into the config:
import { commerceEvents } from "@adobe/aio-lib-telemetry/integrations";
const instrumentedMain = instrumentEntrypoint(main, {
...telemetryConfig,
integrations: [commerceEvents()],
});
See references/integrations.md for details.
Use one placement only: shared telemetry config or a specific instrumentEntrypoint.
For Commerce handlers that invoke another action, use commerceEvents() on the handler and forward contextCarrier on the downstream OpenWhisk call. Do not introduce x-telemetry-context or __telemetryContext in new code.
Step 5: Instrument your action (next skill)
With the entrypoint wrapped, your action produces a root span. For deeper instrumentation, use aio-telemetry-instrument.
At this point, setup is complete. The steps below are optional and depend on the user's architecture.
Step 6: Context propagation (optional)
Needed when the runtime action calls other instrumented services — whether other App Builder actions, external APIs, microservices, or any system that supports W3C Trace Context.
Sending side — serialize context into outbound requests:
import { getInstrumentationHelpers } from "@adobe/aio-lib-telemetry";
function callExternalService() {
const { contextCarrier } = getInstrumentationHelpers();
fetch(serviceUrl, { headers: { ...contextCarrier } });
}
For OpenWhisk action-to-action calls, pass the carrier in the params body rather than HTTP headers:
function invokeFulfillment(openwhisk, payload) {
const { contextCarrier } = getInstrumentationHelpers();
return openwhisk.actions.invoke({
name: "fulfill-order",
params: { ...payload, ...contextCarrier },
});
}
Receiving side — depends on the target:
- Another App Builder action: Automatic extraction if it uses
instrumentEntrypoint and you send contextCarrier in normal params or headers. Use propagation.getContextCarrier only for custom carrier shapes.
- External service with OTel: Their SDK handles W3C header extraction automatically
- Custom setup: They need to extract
traceparent/tracestate from headers
For manual propagation, non-HTTP scenarios, or disabling propagation, see references/propagation.md.
Step 7: Local development setup (optional)
If the user wants to see telemetry data during local development, guide them through setting up a local observability stack. See references/local-dev-setup.md for:
- Docker LGTM stack (all-in-one local collector + backends)
- Docker Compose with tunneling for testing deployed actions
isDev conditional configuration patterns
Helpers Available Inside Instrumented Functions
getInstrumentationHelpers() returns:
currentSpan - active span (set attributes, add events)
contextCarrier - pre-serialized W3C headers for propagation
tracer - global tracer for creating custom spans
meter - global meter for creating custom metrics
logger - auto-configured logger correlated to current trace
Throws if called outside an instrumented function.
Troubleshooting Quick Reference
| Symptom | Likely cause |
|---|
| No telemetry at all | ENABLE_TELEMETRY not set to true |
| No spans for inner functions | Used instrument but function never called within an instrumentEntrypoint context. See the aio-telemetry-instrument skill. |
| Traces not linking across services | Context carrier not sent in outbound headers |
| Signals missing occasionally | Container shut down before flush completed (known limitation) |
Enable diagnostics for debugging:
defineTelemetryConfig((params, isDev) => ({
sdkConfig: {
},
diagnostics: { logLevel: "debug" },
}));
For library and OpenTelemetry documentation sources, see references/documentation-sources.md.
References