llms.txt
llms.txt

Observability

2 min read

Listen to Farm runtime events for server lifecycle, route matching, rendering, API routes, integrations, storage, cache, PPR, builds, plugins, and errors.

Subscribe to events

farm.config.ts
import { onFarmEvent } from "@farmjs/core/observability";onFarmEvent((event) => {  if (event.level === "error") {    console.error("[farm]", event.type, event);  }});

Event families

Family Examples
Server server.start, server.ready, server.shutdown
Routing route.discovered, route.matched, route.notFound, route.redirect
Rendering render.start, render.complete, render.stream.shellReady, render.error
Cache cache.hit, cache.miss, cache.set, cache.revalidateTag
PPR ppr.shell.hit, ppr.shell.cached, ppr.shell.invalidated
Middleware middleware.start, middleware.complete, middleware.shortCircuit, middleware.error
Integrations integration.ready, integration.api.call.start, integration.webhook.verified
Storage storage.query.start, storage.schema.ready
Build build.start, routes.generated, types.generated, manifest.generated

Configure in farm.config.ts

Use config-level observability when an app should log or forward events from startup.

import { defineConfig } from "@farmjs/core";export default defineConfig({  observability: {    logs: true,    events: ["cache.hit", "cache.miss", "ppr.shell.cached"],    onEvent(event) {      if (event.type === "cache.miss") {        console.log("Cache miss", event.key, event.reason);      }    },  },});

events is optional. Leave it out to receive every emitted event.

Runtime subscription

Use onFarmEvent for tests, local debugging, or integration packages that want to register listeners without owning app config.

import { onFarmEvent } from "@farmjs/core/observability";const unsubscribe = onFarmEvent((event) => {  if (event.type === "integration.webhook.failed") {    console.error(event.integration, event.reason);  }});unsubscribe();

Useful event types

Area Events
Cache cache.hit, cache.miss, cache.set, cache.stale, cache.bypass, cache.invalidated, cache.revalidatePath, cache.revalidateTag, cache.updateTag, cache.error
PPR ppr.shell.hit, ppr.shell.miss, ppr.shell.cached, ppr.shell.bypass, ppr.shell.invalidated, ppr.suspense.holeDetected, ppr.refresh.start, ppr.refresh.complete, ppr.refresh.error
API api.request.start, api.request.complete, api.validation.failed, api.error
Integrations integration.registered, integration.config.validated, integration.ready, integration.disposed, integration.api.call.start, integration.api.call.complete, integration.webhook.verified, integration.webhook.failed
Middleware middleware.start, middleware.complete, middleware.shortCircuit, middleware.error
Storage storage.query.start, storage.query.complete, storage.query.error, storage.schema.ready, storage.schema.error

Middleware events include the matched middleware route, request pathname, middleware file/config name, duration for completes, status for short circuits, and the thrown error for failures.

Middleware event payloads

Middleware events are emitted for both farm.config.ts middleware entries and src/app/**/middleware.ts files in development and production.

Event Payload
middleware.start route, pathname, name
middleware.complete route, pathname, name, durationMs
middleware.shortCircuit route, pathname, name, status
middleware.error route, pathname, name, error
import { defineConfig } from "@farmjs/core";export default defineConfig({  observability: {    onEvent(event) {      if (event.type === "middleware.shortCircuit") {        console.log(event.pathname, event.status);      }    },  },});

Production notes

  • Filter high-volume events before shipping them to a log drain.
  • Attach request IDs in middleware so event streams can be correlated.
  • Treat event payloads as operational metadata; do not put secrets in event fields.
  • Watch api.validation.failed, integration.webhook.failed, cache.error, and ppr.refresh.error in production.