Table of Contents

Exporting to a Backend

Note

XMPro exports standard OTLP and does not depend on any particular backend. Any collector or service that accepts OTLP can receive XMPro telemetry.

Introduction

XMPro sends traces, metrics, and logs to a single OTLP endpoint. In most deployments that endpoint is an OpenTelemetry Collector, which receives the data and forwards each signal type to whichever storage backend you use. Pointing XMPro at a collector rather than directly at a vendor endpoint keeps the XMPro configuration unchanged if you later switch or add backends.

This guide covers a worked collector configuration for the Grafana stack, notes for sending data directly to a vendor endpoint, and the collector exporter to use for each common backend. For the XMPro-side configuration, see Configure OpenTelemetry.

Using a Collector

A collector sits between XMPro and your storage backends. It accepts OTLP on ports 4317 for gRPC and 4318 for HTTP, then routes traces, metrics, and logs to different destinations.

Point XMPro at the collector:

{
  "OpenTelemetry": {
    "Enabled": true,
    "Endpoint": "http://otel-collector:4317",
    "Protocol": "Grpc"
  }
}

Grafana Stack Example

This collector configuration receives OTLP from XMPro and forwards traces to Tempo, metrics to Mimir or Prometheus, and logs to Loki:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 5s

exporters:
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true

  otlphttp/loki:
    endpoint: http://loki:3100/otlp

  prometheusremotewrite/mimir:
    endpoint: http://mimir:9009/api/v1/push

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/tempo]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheusremotewrite/mimir]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlphttp/loki]

Once data is flowing, the service.name values described in Observability and OpenTelemetry become your primary filter in Grafana. In Tempo, search by service name to find XMPro traces. In Loki, query by the service_name label.

Tip

The Prometheus remote write exporter converts dots in metric names to underscores, so xmpro.stream_host.stream.started is queried as xmpro_stream_host_stream_started. Counters also gain a _total suffix at this point, which is why XMPro does not include one in the instrument name.

Adding Resource Attributes at the Collector

If you run several XMPro environments, adding an environment attribute at the collector avoids having to configure it on every service:

processors:
  resource:
    attributes:
      - key: deployment.environment
        value: production
        action: upsert

You can also set this on the XMPro side using OTEL_RESOURCE_ATTRIBUTES, which is the better choice when a single collector serves more than one environment. See Using Environment Variables.

Exporting Without a Collector

XMPro can send OTLP directly to a vendor endpoint that accepts it, which avoids running collector infrastructure. Use HttpProtobuf for these endpoints, since vendor ingest is normally exposed over HTTPS, and supply credentials using the Headers key:

{
  "OpenTelemetry": {
    "Enabled": true,
    "Endpoint": "https://otlp.vendor.example.com",
    "Protocol": "HttpProtobuf",
    "Headers": "Authorization=Bearer your-token-here"
  }
}

The trade-off is that changing backend then means reconfiguring and restarting every XMPro service, and you lose the ability to filter or transform telemetry before it leaves your network.

Warning

Store credentials in a secret store rather than in appsettings.json. On Kubernetes, the Helm charts read the endpoint and headers from secret keys, as described in Kubernetes With Helm.

Backend Notes

Because XMPro emits standard OTLP, the backend-specific work happens in the collector rather than in XMPro. The table below gives the collector exporter to use for each common backend. Setup details such as endpoints, API keys, and regions are owned by the vendor and change on their release schedule, so follow their documentation rather than a copy of it here.

Backend Collector exporter Vendor documentation
Grafana (Tempo, Loki, Mimir) otlp, otlphttp, prometheusremotewrite Grafana OpenTelemetry docs
Grafana Cloud otlphttp Grafana Cloud OTLP endpoint
New Relic otlphttp New Relic OTLP setup
Datadog datadog Datadog exporter docs
Dynatrace otlphttp Dynatrace OTLP export
Splunk Observability Cloud sapm, signalfx Splunk OpenTelemetry Collector
Azure Monitor azuremonitor Azure Monitor exporter

Two XMPro-specific points are worth knowing regardless of backend.

Prometheus-style backends rewrite metric names. Dots become underscores and counters gain a _total suffix during Prometheus remote write, so xmpro.stream_host.stream.started is queried as xmpro_stream_host_stream_started_total. This is why XMPro does not include _total in the instrument name itself.

Azure Monitor may duplicate data. An Azure Kubernetes (AKS) deployment already provisions Log Analytics and an Application Insights connection with the cluster, without any OpenTelemetry configuration. Enabling OTLP export does not change that, and the two run side by side. If you also route OTLP to Azure Monitor through the collector, consider whether you need both paths, since the data will overlap.

Troubleshooting

  1. The collector receives data but the backend shows nothing

    Fix: Check the collector's own logs and internal metrics. An exporter failure appears there rather than in the XMPro logs, because from XMPro's perspective the export succeeded once the collector accepted it.

  2. Metric names in Prometheus or Mimir do not match this documentation

    Fix: Dots are converted to underscores and counters gain a _total suffix during Prometheus remote write. Query xmpro_stream_host_stream_started_total rather than the OTLP name.

  3. Traces appear but are not grouped as one service

    Fix: Confirm service.name is present on the resource. If a collector processor overwrites it, XMPro signals will be split or merged unexpectedly.

  4. Logs arrive without trace identifiers

    Fix: Events written outside an active trace legitimately have no trace context, so check with a log event produced during a request. If request-scoped events also lack identifiers, confirm the logs pipeline is not dropping the fields at the collector.

Summary

XMPro emits standard OTLP, so the backend choice is yours and is best made at a collector rather than in XMPro configuration. A collector lets you route each signal type to a different store, add environment attributes centrally, and change backend without touching XMPro. Direct export to a vendor endpoint works and removes infrastructure, at the cost of reconfiguring every service when anything changes. When comparing metric names against this documentation, remember that Prometheus-style backends rewrite dots to underscores and append _total to counters.


Last modified: September 28, 2026