Browse documentation

Instrument

JavaScript and TypeScript

Instrument Node.js, browser, Express, and React applications with the Teml SDK.

Use @teml/sdk for Node.js, browser, Express, and React applications. The base package sends traces, metrics, logs, errors, diagnostic events, and customer identity; replay and LLM wrappers are opt-in subpath imports.

Install and start

After the registry release:

npm install @teml/sdk

During early access, use the package artifact or install path supplied during onboarding if the registry package is not available.

import { init } from '@teml/sdk';

const teml = await init({
  apiKey: process.env.TEML_API_KEY,
  serviceName: 'orders-api',
  serviceVersion: process.env.GIT_SHA,
  environment: process.env.NODE_ENV,
});

Keep one client for the process. Call await teml.stop() during graceful shutdown so buffered telemetry can finish exporting.

Capture a connected operation

teml.identify('user_8842', { email: 'buyer@acme.example', plan: 'pro' });

const span = teml.startSpan('process-order');
try {
  await processOrder();
} catch (error) {
  teml.captureError(error as Error, { tags: { component: 'checkout' } });
  throw error;
} finally {
  span.end();
}

Call teml.reset() on logout. In a multi-user server, prefer framework request context over changing the process-wide identity for every request.

Express and service propagation

import express from 'express';
import { TemlClient } from '@teml/sdk';
import { temlExpressErrorHandler, temlExpressMiddleware } from '@teml/sdk/node';

const app = express();
const teml = await new TemlClient({
  apiKey: process.env.TEML_API_KEY,
  serviceName: 'orders-api',
}).start();

app.use(temlExpressMiddleware(teml, { trustIncomingIdentity: false }));
// Register routes here.
app.use(temlExpressErrorHandler(teml)); // Always last.

The middleware extracts W3C trace context. Identity baggage is ignored by default because a public client can forge it. Change trustIncomingIdentity to true only behind a gateway that strips and recreates client-supplied baggage.

For outbound Node http/https propagation, preload the SDK before application modules and allow only trusted destinations:

node --import @teml/sdk/node/register ./app.mjs
import { initNode } from '@teml/sdk/node';

const teml = await initNode({
  apiKey: process.env.TEML_API_KEY,
  serviceName: 'orders-api',
  propagateTraceHeaderUrls: ['https://billing.internal.example'],
});

Node’s global fetch is not instrumented by this preload. Use an instrumented http/https client when automatic propagation is required.

React and browser credentials

import { TemlClient } from '@teml/sdk';
import { TemlErrorBoundary, TemlProvider } from '@teml/sdk/react';

const teml = await new TemlClient({
  apiKey: import.meta.env.VITE_TEML_API_KEY,
  serviceName: 'web',
  release: import.meta.env.VITE_APP_RELEASE,
}).start();

root.render(
  <TemlProvider client={teml}>
    <TemlErrorBoundary client={teml} fallback={<ErrorPage />}>
      <App />
    </TemlErrorBoundary>
  </TemlProvider>,
);

Use a project-scoped custom key with ingest:write and analytics:write in browser builds. Add replay:write only when recording replay. Client-side feature flags additionally need flags:read; because that exposes flag configuration to the client, never put secrets in targeting rules or payloads. Never expose other read, management, or MCP scopes. Restrict cross-origin propagation with propagateTraceHeaderCorsUrls.

Logs, replay, and AI calls

Use the client’s log and error methods for manual signals. Import @teml/sdk/replay only on pages where browser replay is needed; inputs are masked by default. The @teml/sdk/openai and @teml/sdk/anthropic wrappers record non-streaming model calls, with content capture off by default.

Verify and recover

Generate one request for a known test customer, then open Customers and confirm the error, trace, and logs share that customer and trace. If nothing arrives, enable TEML_DEBUG=true, confirm the key and endpoint, and stop the process gracefully before checking again.