When tracing is enabled, the Apitally SDK captures OpenTelemetry 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:
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,
},
});
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:
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:
instrumentation.ts / instrumentation.mjs
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();
No trace exporter is required. The ApitallySpanProcessor collects spans and attaches them to request logs instead.
Finally, run your application with the --import flag to load the instrumentation before your application code:
npx tsx --import ./instrumentation.ts app.ts
See the official OpenTelemetry guide for Node.js for more details.
Create custom spans
For custom operations that aren’t covered by library instrumentation, you can create spans manually using the startActiveSpan method from the standard OpenTelemetry API.
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();
});
}