Learning tRPC - Observability, Tracing & Monitoring
Episode 14 of 19

Learning tRPC - Observability, Tracing & Monitoring

This episode makes the tRPC API observable: monitoring through OpenTelemetry, metrics, and logs, tracing requests end-to-end from the client to the server, as well as debugging with the built-in logger and devtools.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

A production application cannot be trusted without observability — the ability to understand what is happening inside the system through logs, metrics, and traces. Episode 14 discusses how to apply all three to tRPC: monitoring calls, end-to-end tracing from client to server, and debugging with built-in tooling.

You will learn to measure: how often a procedure is called, how long its execution takes, and at what point a request slows down.

Monitoring with OpenTelemetry, Metrics, and Logs

The Three Pillars of Observability

  • Logs: structured event records, such as "procedure user.byId was called".
  • Metrics: aggregated numbers like requests per second and latency.
  • Traces: the journey of one request through all services.

tRPC makes all three easy because every call passes through the middleware pipeline. Grab the procedure metadata with path and type:

Structured log for every procedure
const observe = t.middleware(async ({ path, type, ctx, next }) => {
  const mulai = Date.now();
  const hasil = await next();
  const durasi = Date.now() - mulai;
 
  logger.info("trpc.request", {
    path,
    type,
    userId: ctx.userId,
    durasiMs: durasi,
    ok: hasil.ok,
  });
 
  if (typeof metrics?.histogram === "function") {
    metrics.histogram("trpc.duration", durasi, { path, type });
  }
  return hasil;
});

The observe middleware records every call to a structured log and also collects a duration histogram per path. One capture point covers the whole API — that is the power of tRPC middleware for observability.

OpenTelemetry Integration

OpenTelemetry provides the standard for traces and metrics. Install the SDK, then connect the tRPC middleware to the global tracer:

Install OpenTelemetry
npm install @opentelemetry/api @opentelemetry/sdk-node
npm install @opentelemetry/instrumentation-http
Trace middleware with OpenTelemetry
import { trace, SpanStatusCode } from "@opentelemetry/api";
 
const tracing = t.middleware(async ({ path, next }) => {
  const tracer = trace.getTracer("trpc");
  return tracer.startActiveSpan(`trpc.${path}`, async (span) => {
    try {
      const hasil = await next();
      span.setStatus({ code: SpanStatusCode.OK });
      return hasil;
    } catch (err) {
      span.setStatus({ code: SpanStatusCode.ERROR });
      span.recordException(err as Error);
      throw err;
    } finally {
      span.end();
    }
  });
});

tracer.startActiveSpan creates a span per procedure. Because the span is named from path, you can see the duration of every procedure in Jaeger, Zipkin, or other observability platforms.

End-to-End Tracing

Linking Client and Server

Tracing has full value when a single trace connects from the user's click in the browser to the database query. The key is propagating traceparent in the request header:

Client propagating trace context
import { context, trace } from "@opentelemetry/api";
 
const client = createTRPCClient<AppRouter>({
  links: [
    httpBatchLink({
      url: "/api/trpc",
      headers: () => {
        const span = trace.getActiveSpan();
        if (!span) return {};
        return { traceparent: span.spanContext().traceId };
      },
    }),
  ],
});

The server reads traceparent in createContext and uses it as the parent span. The result: a single trace showing the full journey — client, HTTP, tRPC middleware, and the database query.

Key Metrics to Monitor

Some metrics you should always monitor:

  • Call count per procedure — to see popular endpoints and anomalies.
  • p95 and p99 duration — not just averages, so slow spikes are visible.
  • Error rate — the number of failures divided by total calls.
  • Subscription success ratio — WebSocket connections that drop.

Build a simple dashboard from these metrics on your favorite platform — starting with a single duration-per-procedure chart is already very helpful.

Debugging with Devtools and the Built-in Logger

Since episode 6, loggerLink has been the fastest debugging companion:

LoggerLink for debugging
import { loggerLink } from "@trpc/client";
 
loggerLink({
  enabled: (opts) =>
    process.env.NODE_ENV === "development" || opts.direction === "down",
  colorMode: "ansi",
});

The configuration above shows full logs in development, and in production only logs incoming responses — enough to see errors without noise. colorMode: "ansi" adds color that makes logs easier to read in the terminal.

React Devtools

For UI debugging, install React Query Devtools. Because tRPC React runs on top of React Query, these devtools display the status of all queries and mutations:

Install React Query Devtools
npm install --save-dev @tanstack/react-query-devtools
Mounting ReactQueryDevtools
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
 
<trpc.Provider client={trpcClient} queryClient={queryClient}>
  <QueryClientProvider client={queryClient}>
    {children}
    <ReactQueryDevtools initialIsOpen={false} />
  </QueryClientProvider>
</trpc.Provider>;

Devtools display active queries, cached data, stale times, and buttons to refetch or invalidate manually — the fastest way to understand why a page shows particular data.

Tip

Start observability small: install loggerLink and a duration middleware first. Data gathered over a week will show which endpoints are worth tracing more deeply.

Conclusion

Episode 14 makes your tRPC API transparent: monitoring with structured logs and metrics, end-to-end tracing with OpenTelemetry connecting the client to the server, and quick debugging with loggerLink and React Query Devtools.

Key takeaways:

  • tRPC middleware is a single capture point for logs, metrics, and traces.
  • path and type give per-procedure observability dimensions.
  • OpenTelemetry creates a span named path for every call.
  • Propagate traceparent in the header for end-to-end tracing.
  • Monitor p95 duration and error rate, not just averages.
  • loggerLink and React Query Devtools speed up daily debugging.

In the next episode, episode 15, we will discuss resilience & fault tolerance — retry, exponential backoff, and error boundary patterns on the client, data fallback strategies and downtime handling, as well as graceful shutdown for a tRPC server in production.

Learning tRPC - Observability, Tracing & Monitoring | Learning tRPC