Configuring SigNoz in Your Next.js Supabase SaaS Kit
Set up SigNoz for OpenTelemetry-native observability with self-hosted error tracking, traces, logs, and metrics.
Steps to configure SigNoz
Learn how to configure SigNoz in your Next.js Supabase SaaS kit.
SigNoz is an open-source, self-hostable observability platform built on OpenTelemetry. It provides traces, metrics, logs, and error tracking in one interface. Choose SigNoz if you want full control over your observability data and prefer OpenTelemetry standards.
Installing the SigNoz Plugin
SigNoz is distributed as a Makerkit plugin. Install it using the CLI:
npx @makerkit/cli@latest plugins installSelect SigNoz from the list. This creates the plugin at packages/plugins/signoz.
Add the plugin as a dependency to the monitoring package:
pnpm --filter "@kit/monitoring" add "@kit/signoz@workspace:*"Registering the Monitoring Services
Register SigNoz in the monitoring package by updating four files:
1. Add SigNoz to the provider enum
const MONITORING_PROVIDERS = [ 'sentry', 'signoz', // Add signoz here '',] as const;export const MONITORING_PROVIDER = z .enum(MONITORING_PROVIDERS) .optional() .transform((value) => value || undefined);2. Register the client provider
// Register the SigNoz providermonitoringProviderRegistry.register('signoz', async () => { const { SignozProvider } = await import('@kit/signoz/provider'); return { default: function SignozProviderWrapper({ children, }: React.PropsWithChildren) { return <SignozProvider>{children}</SignozProvider>; }, };});3. Register the instrumentation
instrumentationRegistry.register('signoz', async () => { const { register } = await import('@kit/signoz/instrumentation'); return { register, };});4. Register the server monitoring service
// Register the 'signoz' monitoring serviceserverMonitoringRegistry.register('signoz', async () => { const { SignozServerMonitoringService } = await import('@kit/signoz/server'); return new SignozServerMonitoringService();});Environment Variables
SigNoz requires several OpenTelemetry environment variables:
# Enable SigNoz as the monitoring providerNEXT_PUBLIC_MONITORING_PROVIDER=signoz# Service identificationNEXT_PUBLIC_OTEL_SERVICE_NAME=makerkitOTEL_RESOURCE_ATTRIBUTES="service.name=makerkit,service.version=1.0.0"# Client-side SigNoz configurationNEXT_PUBLIC_SIGNOZ_INGESTION_KEY=your_ingestion_keyNEXT_PUBLIC_SIGNOZ_INGESTION_URL=http://localhost:4318/v1/logs# Server-side OpenTelemetry configurationOTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/tracesOTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobufOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4318/v1/logsOTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=your_ingestion_key"Variable reference
| Variable | Description |
|---|---|
NEXT_PUBLIC_OTEL_SERVICE_NAME | Name shown in SigNoz dashboards |
OTEL_RESOURCE_ATTRIBUTES | Service metadata (name, version) |
NEXT_PUBLIC_SIGNOZ_INGESTION_KEY | Your SigNoz ingestion API key |
NEXT_PUBLIC_SIGNOZ_INGESTION_URL | Logs ingestion endpoint |
OTEL_EXPORTER_OTLP_ENDPOINT | Base OTLP endpoint |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT | Traces ingestion endpoint |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | Logs ingestion endpoint |
Running SigNoz Locally
For development, run SigNoz in Docker:
# Clone SigNozgit clone -b main https://github.com/SigNoz/signoz.git && cd signoz/deploy/# Start SigNozdocker compose -f docker/clickhouse-setup/docker-compose.yaml up -dSigNoz will be available at http://localhost:3301.
For detailed installation options, see the SigNoz Docker installation guide.
Local environment variables
When running SigNoz locally, use these endpoints:
NEXT_PUBLIC_SIGNOZ_INGESTION_URL=http://localhost:4318/v1/logsOTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/tracesOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4318/v1/logsFor local development, you can leave OTEL_EXPORTER_OTLP_HEADERS empty since no authentication is required.
Production Configuration
When deploying SigNoz to production (self-hosted or SigNoz Cloud):
Self-hosted
Update the endpoints to point to your SigNoz instance:
NEXT_PUBLIC_SIGNOZ_INGESTION_URL=https://signoz.yourdomain.com/v1/logsOTEL_EXPORTER_OTLP_ENDPOINT=https://signoz.yourdomain.comOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://signoz.yourdomain.com/v1/tracesOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://signoz.yourdomain.com/v1/logsSigNoz Cloud
If using SigNoz Cloud, update the endpoints and add your ingestion key:
NEXT_PUBLIC_SIGNOZ_INGESTION_KEY=your_cloud_ingestion_keyNEXT_PUBLIC_SIGNOZ_INGESTION_URL=https://ingest.{region}.signoz.cloud/v1/logsOTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.{region}.signoz.cloudOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.{region}.signoz.cloud/v1/tracesOTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://ingest.{region}.signoz.cloud/v1/logsOTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=your_cloud_ingestion_key"Replace {region} with your SigNoz Cloud region (e.g., us, eu).
Configuring Logging with Winston
Pino logging limitation
Due to compatibility issues between Next.js and the OpenTelemetry transport for Pino (Makerkit's default logger), logs cannot be sent to SigNoz using Pino. Switch to Winston for log ingestion.
1. Switch to Winston
Set the logger environment variable:
LOGGER=winston2. Register the Winston logger
// Register the Winston logger implementationloggerRegistry.register('winston', async () => { const { Logger: WinstonLogger } = await import('./impl/winston'); return WinstonLogger;});3. Configure Winston with OpenTelemetry
Follow the SigNoz Winston integration guide to configure the OpenTelemetry transport for Winston.
Example Winston configuration:
import winston from 'winston';const { combine, timestamp, json } = winston.format;export const Logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: combine( timestamp(), json() ), transports: [ new winston.transports.Console(), // Add OpenTelemetry transport for SigNoz ],});What SigNoz Captures
Traces
SigNoz captures distributed traces across your application:
- HTTP request traces
- Database query traces
- External API call traces
- Server Component render times
View traces in SigNoz under Traces to see the full request lifecycle.
Metrics
OpenTelemetry metrics are automatically collected:
- Request duration histograms
- Error rates
- Request counts by endpoint
Logs
When configured with Winston, logs flow to SigNoz:
- Application logs at all levels (debug, info, warn, error)
- Correlated with traces via trace IDs
- Searchable and filterable
Exceptions
Errors captured via the monitoring service appear in SigNoz with:
- Stack traces
- Request context
- Correlation with traces and logs
SigNoz vs Sentry
| Feature | SigNoz | Sentry |
|---|---|---|
| Self-hostable | Yes (primary use case) | Yes (limited) |
| OpenTelemetry native | Yes | No |
| Traces | Yes | Yes (via APM) |
| Logs | Yes | No |
| Metrics | Yes | No |
| Error tracking | Yes | Yes (primary focus) |
| Session replay | No | Yes |
| Source maps | Limited | Full support |
| Pricing | Free (self-hosted) | Usage-based |
Choose SigNoz when:
- You want to self-host your observability stack
- You prefer OpenTelemetry standards
- You need traces, logs, and metrics in one place
- You want predictable costs (self-hosted = infrastructure cost only)
Choose Sentry when:
- You want managed service with minimal setup
- You need advanced error tracking features
- You want session replay
- You prefer detailed source map integration
Troubleshooting
Traces not appearing
- Check OTLP endpoints: Verify all
OTEL_EXPORTER_OTLP_*variables are set - Check connectivity: Ensure your app can reach the SigNoz endpoints
- Check the SigNoz logs: Look for ingestion errors in SigNoz container logs
Logs not appearing
- Verify Winston is configured: Check
LOGGER=winstonis set - Check the OpenTelemetry transport: Ensure the Winston transport is correctly configured
- Check log levels: Verify your log level includes the logs you expect
Authentication errors
- Check ingestion key: Verify
signoz-ingestion-keyheader is set correctly - Check key format: The header value should be just the key, not
Bearer key