Setup Phoenix tracing in TypeScript/JavaScript with @arizeai/phoenix-otel.
| Attribute | Value |
|---|---|
| Priority | Critical - required for all tracing |
| Setup Time | <5 min |
npm install @arizeai/phoenix-otelimport { register } from "@arizeai/phoenix-otel";
register({ projectName: "my-app" });Connects to http://localhost:6006 by default.
import { register } from "@arizeai/phoenix-otel";
register({
projectName: "my-app",
url: "http://localhost:6006",
apiKey: process.env.PHOENIX_API_KEY,
batch: true
});Environment variables:
export PHOENIX_API_KEY="your-api-key"
export PHOENIX_COLLECTOR_ENDPOINT="http://localhost:6006"
export PHOENIX_PROJECT_NAME="my-app"CommonJS (automatic):
const { register } = require("@arizeai/phoenix-otel");
register({ projectName: "my-app" });
const OpenAI = require("openai");ESM (manual instrumentation required):
import { register, registerInstrumentations } from "@arizeai/phoenix-otel";
import { OpenAIInstrumentation } from "@arizeai/openinference-instrumentation-openai";
import OpenAI from "openai";
register({ projectName: "my-app" });
const instrumentation = new OpenAIInstrumentation();
instrumentation.manuallyInstrument(OpenAI);
registerInstrumentations({ instrumentations: [instrumentation] });Why: ESM imports are hoisted, so manuallyInstrument() is needed.
Next.js (App Router):
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
const { register } = await import("@arizeai/phoenix-otel");
register({ projectName: "my-nextjs-app" });
}
}Express.js:
import { register } from "@arizeai/phoenix-otel";
register({ projectName: "my-express-app" });
const app = express();CRITICAL: Spans may not be exported if still queued in the processor when your process exits. Call provider.shutdown() to explicitly flush before exit.
Standard pattern:
const provider = register({
projectName: "my-app",
batch: true,
});
async function main() {
await doWork();
await provider.shutdown(); // Flush spans before exit
}
main().catch(async (error) => {
console.error(error);
await provider.shutdown(); // Flush on error too
process.exit(1);
});Alternative:
// Use batch: false for immediate export (no shutdown needed)
register({
projectName: "my-app",
batch: false,
});For production patterns including graceful termination, see production-typescript.md.
- Open Phoenix UI:
http://localhost:6006 - Run your application
- Check for traces in your project
Enable diagnostic logging:
import { DiagLogLevel, register } from "@arizeai/phoenix-otel";
register({
projectName: "my-app",
diagLogLevel: DiagLogLevel.DEBUG,
});No traces:
- Verify
PHOENIX_COLLECTOR_ENDPOINTis correct - Set
PHOENIX_API_KEYfor Phoenix Cloud - For ESM: Ensure
manuallyInstrument()is called - With
batch: true: Callprovider.shutdown()before exit to flush queued spans (see Flushing Spans section)
Traces missing:
- With
batch: true: Callawait provider.shutdown()before process exit to flush queued spans - Alternative: Set
batch: falsefor immediate export (no shutdown needed)
Missing attributes:
- Check instrumentation is registered (ESM requires manual setup)
- See
instrumentation-auto-typescript.md
- Auto-instrumentation:
instrumentation-auto-typescript.md - Manual instrumentation:
instrumentation-manual-typescript.md - API docs: https://arize-ai.github.io/phoenix/