SigNoz
Docs
PricingCustomers
Get Started - Free
Docs
IntroductionContributingMigrate from DatadogSigNoz API
OpenTelemetry
What is OpenTelemetryOpenTelemetry Collector GuideOpenTelemetry Demo
Community
Support
Slack
X
Launch Week
Changelog
Dashboard Templates
DevOps Wordle
Newsletter
KubeCon, Atlanta 2025
More
SigNoz vs DatadogSigNoz vs New RelicSigNoz vs GrafanaSigNoz vs Dynatrace
Careers
AboutTermsPrivacySecurity & Compliance
SigNoz Logo
SigNoz
All systems operational
HIPAASOC-2
SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.

Send logs from Logrus to SigNoz using OpenTelemetry

Most steps are identical. To adapt this guide, update the endpoint and remove the ingestion key header as shown in Cloud → Self-Hosted.

Prerequisites

  • A running Golang application that uses the Logrus logger
  • An instance of SigNoz (either Cloud or Self-Hosted)

Send logs to SigNoz

A VM is a virtual computer that runs on physical hardware. This includes:

  • Cloud VMs: AWS EC2, Google Compute Engine, Azure VMs, DigitalOcean Droplets
  • On-premise VMs: VMware, VirtualBox, Hyper-V, KVM
  • Bare metal servers: Physical servers running Linux/Unix directly

Use this section if you're deploying your application directly on a server or VM without containerization.

Step 1. Set environment variables

export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
export OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
export OTEL_SERVICE_NAME="<service_name>"

Verify these values:

  • <region>: Your SigNoz Cloud region.
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service_name>: Your service name.

Step 1. Set environment variables

Add these environment variables to your deployment manifest:

env:
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: 'https://ingest.<region>.signoz.cloud:443'
  - name: OTEL_EXPORTER_OTLP_HEADERS
    value: 'signoz-ingestion-key=<your-ingestion-key>'
  - name: OTEL_SERVICE_NAME
    value: '<service_name>'

Verify these values:

  • <region>: Your SigNoz Cloud region.
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service_name>: Your service name.

If using the k8s-infra chart (which auto-collects container logs), disable log collection for this application to prevent duplicates.

See how to disable log collection →

Step 1. Set environment variables in Dockerfile

Add environment variables to your Dockerfile:

Dockerfile
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .

ENV OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
ENV OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
ENV OTEL_SERVICE_NAME="<service_name>"

CMD ["./main"]

Or pass them at runtime:

docker run -e OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443" \
    -e OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>" \
    -e OTEL_SERVICE_NAME="<service_name>" \
    your-image:latest

Verify these values:

  • <region>: Your SigNoz Cloud region.
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service_name>: Your service name.

Step 1. Set environment variables (PowerShell)

$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://ingest.<region>.signoz.cloud:443"
$env:OTEL_EXPORTER_OTLP_HEADERS = "signoz-ingestion-key=<your-ingestion-key>"
$env:OTEL_SERVICE_NAME = "<service_name>"

Verify these values:

  • <region>: Your SigNoz Cloud region.
  • <your-ingestion-key>: Your SigNoz ingestion key.
  • <service_name>: Your service name.

Step 2. Install dependencies

In the root folder of your Go application, run:

go get \
  github.com/sirupsen/logrus \
  go.opentelemetry.io/contrib/bridges/otellogrus \
  go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp \
  go.opentelemetry.io/otel/sdk/log

Step 3. Instrument your application

Add the following code to your main.go file:

main.go
package main

import (
	"context"
	"log"

	"github.com/sirupsen/logrus"
	"go.opentelemetry.io/contrib/bridges/otellogrus"
	"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
	otel_log "go.opentelemetry.io/otel/sdk/log"
)

func main() {
	ctx := context.Background()

	// Reads OTEL_EXPORTER_OTLP_ENDPOINT from env and initializes the OTLP HTTP log exporter
	logExporter, err := otlploghttp.New(ctx)
	if err != nil {
		log.Fatal(err)
	}

	// Wraps the exporter in a LoggerProvider with a batch processor
	logProvider := otel_log.NewLoggerProvider(
		otel_log.WithProcessor(
			otel_log.NewBatchProcessor(logExporter),
		),
	)
	defer logProvider.Shutdown(ctx)

	// Registers the hook globally. All logrus.Info/Warn/Error calls are exported as OTel logs
	hook := otellogrus.NewHook("signoz-golang", otellogrus.WithLoggerProvider(logProvider))
	logrus.AddHook(hook)

	logrus.Info("Hello from Logrus via OpenTelemetry")
}
  1. Creates an OTLP HTTP log exporter that sends logs to the endpoint defined by OTEL_EXPORTER_OTLP_ENDPOINT.
  2. Wraps the exporter in a LoggerProvider with a batch processor for efficient log delivery.
  3. Creates a Logrus hook via otellogrus.NewHook and registers it globally with logrus.AddHook.
  4. Every logrus.Info, logrus.Warn, logrus.Error, etc. call is now captured and exported as OpenTelemetry logs.

Step 4. Run your application

go run main.go

The environment variables you set in Step 1 are automatically read by the OTLP exporter.

With Trace Correlation (Advanced)

Correlate Logrus logs with OpenTelemetry traces by injecting trace_id and span_id fields into your structured logs.

Install additional dependencies

go get \
  github.com/sirupsen/logrus \
  go.opentelemetry.io/contrib/bridges/otellogrus \
  go.opentelemetry.io/otel \
  go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp \
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \
  go.opentelemetry.io/otel/sdk/log \
  go.opentelemetry.io/otel/sdk/trace \
  go.opentelemetry.io/otel/trace

Instrument your application

Add the following code to your main.go file:

main.go
package main

import (
	"context"
	"log"

	"github.com/sirupsen/logrus"
	"go.opentelemetry.io/contrib/bridges/otellogrus"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	otel_log "go.opentelemetry.io/otel/sdk/log"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	oteltrace "go.opentelemetry.io/otel/trace"
)

// Extracts trace correlation details from an OpenTelemetry span
func LogrusFields(span oteltrace.Span) logrus.Fields {
	return logrus.Fields{
		"span_id":  span.SpanContext().SpanID().String(),
		"trace_id": span.SpanContext().TraceID().String(),
	}
}

func main() {
	ctx := context.Background()

	// Reads OTEL_EXPORTER_OTLP_ENDPOINT from env and initializes the OTLP HTTP log exporter
	logExporter, err := otlploghttp.New(ctx)
	if err != nil {
		log.Fatal(err)
	}

	// Wraps the exporter in a LoggerProvider with a batch processor
	logProvider := otel_log.NewLoggerProvider(
		otel_log.WithProcessor(
			otel_log.NewBatchProcessor(logExporter),
		),
	)
	defer logProvider.Shutdown(ctx)

	// Registers the hook globally. All logrus.Info/Warn/Error calls are exported as OTel logs
	hook := otellogrus.NewHook("signoz-golang", otellogrus.WithLoggerProvider(logProvider))
	logrus.AddHook(hook)

	// Initializes the OTLP HTTP trace exporter
	traceExporter, err := otlptracehttp.New(ctx)
	if err != nil {
		log.Fatal(err)
	}

	// Configures the TracerProvider with a batch processor and always sample
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithSampler(sdktrace.AlwaysSample()),
		sdktrace.WithBatcher(traceExporter),
	)
	defer tp.Shutdown(ctx)

	// Registers the TracerProvider globally
	otel.SetTracerProvider(tp)

	// Starts a sample span
	tracer := otel.GetTracerProvider().Tracer("signoz-tracer")
	ctx, span := tracer.Start(ctx, "signoz-span")
	defer span.End()

	// Injects trace correlation details into structured log fields
	logrus.WithContext(ctx).WithFields(LogrusFields(span)).Info("Logrus log with trace correlation")
	logrus.Info("Logrus log without trace correlation")
}
  1. Sets up both an OTLP log exporter and an OTLP trace exporter.
  2. Creates a LoggerProvider for logs and a TracerProvider for traces.
  3. Registers a Logrus hook to send all logs through OpenTelemetry.
  4. Starts a span and extracts its trace_id and span_id via LogrusFields.
  5. Uses logrus.WithContext(ctx).WithFields(...) to attach trace IDs as structured fields to the log entry.

Run your application

go run main.go

The environment variables you set in Step 1 are automatically read by the OTLP exporter.

Validate

Open the Logs section in your SigNoz dashboard. You should see log entries from your Logrus logger.

If you followed the With Trace Correlation section, the trace_id and span_id fields appear as indexed attributes on each log entry, letting you jump from a log to its corresponding trace.

Logrus log with trace correlation in SigNoz
Logrus log entry with trace_id and span_id fields for trace correlation

Setup OpenTelemetry Collector (Optional)

What is the OpenTelemetry Collector?

The OTel Collector sits between your application and SigNoz. Your app sends telemetry to the Collector, which then forwards it to SigNoz.

Why use it?

  • Filtering and sampling — Drop noisy logs or sample traces before they leave your infrastructure.
  • Lightweight applications — Offload batching, retries, and compression to the Collector.
  • Resource enrichment — The Collector can tag data with Kubernetes pod names, cloud regions, or host metadata.
  • Multi-backend routing — Send telemetry to multiple destinations without changing your application code.

Collector configuration

The default Collector configuration already includes the otlp receiver. Point your application to the Collector endpoint:

OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" \
OTEL_SERVICE_NAME="<service_name>" \
go run main.go

See Switch from direct export to Collector for step-by-step instructions to convert your setup.

For more details, see Why use the OpenTelemetry Collector? and the Collector configuration guide.

Troubleshooting

No logs appearing in SigNoz

  • Verify OTEL_EXPORTER_OTLP_ENDPOINT points to the correct endpoint and port (443 for Cloud, 4318 for self-hosted).
  • For SigNoz Cloud, confirm OTEL_EXPORTER_OTLP_HEADERS contains a valid ingestion key.
  • Ensure defer logProvider.Shutdown(ctx) is called before your application exits. Without it, buffered logs may not flush.
  • Check that your application emits logs via logrus.Info, logrus.Error, etc. after the hook is registered.

Trace IDs not appearing in logs

  • Confirm you are using logrus.WithContext(ctx).WithFields(LogrusFields(span)) and not just logrus.Info().
  • Verify the span is active and not already ended when the log is emitted.
  • Check that the oteltrace import is "go.opentelemetry.io/otel/trace" and LogrusFields correctly extracts span.SpanContext().

Next Steps

  • Query and filter logs
  • Set up log-based alerts
  • Correlate logs with traces

If you need help with the steps in this topic, please reach out to us on SigNoz Community Slack.

If you are a SigNoz Cloud user, please use in product chat support located at the bottom right corner of your SigNoz instance or contact us at cloud-support@signoz.io.

Last updated: April 13, 2026

Edit on GitHub

Was this page helpful?

Your response helps us improve this page.

Prev
Bunyan Node.js
Next
Zerolog
On this page
Prerequisites
Send logs to SigNoz
Step 1. Set environment variables
Step 1. Set environment variables
Step 1. Set environment variables in Dockerfile
Step 1. Set environment variables (PowerShell)
Step 2. Install dependencies
Step 3. Instrument your application
Step 4. Run your application
With Trace Correlation (Advanced)
Install additional dependencies
Instrument your application
Run your application
Validate
Setup OpenTelemetry Collector (Optional)
What is the OpenTelemetry Collector?
Why use it?
Collector configuration
Troubleshooting
No logs appearing in SigNoz
Trace IDs not appearing in logs
Next Steps

Is this page helpful?

Your response helps us improve this page.