microsoft/aspire · error

log exporter

Error message

log exporter: %w

What it means

setupOTel wraps the error from otlploggrpc.New, which constructs the gRPC OTLP log exporter. This fails on an invalid endpoint/URL or bad exporter options. The wrap "log exporter: %w" retains the underlying cause.

Solutions

  1. Validate the log endpoint URL scheme/host:port before calling setupOTel.
  2. Inspect the unwrapped error for the exact URL or dial failure.
  3. Ensure the OTLP logs endpoint (often a different port than traces) is correct and reachable.
  4. Verify otlploggrpc SDK dependency versions are consistent with go.opentelemetry.io/otel/sdk/log.

Example fix

// before
logExp, err := otlploggrpc.New(ctx, logOpts...)
// after
if u, perr := url.Parse(os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")); perr != nil || u.Host == "" {
    return nil, fmt.Errorf("invalid OTLP endpoint for logs: %q", os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"))
}
logExp, err := otlploggrpc.New(ctx, logOpts...)
Defensive patterns

Strategy: validation

Validate before calling

ep := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
if u, err := url.Parse(ep); err != nil || u.Scheme == "" {
    return fmt.Errorf("invalid logs OTLP endpoint %q", ep)
}

Try / catch

if err := setupOTel(...); err != nil {
    log.Printf("log exporter setup failed, falling back to stderr logging: %v", err)
}

Prevention

When it happens

Trigger: otlploggrpc.New returns an error because the log OTLP endpoint is malformed or the connection options (TLS, headers) are invalid when initializing structured logging.

Common situations: Same endpoint misconfiguration as traces/metrics but applied to the logs signal — e.g. dashboard OTLP endpoint not set, wrong port, or mixing http exporter endpoint with the grpc log exporter.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/2cab9e9e878ef5a7. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Templating/Templates/go-starter/api/telemetry.go:88

		return nil, fmt.Errorf("metric exporter: %w", err)
	}
	mp := sdkmetric.NewMeterProvider(
		sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExp)),
		sdkmetric.WithResource(res),
	)
	otel.SetMeterProvider(mp)

	if err := runtime.Start(runtime.WithMeterProvider(mp)); err != nil {
		return nil, fmt.Errorf("runtime metrics: %w", err)
	}

	logOpts := []otlploggrpc.Option{}
	if len(headers) > 0 {
		logOpts = append(logOpts, otlploggrpc.WithHeaders(headers))
	}
	logExp, err := otlploggrpc.New(ctx, logOpts...)
	if err != nil {
		return nil, fmt.Errorf("log exporter: %w", err)
	}
	lp := sdklog.NewLoggerProvider(
		sdklog.WithProcessor(sdklog.NewBatchProcessor(logExp)),
		sdklog.WithResource(res),
	)
	otellog.SetLoggerProvider(lp)

	// Route slog to OTel so structured logs appear in the dashboard.
	slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))

	return func(ctx context.Context) error {
		_ = tp.Shutdown(ctx)
		_ = mp.Shutdown(ctx)
		_ = lp.Shutdown(ctx)
		return nil
	}, nil
}

View on GitHub (pinned to 25830f84bd)