# OpenTelemetry

> Export OpenTelemetry traces, metrics, logs, errors, and profiles from Elide and your code over OTLP, with no SDK in the application: quick start, configuration, providers, and language APIs.

Elide is an OpenTelemetry SDK. JavaScript, TypeScript, and Python code uses the standard OpenTelemetry API for its
language, and Elide supplies the implementation and the OTLP exporter. Elide's own spans and metrics for served
requests, `fetch`, errors, the process, and builds and tests join the same traces.

> [!TIP] No SDK, exporter, or agent
> Import the standard API and configure a destination; there is nothing else to install.

> [!NOTE] Off until configured
> With no destination configured, Elide starts no telemetry threads and opens no connections.

## Quick start

Start an OpenTelemetry Collector that prints what it receives:

```bash
docker run --rm -p 4317:4317 -p 4318:4318 otel/opentelemetry-collector:0.115.1
```

Write a script that creates a span:

```ts
// app.ts
import { trace } from "@opentelemetry/api";

const tracer = trace.getTracer("checkout");
await tracer.startActiveSpan("charge", async (span) => {
  span.setAttribute("order.id", 42);
  console.log("charged order 42");
  span.end();
});
```

Run it with the collector as its endpoint:

```bash
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 OTEL_SERVICE_NAME=checkout elide run app.ts
```

The collector prints the span, and the `console.log` line as a log record carrying the span's ids (excerpt):

```text
Resource attributes:
     -> telemetry.sdk.name: Str(elide)
     -> service.name: Str(checkout)
InstrumentationScope checkout
Span #0
    Trace ID       : 5162303c77b9dab62b1d536ce955c103
    ID             : 410c19dcae7eda3c
    Name           : charge
    Kind           : Internal
Attributes:
     -> order.id: Int(42)

InstrumentationScope console
LogRecord #0
SeverityText: INFO
Body: Str(charged order 42)
Trace ID: 5162303c77b9dab62b1d536ce955c103
Span ID: 410c19dcae7eda3c
```

Elide exports pending data before it exits, so short scripts need no flush call.

`@opentelemetry/api` needs no install: Elide provides it when the project has no copy.

## Configure a project

In a project, put the settings in `elide.pkl`. Credentials stay in environment variables, named by the manifest:

```pkl
amends "elide:project.pkl"

name = "checkout"

opentelemetry {
  service { name = "checkout"; version = "1.4.2"; environment = "production" }
  destinations {
    ["collector"] { endpoint = "http://localhost:4318" }
    ["honeycomb"] { provider = "honeycomb" }
  }
}
```

Variables override the block and `--otel-*` flags override both; see [Configuration](https://elide.help/docs/opentelemetry/configuration).

## Turn it off

```bash
elide run --no-otel app.ts          # one run
OTEL_SDK_DISABLED=true elide serve  # one process
```

## Languages

| Language | API | Elide records |
| --- | --- | --- |
| JavaScript and TypeScript | `@opentelemetry/api`, `@opentelemetry/api-logs`, [`elide:telemetry`](https://elide.help/docs/opentelemetry/javascript#elidetelemetry) | Server spans, `fetch` client spans, `console.*` logs, errors |
| Python | `opentelemetry`, `logging`, [`elide.telemetry`](https://elide.help/docs/opentelemetry/python#elidetelemetry) | `logging` records, errors |
| Java and Kotlin | None | Nothing |

Java and Kotlin programs that Elide runs get no OpenTelemetry API, agent, or trace context from Elide. Use the
OpenTelemetry Java SDK or agent in the program as you would on any JVM. `elide build` and `elide test` still record
their own spans for JVM projects; see [Builds and tests in CI](https://elide.help/docs/opentelemetry/runtime#builds-and-tests-in-ci).

## In this section

| Page | Covers |
| --- | --- |
| [Configuration](https://elide.help/docs/opentelemetry/configuration) | `elide.pkl`, environment variables, flags, precedence |
| [Providers](https://elide.help/docs/opentelemetry/providers) | OTLP, Sentry, Datadog, PostHog, Honeycomb, Grafana Cloud |
| [Signals](https://elide.help/docs/opentelemetry/signals) | Traces, metrics, logs, errors, profiles |
| [Runtime instrumentation](https://elide.help/docs/opentelemetry/runtime) | Serving, `fetch`, process metrics, CI spans |
| [Correlation and baggage](https://elide.help/docs/opentelemetry/correlation) | Linked signals, `traceparent`, W3C baggage |
| [JavaScript and TypeScript](https://elide.help/docs/opentelemetry/javascript) | API, SDK takeover, `elide:telemetry` |
| [Python](https://elide.help/docs/opentelemetry/python) | API, `logging`, `elide.telemetry` |
| [Emitted telemetry](https://elide.help/docs/opentelemetry/reference) | Every span, metric, and attribute Elide emits |
| [Troubleshooting](https://elide.help/docs/opentelemetry/troubleshooting) | Nothing arrives, rejected data, status counters |

## Samples

- [Custom span in TypeScript](https://elide.help/docs/code-samples#custom-span-in-typescript)
- [Metrics instruments](https://elide.help/docs/code-samples#metrics-instruments)
- [Python span and logging](https://elide.help/docs/code-samples#python-span-and-logging)
- [OTLP to a local collector](https://elide.help/docs/code-samples#otlp-to-a-local-collector)
- [Baggage across services](https://elide.help/docs/code-samples#baggage-across-services)
