@odigos/aws-cdk 0.0.12 → 0.0.14

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/.jsii CHANGED
@@ -3826,7 +3826,7 @@
3826
3826
  },
3827
3827
  "name": "@odigos/aws-cdk",
3828
3828
  "readme": {
3829
- "markdown": "# Odigos CDK constructs for AWS Lambda\n\nInstrument AWS Lambda functions with the Odigos OpenTelemetry layer, from your own CDK app.\n\n```bash\nnpm install @odigos/aws-cdk # TypeScript / JavaScript\npip install odigos-aws-cdk # Python\n```\n\n```ts\nimport { OdigosLambdaInstrumentation } from '@odigos/aws-cdk';\n\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [apiFn, workerFn],\n});\n```\n\n```python\nfrom odigos_aws_cdk import OdigosLambdaInstrumentation\n\nOdigosLambdaInstrumentation(self, \"Odigos\",\n destination={\"endpoint\": \"otlp.example.com:4317\"},\n functions=[api_fn, worker_fn],\n)\n```\n\nThat attaches the layer for each function's language and architecture, sets the exec wrapper that loads\nthe OpenTelemetry SDK, and hands the in-Lambda collector its whole configuration.\n\n## How the telemetry actually leaves the function\n\nYour function's SDK **does not** export to your destination. It exports to an OpenTelemetry collector\nrunning inside the same Lambda sandbox, on localhost. The collector forwards to your destination *after*\nthe handler has already returned its response.\n\nThat indirection is the whole point. A slow or unreachable destination costs billed duration, not caller\nlatency — and the collector's `decouple` processor is what holds the sandbox open until the export queue\ndrains, so a low-traffic function does not lose its telemetry to the freeze.\n\nConsequently `OTEL_EXPORTER_OTLP_ENDPOINT` is deliberately never set. If you set it yourself you put the\nexport back on the invocation's critical path.\n\n## Endpoint grammar\n\n`endpoint` is OTLP/**gRPC** as bare `host:port` (conventionally 4317). `httpEndpoint` is OTLP/**HTTP** as a\nscheme-qualified URL (conventionally 4318). Exactly one. They select different collector exporters with\ndifferent endpoint grammars, so a scheme in `endpoint` — or its absence in `httpEndpoint` — throws at synth\nrather than producing a collector that starts and silently delivers nothing. A gRPC endpoint on port 4318\n(or an HTTP one on 4317) is the likeliest version of that mistake, and is reported as a synth warning.\n\n## Choosing a layer source\n\n```ts\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [fn],\n layerSource: OdigosLayerSource.IN_ACCOUNT,\n});\n```\n\n| | `ODIGOS_PUBLIC` (default) | `IN_ACCOUNT` |\n|---|---|---|\n| What it synthesizes | a layer ARN | an `AWS::Serverless::Application` (nested stack) per language/arch |\n| Layer owner | the Odigos AWS account | **your** account, created by your stack |\n| Resolution | synth time, from a table baked into this package | deploy time, from the Serverless Application Repository |\n| Environment-agnostic stacks | not supported — needs a concrete region | works |\n| Deploy speed | unchanged | slower on first deploy |\n\nBoth install identical bytes. `IN_ACCOUNT` exists for organisations whose policy forbids attaching a\nLambda layer owned by another AWS account. It needs the deploying principal to be allowed\n`serverlessrepo:CreateCloudFormationTemplate` and `serverlessrepo:GetApplication`.\n\nIf you mirror the layer somewhere yourself, pass `layerVersion` and neither path is used.\n\n## Versioning\n\n**The package version is the layer version.** `@odigos/aws-cdk@0.2.0` resolves to the layer built and\npublished by Odigos release `v0.2.0`, and pins the SAR application to semantic version `0.2.0` — which is\nimmutable, so it means the same bytes forever.\n\nNothing resolves at deploy time in the default path, so upgrading the layer is `npm update` and a\n`cdk diff` that shows the change. An instrumentation layer moving on its own, under a deployment that\nchanged nothing, is not a property you want.\n\n## Handler mode vs. web-server mode\n\n`OdigosInstrumentationMode.HANDLER` (the default) is for a normal Lambda handler. It sets\n`AWS_LAMBDA_EXEC_WRAPPER`.\n\n`OdigosInstrumentationMode.WEB_SERVER` is for a function running a web server behind the\n[AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter). The adapter owns the exec\nwrapper, so this mode does not touch it and loads instrumentation through the language's own loader\nvariable instead.\n\n```ts\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [webFn],\n mode: OdigosInstrumentationMode.WEB_SERVER,\n // NODE_OPTIONS the function already needs — ours is appended, not substituted.\n existingLoaderValue: '--max-old-space-size=2048',\n});\n```\n\nThere is no auto-detection, deliberately. Detecting the adapter means inspecting the function's other\nlayers, which at synth time are frequently unresolved tokens; a detector that was right most of the time\nwould silently break the functions it got wrong. **Applying `HANDLER` to a web-adapter function\noverwrites the adapter's wrapper and the function stops serving.**\n\n`existingLoaderValue` has to be passed explicitly because CDK's `lambda.Function` exposes no way to read\nback an environment variable set elsewhere in your app. Omit it and the loader variable is set to the\nOdigos value alone — for `NODE_OPTIONS` that can mean losing a flag your app needs to boot.\n\nRuby has no verified web-server loader and is rejected at synth in this mode.\n\n## Java handler interfaces\n\nThe Java layer ships four wrapper scripts, one per handler interface, and this is a correctness switch\nrather than a detail level:\n\n```ts\njavaHandlerDistro: OdigosJavaHandlerDistro.OTEL_STREAM_HANDLER\n```\n\n| Distro | For |\n|---|---|\n| `OTEL_HANDLER` (default) | `RequestHandler` |\n| `OTEL_PROXY_HANDLER` | API Gateway proxy events (enriched) |\n| `OTEL_SQS_HANDLER` | SQS events (enriched) |\n| `OTEL_STREAM_HANDLER` | `RequestStreamHandler` |\n\n`OTEL_HANDLER` installs a `RequestHandler` implementation. A `RequestStreamHandler` function has a\ndifferent signature entirely, so wrapping it with the default **breaks the invocation** — it does not\nmerely produce thinner spans.\n\n## Signals\n\n**Traces only, by default.** Metrics and logs are opt-in:\n\n```ts\ndestination: {\n endpoint: 'otlp.example.com:4317',\n metrics: true, // off unless you ask\n logs: true, // off unless you ask\n}\n```\n\nThey are opt-in because the cost of a signal the destination does not implement falls on the function:\nevery batch is refused and the in-Lambda collector retries it on an exponential backoff, inside billed\nduration. Traces are what nearly every destination accepts; the other two are a decision about your\ndestination, so they are made deliberately.\n\nA disabled signal gets no collector pipeline **and** the SDK is told not to produce it\n(`OTEL_METRICS_EXPORTER=none`). Both halves matter: a signal with no pipeline is refused at the receiver on\nevery batch, so suppressing it at the source is what stops the error loop. An enabled signal's variable\nstays unset, because `otlp` is already the SDK default.\n\n`traces: false` with neither of the others on throws at synth — a collector with no pipeline fails to\nstart, which would leave the function instrumented and silent.\n\n**If Odigos also manages this function in manual mode, the signals have to match.** The connector renders\nthe collector configuration from the destination configured in Odigos and compares the whole string, so a\ntraces-only function judged against an all-three destination is reported as drifted on the\ncollector-export component. Enable the same set on both sides.\n\n## Instrumenting a whole stack\n\n```ts\nAspects.of(stack).add(new OdigosInstrumentationAspect(stack, {\n destination: { endpoint: 'otlp.example.com:4317' },\n}));\n```\n\n`skipUnsupportedRuntimes` defaults to `true` for the aspect: it visits every function in the scope,\nincluding ones whose runtime has no OpenTelemetry Lambda layer (`dotnet*`, `provided.*` for Go and custom\nruntimes). Each skip is a synth warning rather than a silent no-op. The construct defaults it to `false`,\nbecause explicitly asking to instrument a Go function is a mistake worth failing on.\n\n## Credentials in `headers`\n\n`destination.headers` is rendered into `OPENTELEMETRY_COLLECTOR_CONFIG_URI`, which is a plain Lambda\nenvironment variable — readable by anyone with `lambda:GetFunctionConfiguration` and visible in the\nconsole. For a long-lived credential, prefer a destination that authenticates by network position, or\nterminate at a collector you control.\n\n## Making Odigos report the function as instrumented\n\nBy default these constructs do **not** write `ODIGOS_MANAGED`, and the consequence is easy to hit: Odigos\nreports the function as `Absent` — \"awaiting your deployment\" — even though the layer is attached, the\nwrapper is set and the collector is configured. The connector derives ownership from that one variable, and\nchecks for it *before* comparing anything else, so nothing about a correctly instrumented function\nsubstitutes for it.\n\nFor a function Odigos discovers in **manual (IaC) mode** — which is the mode a workload is in unless you\nhave explicitly handed instrumentation to the connector — turn it on:\n\n```ts\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [fn],\n recordOwnershipMarker: true,\n});\n```\n\nThe marker records the exact layer ARN the construct attached, which is also what the connector reads back\nto decide which layer version the function is *supposed* to carry — so a version you pinned is respected\ninstead of being reported as drift. It works in `IN_ACCOUNT` mode too, where the ARN is a deploy-time\nreference your own code has no way to obtain.\n\nIt also records a rollback snapshot (`prevEnv`) naming every variable the construct set. That matters: a\nmarker without one makes an uninstrument remove the **layer** while leaving `AWS_LAMBDA_EXEC_WRAPPER`\npointing into it, which breaks the function at its next cold start. In web-server mode the snapshot holds\nyour `existingLoaderValue`, so a rollback restores your own `NODE_OPTIONS` rather than deleting it.\n\nLeave it `false` for a function you have enabled as an **automatic-mode** connector source: there the\nconnector owns the marker, including a snapshot it wrote itself, and two writers of one ownership record is\nthe combination that genuinely misbehaves.\n\n## Service names\n\nLeft unset, `OTEL_SERVICE_NAME` is the function's physical name when your stack names it explicitly, and\nthe construct id otherwise. The fallback exists because a name CloudFormation generates is a `Ref` to the\nfunction, and a function referencing itself in its own environment is a dependency cycle CloudFormation\nrejects at deploy time.\n\nThe connector compares `OTEL_SERVICE_NAME` against the workload's name in Odigos, which is the real AWS\nfunction name — so for a function whose name is generated, pass `serviceName` explicitly or it is reported\nas drifted. `serviceName` applies to **every** function a construct instruments, so use one construct per\nfunction when you want per-function names.\n\n## Do not also instrument these functions with the Odigos connector\n\nThe Odigos AWS connector instruments **live** functions by mutating them, and reconciles them back to its\nown desired state on every pass. A function instrumented here *and* enabled as an automatic-mode connector\nsource ends up owned by both: each `cdk deploy` reasserts the CDK's environment, each reconcile reasserts\nthe connector's, and every round trip publishes a new function version.\n\nPick one per function. Discovery-only (manual) mode is the combination that works: Odigos watches and\nreports, your stack owns the configuration — that is what `recordOwnershipMarker` is for.\n\n## API\n\n| Export | |\n|---|---|\n| `OdigosLambdaInstrumentation` | the construct; `instrument(fn)`, `instrumentAll(fns)` |\n| `OdigosInstrumentationAspect` | applies it to every function in a scope |\n| `OdigosDestination` | where the collector exports; exactly one of `endpoint` / `httpEndpoint` |\n| `OdigosLayerSource` | `ODIGOS_PUBLIC` \\| `IN_ACCOUNT` |\n| `OdigosInstrumentationMode` | `HANDLER` \\| `WEB_SERVER` |\n| `OdigosJavaHandlerDistro` | the four Java wrappers |\n| `recordOwnershipMarker` | the option that makes Odigos recognise the function as instrumented |\n| `renderCollectorConfig` | the collector config renderer, if you want to inspect what gets set |\n| `LAYER_ARNS`, `ODIGOS_VERSION` | the baked layer table and the release it came from |\n\n## License\n\nApache-2.0.\n"
3829
+ "markdown": "# Odigos CDK constructs for AWS\n\nInstrument AWS Lambda functions and ECS Fargate services with OpenTelemetry, from your own CDK app.\n\n```bash\nnpm install @odigos/aws-cdk # TypeScript / JavaScript\npip install odigos-aws-cdk # Python\n```\n\n| | Lambda | ECS Fargate |\n|---|---|---|\n| Construct | `OdigosLambdaInstrumentation` | `OdigosFargateInstrumentation` |\n| Mechanism | a layer, plus an exec wrapper or loader variable | agents staged into a shared task volume by a run-to-completion container |\n| Languages | python, nodejs, java, ruby | java, python, nodejs, dotnet, php, ruby |\n| Where telemetry goes | a collector in the same Lambda sandbox, which forwards | your destination, from the application process |\n| Language detection | from the function's declared runtime | none — you state the language |\n\nBoth write `ODIGOS_IAC` and never the connector's ownership marker: instrumented by Odigos, owned by you.\n\n# AWS Lambda\n\n```ts\nimport { OdigosLambdaInstrumentation } from '@odigos/aws-cdk';\n\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [apiFn, workerFn],\n});\n```\n\n```python\nfrom odigos_aws_cdk import OdigosLambdaInstrumentation\n\nOdigosLambdaInstrumentation(self, \"Odigos\",\n destination={\"endpoint\": \"otlp.example.com:4317\"},\n functions=[api_fn, worker_fn],\n)\n```\n\nThat attaches the layer for each function's language and architecture, sets the exec wrapper that loads\nthe OpenTelemetry SDK, and hands the in-Lambda collector its whole configuration.\n\n## How the telemetry actually leaves the function\n\nYour function's SDK **does not** export to your destination. It exports to an OpenTelemetry collector\nrunning inside the same Lambda sandbox, on localhost. The collector forwards to your destination *after*\nthe handler has already returned its response.\n\nThat indirection is the whole point. A slow or unreachable destination costs billed duration, not caller\nlatency — and the collector's `decouple` processor is what holds the sandbox open until the export queue\ndrains, so a low-traffic function does not lose its telemetry to the freeze.\n\nConsequently `OTEL_EXPORTER_OTLP_ENDPOINT` is deliberately never set. If you set it yourself you put the\nexport back on the invocation's critical path.\n\n## Endpoint grammar\n\n`endpoint` is OTLP/**gRPC** as bare `host:port` (conventionally 4317). `httpEndpoint` is OTLP/**HTTP** as a\nscheme-qualified URL (conventionally 4318). Exactly one. They select different collector exporters with\ndifferent endpoint grammars, so a scheme in `endpoint` — or its absence in `httpEndpoint` — throws at synth\nrather than producing a collector that starts and silently delivers nothing. A gRPC endpoint on port 4318\n(or an HTTP one on 4317) is the likeliest version of that mistake, and is reported as a synth warning.\n\n## Choosing a layer source\n\n```ts\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [fn],\n layerSource: OdigosLayerSource.IN_ACCOUNT,\n});\n```\n\n| | `ODIGOS_PUBLIC` (default) | `IN_ACCOUNT` |\n|---|---|---|\n| What it synthesizes | a layer ARN | an `AWS::Serverless::Application` (nested stack) per language/arch |\n| Layer owner | the Odigos AWS account | **your** account, created by your stack |\n| Resolution | synth time, from a table baked into this package | deploy time, from the Serverless Application Repository |\n| Environment-agnostic stacks | not supported — needs a concrete region | works |\n| Deploy speed | unchanged | slower on first deploy |\n\nBoth install identical bytes. `IN_ACCOUNT` exists for organisations whose policy forbids attaching a\nLambda layer owned by another AWS account. It needs the deploying principal to be allowed\n`serverlessrepo:CreateCloudFormationTemplate` and `serverlessrepo:GetApplication`.\n\nIf you mirror the layer somewhere yourself, pass `layerVersion` and neither path is used.\n\n## Versioning\n\n**The package version is the layer version.** `@odigos/aws-cdk@0.2.0` resolves to the layer built and\npublished by Odigos release `v0.2.0`, and pins the SAR application to semantic version `0.2.0` — which is\nimmutable, so it means the same bytes forever.\n\nNothing resolves at deploy time in the default path, so upgrading the layer is `npm update` and a\n`cdk diff` that shows the change. An instrumentation layer moving on its own, under a deployment that\nchanged nothing, is not a property you want.\n\n## Handler mode vs. web-server mode\n\n`OdigosInstrumentationMode.HANDLER` (the default) is for a normal Lambda handler. It sets\n`AWS_LAMBDA_EXEC_WRAPPER`.\n\n`OdigosInstrumentationMode.WEB_SERVER` is for a function running a web server behind the\n[AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter). The adapter owns the exec\nwrapper, so this mode does not touch it and loads instrumentation through the language's own loader\nvariable instead.\n\n```ts\nnew OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [webFn],\n mode: OdigosInstrumentationMode.WEB_SERVER,\n // NODE_OPTIONS the function already needs — ours is appended, not substituted.\n existingLoaderValue: '--max-old-space-size=2048',\n});\n```\n\nThere is no auto-detection, deliberately. Detecting the adapter means inspecting the function's other\nlayers, which at synth time are frequently unresolved tokens; a detector that was right most of the time\nwould silently break the functions it got wrong. **Applying `HANDLER` to a web-adapter function\noverwrites the adapter's wrapper and the function stops serving.**\n\n`existingLoaderValue` has to be passed explicitly because CDK's `lambda.Function` exposes no way to read\nback an environment variable set elsewhere in your app. Omit it and the loader variable is set to the\nOdigos value alone — for `NODE_OPTIONS` that can mean losing a flag your app needs to boot.\n\nRuby has no verified web-server loader and is rejected at synth in this mode.\n\n## Java handler interfaces\n\nThe Java layer ships four wrapper scripts, one per handler interface, and this is a correctness switch\nrather than a detail level:\n\n```ts\njavaHandlerDistro: OdigosJavaHandlerDistro.OTEL_STREAM_HANDLER\n```\n\n| Distro | For |\n|---|---|\n| `OTEL_HANDLER` (default) | `RequestHandler` |\n| `OTEL_PROXY_HANDLER` | API Gateway proxy events (enriched) |\n| `OTEL_SQS_HANDLER` | SQS events (enriched) |\n| `OTEL_STREAM_HANDLER` | `RequestStreamHandler` |\n\n`OTEL_HANDLER` installs a `RequestHandler` implementation. A `RequestStreamHandler` function has a\ndifferent signature entirely, so wrapping it with the default **breaks the invocation** — it does not\nmerely produce thinner spans.\n\n## Signals\n\n**Traces only, by default.** Metrics and logs are opt-in:\n\n```ts\ndestination: {\n endpoint: 'otlp.example.com:4317',\n metrics: true, // off unless you ask\n logs: true, // off unless you ask\n}\n```\n\nThey are opt-in because the cost of a signal the destination does not implement falls on the function:\nevery batch is refused and the in-Lambda collector retries it on an exponential backoff, inside billed\nduration. Traces are what nearly every destination accepts; the other two are a decision about your\ndestination, so they are made deliberately.\n\nA disabled signal gets no collector pipeline **and** the SDK is told not to produce it\n(`OTEL_METRICS_EXPORTER=none`). Both halves matter: a signal with no pipeline is refused at the receiver on\nevery batch, so suppressing it at the source is what stops the error loop. An enabled signal's variable\nstays unset, because `otlp` is already the SDK default.\n\n`traces: false` with neither of the others on throws at synth — a collector with no pipeline fails to\nstart, which would leave the function instrumented and silent.\n\n**If Odigos also manages this function in manual mode, the signals have to match.** The connector renders\nthe collector configuration from the destination configured in Odigos and compares the whole string, so a\ntraces-only function judged against an all-three destination is reported as drifted on the\ncollector-export component. Enable the same set on both sides.\n\n## Instrumenting a whole stack\n\n```ts\nAspects.of(stack).add(new OdigosInstrumentationAspect(stack, {\n destination: { endpoint: 'otlp.example.com:4317' },\n}));\n```\n\n`skipUnsupportedRuntimes` defaults to `true` for the aspect: it visits every function in the scope,\nincluding ones whose runtime has no OpenTelemetry Lambda layer (`dotnet*`, `provided.*` for Go and custom\nruntimes). Each skip is a synth warning rather than a silent no-op. The construct defaults it to `false`,\nbecause explicitly asking to instrument a Go function is a mistake worth failing on.\n\n## Credentials in `headers`\n\n`destination.headers` is rendered into `OPENTELEMETRY_COLLECTOR_CONFIG_URI`, which is a plain Lambda\nenvironment variable — readable by anyone with `lambda:GetFunctionConfiguration` and visible in the\nconsole. For a long-lived credential, prefer a destination that authenticates by network position, or\nterminate at a collector you control.\n\n## How Odigos recognises the function\n\nThese constructs write `ODIGOS_IAC` on every function they instrument, recording the layer ARN they attached\nand the package version that attached it. That variable is what Odigos reads to attribute the function to\nitself; without it a function reports as `Absent` — \"awaiting your deployment\" — however completely the layer,\nwrapper and collector configuration are applied. There is nothing to switch on.\n\nThe recorded layer ARN matters beyond attribution: it is what the connector checks the function against, so a\nversion you pinned is respected instead of being reported as drift the day Odigos publishes a newer one. It\nworks in `IN_ACCOUNT` mode too, where the ARN is a deploy-time reference your own code has no way to obtain.\n\nWhat these constructs never write is `ODIGOS_MANAGED`. That is the connector's own record of a mutation *it*\nperformed, including the `prevEnv` snapshot it restores from on rollback, and it is written only when you hand\na function to the connector by enabling it as an automatic-mode source. A CDK stack has no such snapshot to\noffer — nothing was mutated, your stack *is* the function's definition — so writing it would claim a rollback\nthat was never recorded. Do not add it by hand.\n\n## Service names\n\nLeft unset, `OTEL_SERVICE_NAME` is the function's physical name when your stack names it explicitly, and\nthe construct id otherwise. The fallback exists because a name CloudFormation generates is a `Ref` to the\nfunction, and a function referencing itself in its own environment is a dependency cycle CloudFormation\nrejects at deploy time.\n\nThe connector compares `OTEL_SERVICE_NAME` against the workload's name in Odigos, which is the real AWS\nfunction name — so for a function whose name is generated, pass `serviceName` explicitly or it is reported\nas drifted. `serviceName` applies to **every** function a construct instruments, so use one construct per\nfunction when you want per-function names.\n\n## Do not also instrument these functions with the Odigos connector\n\nThe Odigos AWS connector instruments **live** functions by mutating them, and reconciles them back to its\nown desired state on every pass. A function instrumented here *and* enabled as an automatic-mode connector\nsource ends up owned by both: each `cdk deploy` reasserts the CDK's environment, each reconcile reasserts\nthe connector's, and every round trip publishes a new function version.\n\nPick one per function. Discovery-only (manual) mode is the combination that works: Odigos watches and\nreports, your stack owns the configuration. That is what `ODIGOS_IAC` expresses — instrumented by Odigos,\nowned by you — and it is why these constructs never write the connector's ownership marker.\n\n# ECS Fargate\n\n```ts\nimport { OdigosFargateInstrumentation, OdigosFargateLanguage } from '@odigos/aws-cdk';\n\nconst odigos = new OdigosFargateInstrumentation(this, 'Odigos', {\n destination: { httpEndpoint: 'https://otlp.example.com:4318' },\n});\n\nodigos.instrument({\n container: apiContainer, // the ecs.ContainerDefinition to instrument\n language: OdigosFargateLanguage.JAVA,\n service: apiService, // read OTEL_SERVICE_NAME off the ECS service\n});\n```\n\n```python\nfrom odigos_aws_cdk import OdigosFargateInstrumentation, OdigosFargateLanguage\n\nodigos = OdigosFargateInstrumentation(self, \"Odigos\",\n destination={\"http_endpoint\": \"https://otlp.example.com:4318\"},\n)\nodigos.instrument(\n container=api_container,\n language=OdigosFargateLanguage.JAVA,\n service=api_service,\n)\n```\n\n## What it does to the task definition\n\nFour moves, which are one mechanism and only work together:\n\n1. a bare-name task volume, `odigos-agent` — on Fargate an ephemeral-storage bind mount scoped to the task\n (there is no tmpfs);\n2. a **non-essential** `odigos-agent` container that copies the language agents out of the agents bundle\n into that volume and exits 0;\n3. the volume mounted read-only at `/var/odigos` in your container, which `DependsOn` the staging container\n with condition `SUCCESS` — legal only against a non-essential container, which is why (2) is\n non-essential;\n4. the language's activation environment, the OTLP export environment and the `ODIGOS_IAC` marker on your\n container.\n\nMarker presence alone is a false green here. A container can carry a complete, correct activation\nenvironment while the staging container is gone — the application then starts, finds nothing at\n`/var/odigos`, and exports nothing while reporting as instrumented. That is why all four are one construct.\n\n## Where the telemetry goes\n\nStraight to your destination, from inside the application process. **This is the substantive difference\nfrom Lambda**, where the SDK hands batches to a collector in the same sandbox and the export happens after\nthe response has already been returned. A Fargate task has no such collector, so a slow or unreachable\ndestination is felt by the application's own exporter.\n\n## Naming the service\n\n`OTEL_SERVICE_NAME` **must equal the workload's name in Odigos, which for a Fargate workload is the ECS\nservice name** — not the task definition family and not the container name. A different value is reported\nas instrumentation drift rather than treated as a naming preference, so there is no default: pass `service`\nto read the name off an `ecs.FargateService`, or `serviceName` when the service is defined elsewhere.\n\nThe service's physical name has to be one you set. A name CloudFormation generates is a `Ref` to the\nservice, and the task definition that service runs cannot reference it — CloudFormation rejects the cycle\nat deploy time — so a generated name throws at synth pointing you at `serviceName`.\n\n## Languages, and stating them\n\n| | Activated through | Needs `runtimeVersion` |\n|---|---|---|\n| `JAVA` | `JAVA_TOOL_OPTIONS` | no |\n| `PYTHON` | `PYTHONPATH` | no |\n| `NODEJS` | `NODE_OPTIONS` | no |\n| `DOTNET` | `CORECLR_*` / `DOTNET_*` (glibc only) | no |\n| `PHP` | `PHP_INI_SCAN_DIR` | **yes** — major.minor, e.g. `\"8.3\"` |\n| `RUBY` | `RUBYOPT` | **yes** — major.minor, e.g. `\"3.3\"` |\n\nThere is no aspect and no detection, and unlike Lambda that is not a matter of taste. A function declares\nits runtime; a container declares an image. A language guessed from an image would silently mis-instrument\nwhatever it got wrong — a Java agent staged into a Python container leaves it uninstrumented, and a\n`JAVA_TOOL_OPTIONS` on a JVM-less image is simply ignored, so nothing fails loudly enough to notice.\n\nphp and ruby need `runtimeVersion` because their agents are laid down per runtime version in the bundle,\nand the version selects the path their activation variable points at. It must be exactly `major.minor`;\nanything else names a directory that does not exist, and the container starts with no agent loaded.\n\n**Go cannot be instrumented on Fargate at all.** Its only zero-code instrumentation is eBPF, and Fargate\nforbids the privileged containers and host PID an eBPF agent needs. Use the OpenTelemetry Go SDK.\n\n## Loader variables your container already sets\n\nThe construct reads the value your container was created with and **appends** to it, joined by the\nseparator the language's own pattern specifies — a space for `JAVA_TOOL_OPTIONS` and `NODE_OPTIONS`, a\ncolon for `PYTHONPATH`:\n\n```ts\ntaskDefinition.addContainer('App', {\n image,\n environment: { JAVA_TOOL_OPTIONS: '-Xmx512m' },\n});\n// becomes: -Xmx512m -javaagent:/var/odigos/java/javaagent.jar\n```\n\nPass `existingLoaderValue` when the value is not visible at synth — set by an `environmentFiles` entry,\nbaked into the image's own `ENV`, or supplied through `secrets`.\n\n`PHP_INI_SCAN_DIR` and `RUBYOPT` are the exception: Odigos compares them **exactly**, so they are set\noutright and a value already there is reported as a synth warning rather than merged. Fold what your\napplication needs into the value Odigos sets.\n\n## Transport\n\nEach language's agent has a preferred transport, and giving the destination **both** endpoints lets each\none take it:\n\n```ts\ndestination: {\n endpoint: 'otlp.example.com:4317', // OTLP/gRPC, bare host:port\n httpEndpoint: 'https://otlp.example.com:4318', // OTLP/HTTP, scheme-qualified\n}\n```\n\nEvery agent in the bundle prefers `http/protobuf`. java, python, nodejs and dotnet honour\n`OTEL_EXPORTER_OTLP_PROTOCOL` and fall back to gRPC when that is all the destination offers; **php and\nruby cannot** — their community SDKs are `http/protobuf`-only, so instrumenting one against a gRPC-only\ndestination throws at synth rather than deploying a task that exports nothing.\n\nEndpoint and protocol are one decision, and are compared as one. Pairing an endpoint with the other\nprotocol fails at runtime as a connection reset that points nowhere near the cause, so an endpoint on the\nother protocol's standard port (4317 with `http/protobuf`, 4318 with `grpc`) is a synth warning.\n\nUnlike Lambda, `destination.headers` is rendered into `OTEL_EXPORTER_OTLP_HEADERS` on the container. The\nconnector does not set or compare that variable when it instruments a Fargate task itself, so it is\nneither reconciled nor reported as drift — it is here because a task with no collector of its own has\nnowhere else to hold a credential. Same exposure caveat as Lambda: `ecs:DescribeTaskDefinition` and the\nconsole can read it.\n\n## Signals\n\nSame defaults as Lambda — traces on, metrics and logs opt-in — and the same requirement that they match\nwhat Odigos has configured for the destination. All three `OTEL_*_EXPORTER` variables are written\nexplicitly here, unlike Lambda where an enabled signal's variable is left unset, because the connector's\nFargate check compares all three by value.\n\n## A task definition with more than one application\n\nSix applications in six languages in one task definition is a real shape. Call `instrument()` once per\ncontainer; there is **one** staging container for the whole task definition, and its command is built\nlazily from the union of every instrumented container's agents, in ascending directory order — which is\nexactly what the connector compares it against.\n\n```ts\nodigos.instrumentAll([\n { container: apiContainer, language: OdigosFargateLanguage.JAVA, service: svc },\n { container: workerContainer, language: OdigosFargateLanguage.PYTHON, service: svc },\n]);\n```\n\nAWS caps a task definition at 10 containers and the staging container needs one of them; a definition\nalready at the limit fails at synth rather than on `RegisterTaskDefinition`.\n\n## The agents image\n\nThe staging container pulls `registry.odigos.io/odigos-fargate-agents` at this package's release tag — a\nmulti-arch manifest list, so amd64 and Graviton tasks both get a matching image. **It is pulled by your\ntask's execution role at every task start**, so a task in a private subnet with no NAT and no registry\nendpoint cannot pull it. Mirror it into a registry your tasks can reach and pass `agentsImage`:\n\n```ts\nagentsImage: '111122223333.dkr.ecr.eu-west-1.amazonaws.com/odigos-fargate-agents:v0.0.13',\n```\n\nA mirror has to be the same bundle — the activation environment names exact paths inside it. The bundle is\nLinux-only and glibc-based: a Windows task definition throws at synth, and musl (Alpine) images have no\n.NET native profiler in it.\n\n## Do not also instrument these services with the connector\n\nSame rule as Lambda, with ECS's own cost. The connector instruments a live service by registering a new\ntask-definition revision and updating the service to it. A service instrumented here *and* enabled as an\nautomatic-mode source is owned by both: each `cdk deploy` reasserts your stack's definition, each\nreconcile reasserts the connector's, and every round trip registers a revision and rolls the service.\nDiscovery-only (manual) mode is the combination that works.\n\n# API\n\n| Export | |\n|---|---|\n| `OdigosLambdaInstrumentation` | the Lambda construct; `instrument(fn)`, `instrumentAll(fns)` |\n| `OdigosInstrumentationAspect` | applies it to every function in a scope |\n| `OdigosFargateInstrumentation` | the Fargate construct; `instrument(target)`, `instrumentAll(targets)` |\n| `OdigosFargateTarget` | one container to instrument: `container`, `language`, `service` / `serviceName`, `runtimeVersion`, `existingLoaderValue` |\n| `OdigosFargateLanguage` | `JAVA` \\| `PYTHON` \\| `NODEJS` \\| `DOTNET` \\| `PHP` \\| `RUBY` |\n| `OdigosDestination` | where telemetry goes; exactly one endpoint on Lambda, either or both on Fargate |\n| `OdigosLayerSource` | `ODIGOS_PUBLIC` \\| `IN_ACCOUNT` |\n| `OdigosInstrumentationMode` | `HANDLER` \\| `WEB_SERVER` |\n| `OdigosJavaHandlerDistro` | the four Java wrappers |\n| `renderCollectorConfig` | the Lambda collector config renderer, if you want to inspect what gets set |\n| `sidecarCommand`, `evaluateAppendPattern` | the Fargate staging command and loader-value rendering |\n| `LAYER_ARNS`, `ODIGOS_VERSION` | the baked layer table and the release it came from |\n| `FARGATE_AGENTS_IMAGE`, `FARGATE_DISTROS_VERSION` | the agents image this build stages, and the distros release its recipes mirror |\n\n## License\n\nApache-2.0.\n"
3830
3830
  },
3831
3831
  "repository": {
3832
3832
  "directory": "cdk",
@@ -3852,7 +3852,7 @@
3852
3852
  "assembly": "@odigos/aws-cdk",
3853
3853
  "datatype": true,
3854
3854
  "docs": {
3855
- "remarks": "Exactly one of `endpoint` (OTLP/gRPC) and `httpEndpoint` (OTLP/HTTP) must be set. They are different\ncollector components with different endpoint grammars — `host:port` versus a scheme-qualified URL — so\nthis is a genuine branch and not a formatting difference. Setting neither, or both, throws at synth.\n\nNOTE ON THE DATA PATH. The function's SDK does not export here. It exports to the collector running\ninside the same Lambda sandbox on localhost, and the collector forwards to this destination after the\nhandler has already returned its response. That indirection is the point: a slow or unreachable\ndestination costs billed duration, not caller latency.",
3855
+ "remarks": "Exactly one of `endpoint` (OTLP/gRPC) and `httpEndpoint` (OTLP/HTTP) must be set. They are different\ncollector components with different endpoint grammars — `host:port` versus a scheme-qualified URL — so\nthis is a genuine branch and not a formatting difference. Setting neither, or both, throws at synth.\n\nON ECS FARGATE, WHERE THE SAME STRUCT IS REUSED, BOTH MAY BE SET AND OFTEN SHOULD BE. There is no\ncollector in the task, so the language agent exports to this destination itself, and which transport it\ncan use is a property of the agent: the php and ruby community SDKs speak OTLP/HTTP only, so a task\nholding one of those alongside a gRPC-only destination cannot be instrumented at all. Giving both\nendpoints lets each language take the transport it prefers. One struct rather than two so a stack that\ninstruments Lambda functions and Fargate services describes its destination once.\n\nNOTE ON THE DATA PATH. The function's SDK does not export here. It exports to the collector running\ninside the same Lambda sandbox on localhost, and the collector forwards to this destination after the\nhandler has already returned its response. That indirection is the point: a slow or unreachable\ndestination costs billed duration, not caller latency.\n\nTHIS MUST DESCRIBE THE SAME DESTINATION ODIGOS HAS CONFIGURED, SIGNAL FOR SIGNAL. The connector renders\nthis same configuration from its own destination record and compares the whole rendered document against\nwhat the function carries, so any difference — the endpoint, the credential, or which of the three signals\nis enabled — is reported as instrumentation drift on the workload rather than being reconciled. The\nasymmetry to watch is the signals: `traces` is on here and `metrics`/`logs` are off, while a destination in\nOdigos commonly has more than one enabled. A stack that leaves the defaults against such a destination\nreports as drifted for a reason nothing in the stack makes visible, so read the enabled signals off the\ndestination in Odigos and state them here.",
3856
3856
  "stability": "stable",
3857
3857
  "summary": "Where the in-Lambda collector exports telemetry to."
3858
3858
  },
@@ -3860,7 +3860,7 @@
3860
3860
  "kind": "interface",
3861
3861
  "locationInModule": {
3862
3862
  "filename": "src/types.ts",
3863
- "line": 102
3863
+ "line": 157
3864
3864
  },
3865
3865
  "name": "OdigosDestination",
3866
3866
  "properties": [
@@ -3875,7 +3875,7 @@
3875
3875
  "immutable": true,
3876
3876
  "locationInModule": {
3877
3877
  "filename": "src/types.ts",
3878
- "line": 111
3878
+ "line": 166
3879
3879
  },
3880
3880
  "name": "endpoint",
3881
3881
  "optional": true,
@@ -3887,14 +3887,14 @@
3887
3887
  "abstract": true,
3888
3888
  "docs": {
3889
3889
  "default": "- no headers",
3890
- "remarks": "These are rendered into `OPENTELEMETRY_COLLECTOR_CONFIG_URI`, which is a plain Lambda environment\nvariable: readable by anyone with `lambda:GetFunctionConfiguration` and visible in the console. For a\nlong-lived credential prefer a destination that authenticates by network position, or terminate at a\ncollector you control.",
3890
+ "remarks": "These are rendered into `OPENTELEMETRY_COLLECTOR_CONFIG_URI`, which is a plain Lambda environment\nvariable: readable by anyone with `lambda:GetFunctionConfiguration` and visible in the console. For a\nlong-lived credential prefer a destination that authenticates by network position, or terminate at a\ncollector you control.\n\nOn ECS Fargate they are rendered into `OTEL_EXPORTER_OTLP_HEADERS` on the instrumented container,\nwith the same exposure — `ecs:DescribeTaskDefinition` and the console. Note that the connector does\nNOT set that variable when it instruments a Fargate task itself, and does not compare it, so this is\nneither reconciled nor reported as drift either way: it is here because an authenticated destination\nis otherwise unreachable from a task, which has no collector of its own to hold the credential.",
3891
3891
  "stability": "stable",
3892
3892
  "summary": "Per-request headers, in practice the destination's credential."
3893
3893
  },
3894
3894
  "immutable": true,
3895
3895
  "locationInModule": {
3896
3896
  "filename": "src/types.ts",
3897
- "line": 139
3897
+ "line": 200
3898
3898
  },
3899
3899
  "name": "headers",
3900
3900
  "optional": true,
@@ -3917,7 +3917,7 @@
3917
3917
  "immutable": true,
3918
3918
  "locationInModule": {
3919
3919
  "filename": "src/types.ts",
3920
- "line": 118
3920
+ "line": 173
3921
3921
  },
3922
3922
  "name": "httpEndpoint",
3923
3923
  "optional": true,
@@ -3936,7 +3936,7 @@
3936
3936
  "immutable": true,
3937
3937
  "locationInModule": {
3938
3938
  "filename": "src/types.ts",
3939
- "line": 127
3939
+ "line": 182
3940
3940
  },
3941
3941
  "name": "insecure",
3942
3942
  "optional": true,
@@ -3955,7 +3955,7 @@
3955
3955
  "immutable": true,
3956
3956
  "locationInModule": {
3957
3957
  "filename": "src/types.ts",
3958
- "line": 176
3958
+ "line": 237
3959
3959
  },
3960
3960
  "name": "logs",
3961
3961
  "optional": true,
@@ -3974,7 +3974,7 @@
3974
3974
  "immutable": true,
3975
3975
  "locationInModule": {
3976
3976
  "filename": "src/types.ts",
3977
- "line": 165
3977
+ "line": 226
3978
3978
  },
3979
3979
  "name": "metrics",
3980
3980
  "optional": true,
@@ -3993,7 +3993,7 @@
3993
3993
  "immutable": true,
3994
3994
  "locationInModule": {
3995
3995
  "filename": "src/types.ts",
3996
- "line": 153
3996
+ "line": 214
3997
3997
  },
3998
3998
  "name": "traces",
3999
3999
  "optional": true,
@@ -4004,6 +4004,408 @@
4004
4004
  ],
4005
4005
  "symbolId": "src/types:OdigosDestination"
4006
4006
  },
4007
+ "@odigos/aws-cdk.OdigosFargateInstrumentation": {
4008
+ "assembly": "@odigos/aws-cdk",
4009
+ "base": "constructs.Construct",
4010
+ "docs": {
4011
+ "remarks": "```ts\nconst odigos = new OdigosFargateInstrumentation(this, 'Odigos', {\n destination: { httpEndpoint: 'https://otlp.example.com:4318' },\n});\nodigos.instrument({\n container: apiContainer,\n language: OdigosFargateLanguage.JAVA,\n service: apiService,\n});\n```\n\n## What it does to the task definition\n\nFour moves, which are one mechanism and only work together — the ECS adaptation of the Odikos\ninit-container mount method:\n\n 1. a bare-name task volume (`odigos-agent`), which on Fargate is an ephemeral-storage bind mount\n scoped to the task;\n 2. a NON-ESSENTIAL `odigos-agent` container that copies the language agents out of the agents bundle\n into that volume and exits 0;\n 3. the volume mounted read-only at `/var/odigos` in each instrumented container, which depends on the\n staging container with condition `SUCCESS` — only valid against a non-essential container, which is\n why (2) is non-essential;\n 4. the language's activation environment, the OTLP export environment, and the `ODIGOS_IAC` marker on\n each instrumented container.\n\nThere is ONE staging container per task definition however many languages the task holds; its command\nis the union of every instrumented container's agent directories, and it is built lazily so containers\ninstrumented later are included.\n\n## Where the telemetry goes\n\nStraight to your destination, from inside the application process. This is the substantive difference\nfrom Lambda: there is no collector in the task to hand a batch to, so a slow or unreachable destination\nis felt by the application's own exporter rather than absorbed after a response has been returned.\n\n## What it deliberately does NOT do\n\nThere is no aspect that sweeps a scope, as there is for Lambda. An aspect there works because a\nfunction DECLARES its runtime; a container declares an image, and a language guessed from an image name\nwould silently mis-instrument the ones it got wrong — staging a Java agent into a Python container\nleaves it uninstrumented, and a `JAVA_TOOL_OPTIONS` on a JVM-less image is simply ignored, so nothing\nfails loudly enough to notice.\n\n## Do not also instrument these services with the connector\n\nThe connector instruments live services by registering a new task-definition revision and updating the\nservice to it, reconciling to its own desired state on every pass. A service instrumented here and also\nenabled as a connector source ends up owned by both: each `cdk deploy` reasserts the stack's\ndefinition, each reconcile reasserts the connector's, and every round trip registers a revision and\nrolls the service. Choose one per service.",
4012
+ "stability": "stable",
4013
+ "summary": "Instruments ECS Fargate containers with the Odigos OpenTelemetry agents."
4014
+ },
4015
+ "fqn": "@odigos/aws-cdk.OdigosFargateInstrumentation",
4016
+ "initializer": {
4017
+ "docs": {
4018
+ "stability": "stable"
4019
+ },
4020
+ "locationInModule": {
4021
+ "filename": "src/fargate.ts",
4022
+ "line": 267
4023
+ },
4024
+ "parameters": [
4025
+ {
4026
+ "name": "scope",
4027
+ "type": {
4028
+ "fqn": "constructs.Construct"
4029
+ }
4030
+ },
4031
+ {
4032
+ "name": "id",
4033
+ "type": {
4034
+ "primitive": "string"
4035
+ }
4036
+ },
4037
+ {
4038
+ "name": "props",
4039
+ "type": {
4040
+ "fqn": "@odigos/aws-cdk.OdigosFargateInstrumentationProps"
4041
+ }
4042
+ }
4043
+ ]
4044
+ },
4045
+ "kind": "class",
4046
+ "locationInModule": {
4047
+ "filename": "src/fargate.ts",
4048
+ "line": 261
4049
+ },
4050
+ "methods": [
4051
+ {
4052
+ "docs": {
4053
+ "remarks": "Idempotent — instrumenting the same container twice is a no-op rather than\na doubled loader value.",
4054
+ "stability": "stable",
4055
+ "summary": "Instruments one container."
4056
+ },
4057
+ "locationInModule": {
4058
+ "filename": "src/fargate.ts",
4059
+ "line": 293
4060
+ },
4061
+ "name": "instrument",
4062
+ "parameters": [
4063
+ {
4064
+ "name": "target",
4065
+ "type": {
4066
+ "fqn": "@odigos/aws-cdk.OdigosFargateTarget"
4067
+ }
4068
+ }
4069
+ ]
4070
+ },
4071
+ {
4072
+ "docs": {
4073
+ "stability": "stable",
4074
+ "summary": "Instruments every target in the list."
4075
+ },
4076
+ "locationInModule": {
4077
+ "filename": "src/fargate.ts",
4078
+ "line": 331
4079
+ },
4080
+ "name": "instrumentAll",
4081
+ "parameters": [
4082
+ {
4083
+ "name": "targets",
4084
+ "type": {
4085
+ "collection": {
4086
+ "elementtype": {
4087
+ "fqn": "@odigos/aws-cdk.OdigosFargateTarget"
4088
+ },
4089
+ "kind": "array"
4090
+ }
4091
+ }
4092
+ }
4093
+ ]
4094
+ }
4095
+ ],
4096
+ "name": "OdigosFargateInstrumentation",
4097
+ "symbolId": "src/fargate:OdigosFargateInstrumentation"
4098
+ },
4099
+ "@odigos/aws-cdk.OdigosFargateInstrumentationOptions": {
4100
+ "assembly": "@odigos/aws-cdk",
4101
+ "datatype": true,
4102
+ "docs": {
4103
+ "stability": "stable",
4104
+ "summary": "Options shared by every container this construct instruments."
4105
+ },
4106
+ "fqn": "@odigos/aws-cdk.OdigosFargateInstrumentationOptions",
4107
+ "kind": "interface",
4108
+ "locationInModule": {
4109
+ "filename": "src/fargate.ts",
4110
+ "line": 85
4111
+ },
4112
+ "name": "OdigosFargateInstrumentationOptions",
4113
+ "properties": [
4114
+ {
4115
+ "abstract": true,
4116
+ "docs": {
4117
+ "remarks": "Unlike Lambda, BOTH transports may be set and often should be: a Fargate task has no collector of its\nown, so each language's agent exports to this destination itself and takes the transport it prefers.\nphp and ruby can only speak OTLP/HTTP at all.",
4118
+ "stability": "stable",
4119
+ "summary": "Where the instrumented containers export telemetry to."
4120
+ },
4121
+ "immutable": true,
4122
+ "locationInModule": {
4123
+ "filename": "src/fargate.ts",
4124
+ "line": 93
4125
+ },
4126
+ "name": "destination",
4127
+ "type": {
4128
+ "fqn": "@odigos/aws-cdk.OdigosDestination"
4129
+ }
4130
+ },
4131
+ {
4132
+ "abstract": true,
4133
+ "docs": {
4134
+ "default": "- the released `registry.odigos.io/odigos-fargate-agents` image for this package version",
4135
+ "remarks": "Defaults to the multi-arch image this package's release published, at that release's immutable tag.\nOverride it to mirror the image into a registry your tasks can reach — the image is pulled by YOUR\ntask's execution role at every task start, so a task in a private subnet with no NAT and no\ninterface endpoint cannot pull the default.\n\nA mirror must be the same bundle: the activation environment set below names exact paths inside it.",
4136
+ "stability": "stable",
4137
+ "summary": "The agents bundle the staging container copies the language agents out of."
4138
+ },
4139
+ "immutable": true,
4140
+ "locationInModule": {
4141
+ "filename": "src/fargate.ts",
4142
+ "line": 107
4143
+ },
4144
+ "name": "agentsImage",
4145
+ "optional": true,
4146
+ "type": {
4147
+ "primitive": "string"
4148
+ }
4149
+ },
4150
+ {
4151
+ "abstract": true,
4152
+ "docs": {
4153
+ "default": "false",
4154
+ "remarks": "Useful while wiring up a destination, expensive to leave on — and it is compared: the connector\nexpects the variable ABSENT unless debug telemetry is enabled for the connector too, so leaving this\non can itself be reported as drift.",
4155
+ "stability": "stable",
4156
+ "summary": "Raise agent verbosity (`OTEL_LOG_LEVEL=debug`) on every instrumented container."
4157
+ },
4158
+ "immutable": true,
4159
+ "locationInModule": {
4160
+ "filename": "src/fargate.ts",
4161
+ "line": 118
4162
+ },
4163
+ "name": "debug",
4164
+ "optional": true,
4165
+ "type": {
4166
+ "primitive": "boolean"
4167
+ }
4168
+ }
4169
+ ],
4170
+ "symbolId": "src/fargate:OdigosFargateInstrumentationOptions"
4171
+ },
4172
+ "@odigos/aws-cdk.OdigosFargateInstrumentationProps": {
4173
+ "assembly": "@odigos/aws-cdk",
4174
+ "datatype": true,
4175
+ "docs": {
4176
+ "stability": "stable",
4177
+ "summary": "Props for {@link OdigosFargateInstrumentation}."
4178
+ },
4179
+ "fqn": "@odigos/aws-cdk.OdigosFargateInstrumentationProps",
4180
+ "interfaces": [
4181
+ "@odigos/aws-cdk.OdigosFargateInstrumentationOptions"
4182
+ ],
4183
+ "kind": "interface",
4184
+ "locationInModule": {
4185
+ "filename": "src/fargate.ts",
4186
+ "line": 191
4187
+ },
4188
+ "name": "OdigosFargateInstrumentationProps",
4189
+ "properties": [
4190
+ {
4191
+ "abstract": true,
4192
+ "docs": {
4193
+ "default": "- none",
4194
+ "remarks": "More can be added with `instrument()`.",
4195
+ "stability": "stable",
4196
+ "summary": "Containers to instrument on construction."
4197
+ },
4198
+ "immutable": true,
4199
+ "locationInModule": {
4200
+ "filename": "src/fargate.ts",
4201
+ "line": 197
4202
+ },
4203
+ "name": "targets",
4204
+ "optional": true,
4205
+ "type": {
4206
+ "collection": {
4207
+ "elementtype": {
4208
+ "fqn": "@odigos/aws-cdk.OdigosFargateTarget"
4209
+ },
4210
+ "kind": "array"
4211
+ }
4212
+ }
4213
+ }
4214
+ ],
4215
+ "symbolId": "src/fargate:OdigosFargateInstrumentationProps"
4216
+ },
4217
+ "@odigos/aws-cdk.OdigosFargateLanguage": {
4218
+ "assembly": "@odigos/aws-cdk",
4219
+ "docs": {
4220
+ "remarks": "There is no auto-detection, and unlike Lambda that is not a choice: a Lambda function declares its\nruntime as a property CloudFormation can be asked for, while a Fargate container declares an image.\nResolving a language from an image means pulling it and reading its config, which is deploy-time I/O a\nsynth cannot do — and the connector, which CAN do it, still accepts a runtime override for the cases it\ngets wrong. So the language is stated.\n\nThe MEMBER VALUES are the connector's canonical language keys rather than a restatement of the member\nnames, because these values are load-bearing twice over: they are what the `ODIGOS_IAC` marker records\nas `lang`, which is what the connector's conformance check rebuilds the container's expected activation\nenvironment from, and they name the agent directory the staging container copies.\n\nGo is absent by platform design, not omission. Its only zero-code instrumentation is eBPF, and Fargate\nforbids the privileged containers and host PID an eBPF agent needs — no override enables it. Instrument\na Go application with the OpenTelemetry Go SDK instead.",
4221
+ "stability": "stable",
4222
+ "summary": "The language whose OpenTelemetry agent is staged into an ECS Fargate container."
4223
+ },
4224
+ "fqn": "@odigos/aws-cdk.OdigosFargateLanguage",
4225
+ "kind": "enum",
4226
+ "locationInModule": {
4227
+ "filename": "src/types.ts",
4228
+ "line": 108
4229
+ },
4230
+ "members": [
4231
+ {
4232
+ "docs": {
4233
+ "remarks": "Activated through `JAVA_TOOL_OPTIONS`.",
4234
+ "stability": "stable",
4235
+ "summary": "JVM applications — Java, Kotlin, Scala."
4236
+ },
4237
+ "name": "JAVA"
4238
+ },
4239
+ {
4240
+ "docs": {
4241
+ "remarks": "Activated through `PYTHONPATH`.",
4242
+ "stability": "stable",
4243
+ "summary": "Python."
4244
+ },
4245
+ "name": "PYTHON"
4246
+ },
4247
+ {
4248
+ "docs": {
4249
+ "stability": "stable",
4250
+ "summary": "Node.js. Activated through `NODE_OPTIONS`."
4251
+ },
4252
+ "name": "NODEJS"
4253
+ },
4254
+ {
4255
+ "docs": {
4256
+ "stability": "stable",
4257
+ "summary": ".NET, glibc only — the bundle ships no musl (Alpine) native profiler."
4258
+ },
4259
+ "name": "DOTNET"
4260
+ },
4261
+ {
4262
+ "docs": {
4263
+ "remarks": "Needs `runtimeVersion` (major.minor): its agent is laid down per runtime version, and the\nversion selects the path `PHP_INI_SCAN_DIR` points at.",
4264
+ "stability": "stable",
4265
+ "summary": "PHP."
4266
+ },
4267
+ "name": "PHP"
4268
+ },
4269
+ {
4270
+ "docs": {
4271
+ "remarks": "Needs `runtimeVersion` (major.minor), for the same reason as PHP — the version selects the path\n`RUBYOPT` requires.",
4272
+ "stability": "stable",
4273
+ "summary": "Ruby."
4274
+ },
4275
+ "name": "RUBY"
4276
+ }
4277
+ ],
4278
+ "name": "OdigosFargateLanguage",
4279
+ "symbolId": "src/types:OdigosFargateLanguage"
4280
+ },
4281
+ "@odigos/aws-cdk.OdigosFargateTarget": {
4282
+ "assembly": "@odigos/aws-cdk",
4283
+ "datatype": true,
4284
+ "docs": {
4285
+ "stability": "stable",
4286
+ "summary": "One container to instrument."
4287
+ },
4288
+ "fqn": "@odigos/aws-cdk.OdigosFargateTarget",
4289
+ "kind": "interface",
4290
+ "locationInModule": {
4291
+ "filename": "src/fargate.ts",
4292
+ "line": 124
4293
+ },
4294
+ "name": "OdigosFargateTarget",
4295
+ "properties": [
4296
+ {
4297
+ "abstract": true,
4298
+ "docs": {
4299
+ "remarks": "Its task definition is taken from it, so the staging container, the shared\nvolume and the startup dependency are added to the right one automatically.",
4300
+ "stability": "stable",
4301
+ "summary": "The application container."
4302
+ },
4303
+ "immutable": true,
4304
+ "locationInModule": {
4305
+ "filename": "src/fargate.ts",
4306
+ "line": 129
4307
+ },
4308
+ "name": "container",
4309
+ "type": {
4310
+ "fqn": "aws-cdk-lib.aws_ecs.ContainerDefinition"
4311
+ }
4312
+ },
4313
+ {
4314
+ "abstract": true,
4315
+ "docs": {
4316
+ "remarks": "Stated rather than detected — a container declares an image, not a runtime, and resolving a language\nfrom an image means pulling it.",
4317
+ "stability": "stable",
4318
+ "summary": "The language whose agent to stage and activate."
4319
+ },
4320
+ "immutable": true,
4321
+ "locationInModule": {
4322
+ "filename": "src/fargate.ts",
4323
+ "line": 137
4324
+ },
4325
+ "name": "language",
4326
+ "type": {
4327
+ "fqn": "@odigos/aws-cdk.OdigosFargateLanguage"
4328
+ }
4329
+ },
4330
+ {
4331
+ "abstract": true,
4332
+ "docs": {
4333
+ "default": "- read from the container's own environment",
4334
+ "remarks": "Only needed as an OVERRIDE. The construct reads the value the container was created with and appends\nto it, so a container that sets its own `JAVA_TOOL_OPTIONS` in `addContainer` keeps it. Pass this when\nthe value is not visible at synth — set by an `environmentFiles` entry, injected by the image's own\n`ENV`, or supplied through `secrets`.",
4335
+ "stability": "stable",
4336
+ "summary": "The value this container already needs in its loader variable (`JAVA_TOOL_OPTIONS`, `NODE_OPTIONS` or `PYTHONPATH`), which the Odigos fragment is joined to rather than replacing."
4337
+ },
4338
+ "immutable": true,
4339
+ "locationInModule": {
4340
+ "filename": "src/fargate.ts",
4341
+ "line": 185
4342
+ },
4343
+ "name": "existingLoaderValue",
4344
+ "optional": true,
4345
+ "type": {
4346
+ "primitive": "string"
4347
+ }
4348
+ },
4349
+ {
4350
+ "abstract": true,
4351
+ "docs": {
4352
+ "default": "- none; required for php and ruby",
4353
+ "remarks": "Required for php and ruby, whose agents are laid down per runtime version in the bundle, and the\nversion selects the path their activation variables point at. Ignored by every other language.",
4354
+ "stability": "stable",
4355
+ "summary": "The application's runtime version as `major.minor` — for example `\"8.3\"`."
4356
+ },
4357
+ "immutable": true,
4358
+ "locationInModule": {
4359
+ "filename": "src/fargate.ts",
4360
+ "line": 172
4361
+ },
4362
+ "name": "runtimeVersion",
4363
+ "optional": true,
4364
+ "type": {
4365
+ "primitive": "string"
4366
+ }
4367
+ },
4368
+ {
4369
+ "abstract": true,
4370
+ "docs": {
4371
+ "default": "- `serviceName` must be given instead",
4372
+ "remarks": "Its physical name has to be one your stack SET, not one CloudFormation generates: a generated name is\na `Ref` to the service, and a service's own task definition referencing it is a dependency cycle\nCloudFormation rejects at deploy time. A generated name throws at synth pointing at `serviceName`.",
4373
+ "stability": "stable",
4374
+ "summary": "The ECS service that runs this task definition, used only to read its name."
4375
+ },
4376
+ "immutable": true,
4377
+ "locationInModule": {
4378
+ "filename": "src/fargate.ts",
4379
+ "line": 162
4380
+ },
4381
+ "name": "service",
4382
+ "optional": true,
4383
+ "type": {
4384
+ "fqn": "aws-cdk-lib.aws_ecs.BaseService"
4385
+ }
4386
+ },
4387
+ {
4388
+ "abstract": true,
4389
+ "docs": {
4390
+ "default": "- taken from `service`",
4391
+ "remarks": "THIS MUST MATCH THE WORKLOAD'S NAME IN ODIGOS, which for a Fargate workload is the ECS SERVICE name —\nnot the task definition family and not the container name. A different value is reported as\ninstrumentation drift rather than treated as a naming preference.\n\nPass `service` instead to read it off the service, or set this when the service is defined elsewhere\n(a different stack, Terraform, the console). One of the two is required.",
4392
+ "stability": "stable",
4393
+ "summary": "`OTEL_SERVICE_NAME` for this container."
4394
+ },
4395
+ "immutable": true,
4396
+ "locationInModule": {
4397
+ "filename": "src/fargate.ts",
4398
+ "line": 151
4399
+ },
4400
+ "name": "serviceName",
4401
+ "optional": true,
4402
+ "type": {
4403
+ "primitive": "string"
4404
+ }
4405
+ }
4406
+ ],
4407
+ "symbolId": "src/fargate:OdigosFargateTarget"
4408
+ },
4007
4409
  "@odigos/aws-cdk.OdigosInstrumentationAspect": {
4008
4410
  "assembly": "@odigos/aws-cdk",
4009
4411
  "docs": {
@@ -4018,7 +4420,7 @@
4018
4420
  },
4019
4421
  "locationInModule": {
4020
4422
  "filename": "src/instrumentation.ts",
4021
- "line": 448
4423
+ "line": 386
4022
4424
  },
4023
4425
  "parameters": [
4024
4426
  {
@@ -4045,7 +4447,7 @@
4045
4447
  "kind": "class",
4046
4448
  "locationInModule": {
4047
4449
  "filename": "src/instrumentation.ts",
4048
- "line": 440
4450
+ "line": 378
4049
4451
  },
4050
4452
  "methods": [
4051
4453
  {
@@ -4055,7 +4457,7 @@
4055
4457
  },
4056
4458
  "locationInModule": {
4057
4459
  "filename": "src/instrumentation.ts",
4058
- "line": 455
4460
+ "line": 393
4059
4461
  },
4060
4462
  "name": "visit",
4061
4463
  "overrides": "aws-cdk-lib.IAspect",
@@ -4086,7 +4488,7 @@
4086
4488
  "kind": "interface",
4087
4489
  "locationInModule": {
4088
4490
  "filename": "src/instrumentation.ts",
4089
- "line": 421
4491
+ "line": 359
4090
4492
  },
4091
4493
  "name": "OdigosInstrumentationAspectProps",
4092
4494
  "symbolId": "src/instrumentation:OdigosInstrumentationAspectProps"
@@ -4269,25 +4671,6 @@
4269
4671
  "fqn": "@odigos/aws-cdk.OdigosInstrumentationMode"
4270
4672
  }
4271
4673
  },
4272
- {
4273
- "abstract": true,
4274
- "docs": {
4275
- "default": "false",
4276
- "remarks": "WITHOUT IT THE FUNCTION IS REPORTED AS UNINSTRUMENTED. The connector derives ownership from this\nvariable alone: no marker means `Absent` — \"awaiting your deployment\" — even though the layer is\nattached, the wrapper is set and the collector is configured. Set this to `true` for a function that\nOdigos discovers in MANUAL (IaC) mode, which is the mode a workload is in unless you explicitly hand\ninstrumentation to the connector.\n\nLeave it `false` (the default) for a function you have enabled as an AUTOMATIC-mode connector source.\nThere, the connector instruments the function itself and owns this variable, including the `prevEnv`\nsnapshot it restores on rollback; two writers of one ownership record is the one combination that\ngenuinely misbehaves.\n\nThe marker records the exact layer ARN this construct attached, which is also what the connector reads\nback to decide which layer version the function is supposed to carry — so a version you pinned is\nrespected rather than reported as drift. It works in every layer mode, including `IN_ACCOUNT`, where the\nARN is a deploy-time reference your own code cannot obtain.",
4277
- "stability": "stable",
4278
- "summary": "Write `ODIGOS_MANAGED`, the marker that makes the Odigos connector recognise this function as instrumented."
4279
- },
4280
- "immutable": true,
4281
- "locationInModule": {
4282
- "filename": "src/instrumentation.ts",
4283
- "line": 187
4284
- },
4285
- "name": "recordOwnershipMarker",
4286
- "optional": true,
4287
- "type": {
4288
- "primitive": "boolean"
4289
- }
4290
- },
4291
4674
  {
4292
4675
  "abstract": true,
4293
4676
  "docs": {
@@ -4318,7 +4701,7 @@
4318
4701
  "immutable": true,
4319
4702
  "locationInModule": {
4320
4703
  "filename": "src/instrumentation.ts",
4321
- "line": 198
4704
+ "line": 174
4322
4705
  },
4323
4706
  "name": "skipUnsupportedRuntimes",
4324
4707
  "optional": true,
@@ -4380,7 +4763,7 @@
4380
4763
  "assembly": "@odigos/aws-cdk",
4381
4764
  "base": "constructs.Construct",
4382
4765
  "docs": {
4383
- "remarks": "```ts\nconst odigos = new OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [apiFn, workerFn],\n});\nodigos.instrument(anotherFn);\n```\n\nWhat it does to each function: attaches the layer for the function's language and architecture, sets\n`AWS_LAMBDA_EXEC_WRAPPER` so the layer loads the SDK, sets `OTEL_SERVICE_NAME`, and hands the in-Lambda\ncollector its entire configuration inline through `OPENTELEMETRY_COLLECTOR_CONFIG_URI`.\n\nThe function's SDK exports to the collector on localhost, not to your destination. The collector\nforwards after the handler has already returned, so a slow destination costs billed duration rather\nthan caller latency.\n\n## Do not also instrument these functions with the connector\n\nThe Odigos AWS connector instruments live functions by mutating them, and reconciles them back to its\nown desired state on every pass. A function instrumented here and also enabled as a connector source\nends up owned by both: each `cdk deploy` reasserts the CDK's environment, each reconcile reasserts the\nconnector's, and every round trip publishes a new function version.\n\nChoose one per function. This construct never sets the connector's `ODIGOS_MANAGED` ownership marker,\nso an IaC-instrumented function is not one the connector will roll back — but it will happily take it\nover if you enable it as a source.",
4766
+ "remarks": "```ts\nconst odigos = new OdigosLambdaInstrumentation(this, 'Odigos', {\n destination: { endpoint: 'otlp.example.com:4317' },\n functions: [apiFn, workerFn],\n});\nodigos.instrument(anotherFn);\n```\n\nWhat it does to each function: attaches the layer for the function's language and architecture, sets\n`AWS_LAMBDA_EXEC_WRAPPER` so the layer loads the SDK, sets `OTEL_SERVICE_NAME`, and hands the in-Lambda\ncollector its entire configuration inline through `OPENTELEMETRY_COLLECTOR_CONFIG_URI`.\n\nThe function's SDK exports to the collector on localhost, not to your destination. The collector\nforwards after the handler has already returned, so a slow destination costs billed duration rather\nthan caller latency.\n\n## Do not also instrument these functions with the connector\n\nThe Odigos AWS connector instruments live functions by mutating them, and reconciles them back to its\nown desired state on every pass. A function instrumented here and also enabled as a connector source\nends up owned by both: each `cdk deploy` reasserts the CDK's environment, each reconcile reasserts the\nconnector's, and every round trip publishes a new function version.\n\nChoose one per function. This construct writes `ODIGOS_IAC` and never the connector's `ODIGOS_MANAGED`\nownership marker, so an IaC-instrumented function reports as instrumented but is not one the connector\nwill roll back — though it will happily take it over if you enable it as a source.",
4384
4767
  "stability": "stable",
4385
4768
  "summary": "Instruments AWS Lambda functions with the Odigos OpenTelemetry layer."
4386
4769
  },
@@ -4391,7 +4774,7 @@
4391
4774
  },
4392
4775
  "locationInModule": {
4393
4776
  "filename": "src/instrumentation.ts",
4394
- "line": 249
4777
+ "line": 225
4395
4778
  },
4396
4779
  "parameters": [
4397
4780
  {
@@ -4417,7 +4800,7 @@
4417
4800
  "kind": "class",
4418
4801
  "locationInModule": {
4419
4802
  "filename": "src/instrumentation.ts",
4420
- "line": 243
4803
+ "line": 219
4421
4804
  },
4422
4805
  "methods": [
4423
4806
  {
@@ -4428,7 +4811,7 @@
4428
4811
  },
4429
4812
  "locationInModule": {
4430
4813
  "filename": "src/instrumentation.ts",
4431
- "line": 289
4814
+ "line": 265
4432
4815
  },
4433
4816
  "name": "instrument",
4434
4817
  "parameters": [
@@ -4447,7 +4830,7 @@
4447
4830
  },
4448
4831
  "locationInModule": {
4449
4832
  "filename": "src/instrumentation.ts",
4450
- "line": 322
4833
+ "line": 298
4451
4834
  },
4452
4835
  "name": "instrumentAll",
4453
4836
  "parameters": [
@@ -4482,7 +4865,7 @@
4482
4865
  "kind": "interface",
4483
4866
  "locationInModule": {
4484
4867
  "filename": "src/instrumentation.ts",
4485
- "line": 204
4868
+ "line": 180
4486
4869
  },
4487
4870
  "name": "OdigosLambdaInstrumentationProps",
4488
4871
  "properties": [
@@ -4497,7 +4880,7 @@
4497
4880
  "immutable": true,
4498
4881
  "locationInModule": {
4499
4882
  "filename": "src/instrumentation.ts",
4500
- "line": 210
4883
+ "line": 186
4501
4884
  },
4502
4885
  "name": "functions",
4503
4886
  "optional": true,
@@ -4547,6 +4930,6 @@
4547
4930
  "symbolId": "src/types:OdigosLayerSource"
4548
4931
  }
4549
4932
  },
4550
- "version": "0.0.12",
4551
- "fingerprint": "76adPuc8StHhgh9x1dH8rP9GBtLmzzNKY1d5Dvhv+hM="
4933
+ "version": "0.0.14",
4934
+ "fingerprint": "eXW2kcI443e8XtE7aA9wNkGzqU5uCVrtQgst7XvbbSE="
4552
4935
  }