Skip to content

Send from an SDK

Configure OpenTelemetry SDKs and language agents to send logs over OTLP/gRPC or OTLP/HTTP.

Updated View as Markdown

OpenTelemetry SDKs and language agents read their exporter settings from environment variables. The same variables work for every language and both protocols.

The environment variables

export OTEL_EXPORTER_OTLP_ENDPOINT=https://obs-ingest.ezghcloud.com
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf          # or grpc, or http/json
export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer%20${EZGH_INGEST_KEY}"
export OTEL_RESOURCE_ATTRIBUTES="service.name=checkout,ezgh.metadata.application=storefront,ezgh.metadata.environment=production"
export OTEL_LOGS_EXPORTER=otlp
export OTEL_TRACES_EXPORTER=none
export OTEL_METRICS_EXPORTER=none
Variable Value
OTEL_EXPORTER_OTLP_ENDPOINT https://obs-ingest.ezghcloud.com, the base URL, for every protocol. HTTP exporters add /v1/logs; gRPC exporters connect to port 443 with TLS.
OTEL_EXPORTER_OTLP_PROTOCOL grpc, http/protobuf or http/json. All three are accepted. Set it explicitly: defaults differ between SDKs.
OTEL_EXPORTER_OTLP_HEADERS authorization=Bearer%20<ingest key>. The value uses the W3C Baggage format, where the space is written %20; SDKs decode it.
OTEL_RESOURCE_ATTRIBUTES service.name, ezgh.metadata.application and ezgh.metadata.environment. See service metadata.
OTEL_LOGS_EXPORTER otlp.
OTEL_TRACES_EXPORTER, OTEL_METRICS_EXPORTER none. Only logs are accepted today; traces and metrics are refused with 404 / UNIMPLEMENTED.

Keep the ingest key in your secret manager and pass it in as EZGH_INGEST_KEY. Don’t put it in code or images. Don’t set OTEL_EXPORTER_OTLP_LOGS_ENDPOINT unless you need it: it’s used as the exact URL, without /v1/logs added.

Java

The OpenTelemetry Java agent sends what your application logs through Logback, Log4j or java.util.logging.

java -javaagent:opentelemetry-javaagent.jar -jar app.jar

Python

pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
opentelemetry-instrument python app.py

Records written with the standard logging module are sent.

Node.js

npm install @opentelemetry/api @opentelemetry/auto-instrumentations-node
node --require @opentelemetry/auto-instrumentations-node/register app.js

Records written with winston, pino or bunyan are sent through their instrumentations.

Go

Go has no agent: create a logger provider with an OTLP exporter. The exporters and resource.Default() read the environment variables above.

import (
	"context"

	"go.opentelemetry.io/contrib/bridges/otelslog"
	"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp" // or otlploggrpc
	"go.opentelemetry.io/otel/log/global"
	sdklog "go.opentelemetry.io/otel/sdk/log"
	"go.opentelemetry.io/otel/sdk/resource"
)

func setupLogs(ctx context.Context) (*sdklog.LoggerProvider, error) {
	exporter, err := otlploghttp.New(ctx)
	if err != nil {
		return nil, err
	}
	provider := sdklog.NewLoggerProvider(
		sdklog.WithResource(resource.Default()),
		sdklog.WithProcessor(sdklog.NewBatchProcessor(exporter)),
	)
	global.SetLoggerProvider(provider)
	return provider, nil // call provider.Shutdown(ctx) before exiting
}

// Then log with log/slog through the bridge:
//   logger := otelslog.NewLogger("checkout")
//   logger.ErrorContext(ctx, "payment timeout", "order", orderID)

.NET

builder.Logging.AddOpenTelemetry(logging =>
{
    logging.IncludeFormattedMessage = true;
    logging.AddOtlpExporter();
});

AddOtlpExporter reads the environment variables above, including OTEL_EXPORTER_OTLP_PROTOCOL.

Check that it works

Send a log line, then search for it a few seconds later:

ezgh obs search --environment production --from 5m --project web

If nothing arrives, see Troubleshooting. An exporter logs the status it gets back.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close