> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apitally.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Tracing instrumentation

> Instrument your JavaScript application with OpenTelemetry for tracing in Apitally.

When tracing is enabled, the Apitally SDK captures [OpenTelemetry](https://opentelemetry.io/docs/languages/js/) spans during request handling and attaches them to request logs. This allows you to see exactly what happened during each request, including database queries, HTTP calls to external services, and custom operations.

## Enable tracing

To enable tracing, set `captureTraces` to `true` in your request logging configuration:

<CodeGroup>
  ```javascript Hono {10-11} theme={null}
  import { Hono } from "hono";
  import { useApitally } from "apitally/hono";

  const app = new Hono();

  useApitally(app, {
    clientId: "your-client-id",
    env: "dev",
    requestLogging: {
      enabled: true,
      captureTraces: true,
    },
  });
  ```

  ```javascript NestJS {12-13} theme={null}
  import { NestFactory } from "@nestjs/core";
  import { useApitally } from "apitally/nestjs";
  import { AppModule } from "./app.module";

  async function bootstrap() {
    const app = await NestFactory.create(AppModule);

    await useApitally(app, {
      clientId: "your-client-id",
      env: "dev",
      requestLogging: {
        enabled: true,
        captureTraces: true,
      },
    });
  }
  ```

  ```javascript Express {10-11} theme={null}
  import express from "express";
  import { useApitally } from "apitally/express";

  const app = express();

  useApitally(app, {
    clientId: "your-client-id",
    env: "dev",
    requestLogging: {
      enabled: true,
      captureTraces: true,
    },
  });
  ```

  ```javascript Fastify {10-11} theme={null}
  import Fastify from "fastify";
  import { apitallyPlugin } from "apitally/fastify";

  const fastify = Fastify({ logger: true });

  await fastify.register(apitallyPlugin, {
    clientId: "your-client-id",
    env: "dev",
    requestLogging: {
      enabled: true,
      captureTraces: true,
    },
  });
  ```
</CodeGroup>

## Set up OpenTelemetry

To capture spans from libraries like HTTP clients and database drivers, you need to set up OpenTelemetry instrumentation.

First, install the required packages:

```shell theme={null}
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node
```

Then create an `instrumentation.ts` file (or `instrumentation.mjs` for JavaScript) that initializes the OpenTelemetry SDK with the `ApitallySpanProcessor` and auto-instrumentations:

```javascript instrumentation.ts / instrumentation.mjs {3,6} theme={null}
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { ApitallySpanProcessor } from "apitally/otel";

const sdk = new NodeSDK({
  spanProcessors: [new ApitallySpanProcessor()],
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();
```

<Info>
  No trace exporter is required. The `ApitallySpanProcessor` collects spans and attaches them to request logs instead.
</Info>

Finally, run your application with the `--import` flag to load the instrumentation before your application code:

<CodeGroup>
  ```shell TypeScript theme={null}
  npx tsx --import ./instrumentation.ts app.ts
  ```

  ```shell JavaScript theme={null}
  node --import ./instrumentation.mjs app.js
  ```
</CodeGroup>

See the official [OpenTelemetry guide for Node.js](https://opentelemetry.io/docs/languages/js/getting-started/nodejs/) for more details.

## Create custom spans

For custom operations that aren't covered by library instrumentation, you can [create spans](https://opentelemetry.io/docs/languages/js/instrumentation/#create-spans) manually using the `startActiveSpan` method from the standard OpenTelemetry API.

```javascript theme={null}
import { trace } from "@opentelemetry/api";

const tracer = trace.getTracer("my-app");

async function processOrder(orderId) {
  await tracer.startActiveSpan("process_order", async (span) => {
    span.setAttribute("order_id", orderId);
    // ...
    span.end();
  });
}
```
