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.