Skip to main content

Logging

Formbricks follows Next.js best practices with all logs being written to stdout/stderr, making it easy to collect and forward logs to your preferred logging solution.

Log Levels

  • debug: Detailed information for debugging purposes.
  • info: General information about the system’s operation.
  • warn: Potential issues that may require attention.
  • error: Errors that occur during the operation of the system.
  • fatal: Critical errors that cause the system to crash.

Log Format

Formbricks uses JSON format for logs, which is structured and easy to parse. Each log entry includes:
  • level: The log level (e.g., info, error).
  • time: Timestamp of the log entry in milliseconds since epoch.
  • pid: Process ID of the application.
  • hostname: Hostname of the server where the log was generated.
  • requestId: Unique identifier for the request (if applicable).
  • userId: Unique identifier for the user (if applicable).
  • msg: The log message.
  • stack: Stack trace (if applicable).
  • data: Additional data related to the log entry.

Example Log Entry

Configuring Log Levels

You can configure the minimum log level using the LOG_LEVEL environment variable. Valid values: debug, info, warn, error, fatal. The default log level in production environments is warn, while in development environments it is debug.

AccessDocker Container Logs

Access Kubernetes Pod Logs

Log Forwarding

Since all logs are written to stdout/stderr, you can integrate with various logging solutions:
  • ELK Stack (Elasticsearch, Logstash, Kibana)
  • Fluentd/Fluent Bit
  • Datadog
  • Splunk
  • CloudWatch Logs (AWS)

OpenTelemetry Integration

Formbricks offers two complementary observability approaches:
  1. Next.js OpenTelemetry - For tracing and APM integration
  2. Prometheus Integration - For metrics collection and monitoring

Next.js OpenTelemetry for Tracing

Formbricks leverages Next.js’s built-in OpenTelemetry instrumentation for tracing and APM integration. When enabled, it automatically instruments various aspects of your application, providing detailed insights into request flows and performance. To enable Next.js OpenTelemetry, set the following environment variables:

Default Next.js Instrumentation

The Next.js OpenTelemetry integration automatically tracks:
  • HTTP requests and responses
  • Route rendering
  • API route execution
  • Server-side operations
  • Database queries
  • External API calls

Supported Backends for Tracing

OpenTelemetry trace data can be exported to various observability platforms:
Tracing Backends
  • Jaeger
  • Zipkin
  • Tempo
APM & Full-Stack Observability Platforms
  • New Relic
  • Datadog
  • Dynatrace
  • Azure Monitor
  • AWS X-Ray
  • Google Cloud Trace

Prometheus Integration

Formbricks implements a dedicated Prometheus metrics exporter using OpenTelemetry. This integration runs a metrics server on a separate port and exposes metrics in Prometheus format for scraping. It focuses specifically on host and runtime metrics rather than application-specific traces.

Configuration

To enable and configure the Prometheus exporter, set the following environment variables:
The PROMETHEUS_ENABLED environment variable must be set to 1 to enable metrics collection. The PROMETHEUS_EXPORTER_PORT variable is optional and defaults to 9464 if not specified. The exporter listens on all network interfaces (0.0.0.0) and exposes metrics at the /metrics endpoint.

Available Metrics

The metrics exported by the Prometheus integration include:
  • Host Metrics:
    • CPU usage (user, system, idle)
    • Memory usage (used, free, cached)
    • Disk I/O (reads, writes)
    • Network I/O (bytes in/out, packets in/out)
  • HTTP Metrics:
    • Request counts
    • Request durations
    • Error rates
  • Runtime Metrics:
    • Garbage collection frequency and duration
    • Event loop lag
    • Heap statistics (size, used, available)
  • v3 Responses API Metrics — the two counters and the two unresolved counters below are exported under exactly these series names through both the Prometheus exporter and an OTLP collector. The two histograms are metric families: querying the family name returns nothing, and their queryable series are the _bucket, _sum and _count suffixes.
    • formbricks_api_v3_responses_reads_total — one count per list, count or get, at the route boundary, so a 401, 429 or 400 counts too. Attributes: operation, via (ui, api, mcp), status_class, and filters (the sorted filter keys the caller used, never their values).
    • formbricks_api_v3_responses_read_duration_seconds (histogram family) — wall-clock seconds per read, by operation, via and status_class. Series: formbricks_api_v3_responses_read_duration_seconds_bucket, ..._sum, ..._count. For example, the p95 per operation: histogram_quantile(0.95, sum by (le, operation) (rate(formbricks_api_v3_responses_read_duration_seconds_bucket[5m]))).
    • formbricks_api_v3_responses_page_surveys (histogram family) — how many distinct surveys one list page spans, i.e. the size of its single survey query. Series: formbricks_api_v3_responses_page_surveys_bucket, ..._sum, ..._count. The first bucket boundary is 0.5, so formbricks_api_v3_responses_page_surveys_bucket{le="0.5"} counts empty pages and is distinguishable from one-survey pages.
    • formbricks_api_v3_responses_unresolved_responses_total and formbricks_api_v3_responses_unresolved_entries_total — responses served with a non-empty unresolved[], and its entries by reason. These count every read, so a client polling one unchanged response raises them without any survey edit, and valueShapeMismatch can be legacy malformed data rather than a definition change. Read unresolved_responses_total over reads_total by operation as unresolved responses served per read (a list page can carry several, so for list this can exceed 1; for get it is the share of affected reads), and use unresolved_entries_total grouped by reason for the breakdown, rather than a rising raw count.

Collecting Metrics

You can scrape metrics from your Prometheus server by adding the following to your Prometheus configuration:

Resource Attributes

The metrics include resource attributes automatically detected from:
  • Environment variables
  • Process information
  • Host information
These attributes can help you filter and group metrics in your dashboards.

Health Checks

Available endpoints:
Use these endpoints for monitoring system health in container orchestration and monitoring tools.

AuthZed and SpiceDB

Self-hosted v6 upgrades use a maintenance window and do not require a v5 bridge or shadow comparisons. Monitor projection failures, disabled outcomes, schema drift, authorization operational errors, and latency. The v6 direct-authority release exposes authoritative allow/deny/operational-error and latency metrics plus outbox backlog, revocation delivery latency, oldest pending item, dead-letter, reconciliation drift, and repair signals. The fixed revocation thresholds warn at 15 seconds, become critical at 45 seconds, and make protected authorization fail closed at 60 seconds; the 60-second bound is not configurable. A dead-lettered revocation triggers warning, critical, and fail-closed states immediately, regardless of its age. Follow the release-matched AuthZed Operations guide during upgrade rather than treating v5 comparison metrics as a v6 rollout gate. For every release, also monitor SpiceDB pod availability, datastore migrations, PostgreSQL pool saturation, dispatch latency, and cache behavior. The general Formbricks /health endpoint intentionally stays independent from SpiceDB. Use the release-matched formbricks-authzed health command for authenticated authorization health checks. The AuthZed Operations guide contains metric names, PromQL examples, starting alert thresholds, stable error codes, and the outage-repair runbook.