Learn GraphQL - Production Monitoring & Observability
Episode 24 of 51

Learn GraphQL - Production Monitoring & Observability

Episode 24 builds production observability: structured logging with Pino, Apollo Studio setup for query analytics and schema checks, OpenTelemetry integration for distributed tracing, Prometheus metrics and Grafana dashboards, APM tools like Sentry, and health checks.

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

Introduction

An API that can't be observed is like walking in the dark. Episode 24 builds observability for production GraphQL: logging, tracing, metrics, and health checks that let you see what's happening inside the server from the outside. We'll cover structured logging with Pino, query analytics with Apollo Studio, distributed tracing with OpenTelemetry, metrics with Prometheus and Grafana, APM for error tracking, and health checks.

Logging Strategies

Structured Logging with Pino

Logs in production must be structured — JSON with consistent fields — so they can be filtered and aggregated. Pino is a popular choice because it's fast; install it with npm install pino:

JSStructured logger
import pino from "pino";
 
export const logger = pino({
  level: process.env.LOG_LEVEL ?? "info",
});

Logging Queries and Resolvers

Integrate the logger into the context so every resolver uses the same logger — create a child logger per request with logger.child({ requestId: crypto.randomUUID() }):

JSLogger in the context
const { url } = await startStandaloneServer(server, {
  context: async ({ req }) => ({
    logger: logger.child({ requestId: crypto.randomUUID() }),
    user,
  }),
});
JSPlugin to log resolver duration
import { ApolloServerPlugin } from "@apollo/server";
 
const logPlugin = {
  async requestDidStart() {
    return {
      async willSendResponse({ response, contextValue }) {
        contextValue.logger.info({ body: response.body }, "response dikirim");
      },
    };
  },
};

Apollo Studio

Query Analytics and Error Tracking

Apollo Studio is Apollo's observability platform that shows GraphQL operations live. After registering your graph and filling in the key:

JSConnect to Apollo Studio
const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [ApolloServerPluginUsageReporting({ sendErrors: { unmodified: true } })],
});

OpenTelemetry Integration

Distributed Tracing

In a microservices architecture, a query passes through many services. OpenTelemetry standardizes tracing so one request's journey can be tracked across services; install it with npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node:

JSInitialize OpenTelemetry
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
 
const sdk = new NodeSDK({
  traceExporter: { url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT },
  instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();

The core concept: every request carries a trace id, is split into spans (one per resolver or per database query), and the context flows through propagation so the receiving service stays within the same trace. This makes inter-service bottlenecks clearly visible.

Metrics and APM

Prometheus and Grafana

For metrics, expose Prometheus metrics from the server; install with npm install prom-client:

JSCustom metrics
import { Counter, Histogram } from "prom-client";
 
const queriesTotal = new Counter({
  name: "graphql_queries_total",
  help: "Jumlah query",
  labelNames: ["operationName"],
});
 
const queryDuration = new Histogram({
  name: "graphql_query_duration_seconds",
  help: "Durasi query",
  labelNames: ["operationName"],
});

Prometheus pulls metrics from the /metrics endpoint, and Grafana displays them as dashboards. Metrics you must have: total queries per operation, duration histograms, error counts, and database health.

APM and Sentry

For error tracking, integrate Sentry; install with npm install @sentry/node:

JSSentry for error tracking
import * as Sentry from "@sentry/node";
 
Sentry.init({ dsn: process.env.SENTRY_DSN });
 
const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    {
      async requestDidStart() {
        return {
      async didEncounterErrors({ errors }) {
        errors.forEach(Sentry.captureException);
      },
        };
      },
    },
  ],
});

Sentry shows errors with their stack traces, users, and request context — replacing the habit of "checking logs on the server". Alternatives: Datadog and New Relic for integrated APM.

Health Checks

Readiness and Liveness

Health checks tell the orchestrator (Kubernetes, load balancer) whether the application is healthy:

  • Liveness: "is the process still alive?" — if it fails, the process is restarted.
  • Readiness: "is it ready to receive traffic?" — if it fails, traffic is redirected.
JSHealth check endpoints
app.get("/health/live", (req, res) => {
  res.json({ status: "ok" });
});
 
app.get("/health/ready", async (req, res) => {
  try {
    await prisma.$queryRaw`SELECT 1`;
    res.json({ status: "ok" });
  } catch {
    res.status(503).json({ status: "degraded" });
  }
});

The readiness check tests dependencies (database, Redis) so the load balancer knows when the app is actually ready. This is required before automated deployment — we'll use it again in episodes 31 and 35.

Conclusion

Key takeaways:

  • Structured logging with Pino and a requestId makes tracking easy.
  • Apollo Studio gives query analytics and automatic schema checks.
  • OpenTelemetry standardizes distributed tracing across services.
  • Prometheus and Grafana display query, error, and duration metrics.
  • Sentry captures production errors with full context.
  • Liveness and readiness health checks are the foundation of healthy deployments.

In the next episode, episode 25, you'll learn about Apollo Client fundamentals — setting up the client and ApolloProvider, the useQuery hook with polling and refetch, useMutation with optimistic UI, InMemoryCache management, and local state with reactive variables. The frontend will be fully connected to GraphQL!

Learn GraphQL - Production Monitoring & Observability | Learn GraphQL