LinkMesh

Search docs, blog and changelog

ENDE

Snippets · Destinations

Send metrics with Prometheus remote write

Prometheus-compatible stores accept remote write. The prometheusremotewrite exporter converts OpenTelemetry metrics to time series, and resource_to_telemetry_conversion decides whether resource attributes such as deployment.environment.name become labels on every series.

Signals
Metrics
Source
OTLP
Components
otlpbatchmemory_limiterprometheusremotewrite
Destination
Prometheus remote write

OpenTelemetry Collector

OpenTelemetry Collector YAML
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 25
  batch:
    timeout: 5s

exporters:
  prometheusremotewrite:
    endpoint: https://prometheus.example.internal/api/v1/write
    headers:
      Authorization: Bearer ${env:PROMETHEUS_WRITE_TOKEN}
    resource_to_telemetry_conversion:
      enabled: true
    target_info:
      enabled: true
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 300s

service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [prometheusremotewrite]

LinkMesh

Library › Destinations › Prometheus Remote Write

Endpoint
https://prometheus.example.internal/api/v1/write
Headers
{"Authorization":"Bearer ${env:PROMETHEUS_WRITE_TOKEN}"}
Promote Selected Resource Attributes To Labels
true

What LinkMesh then pushes to the collector, under exporters:

Pushed to the collector
prometheusremotewrite/output_dst_00000502:
  endpoint: https://prometheus.example.internal/api/v1/write
  headers:
    Authorization: Bearer ${env:PROMETHEUS_WRITE_TOKEN}

The same, as an API call (see automation recipes):

API call
curl -X POST "$LINKMESH/destinations" \
  -H "Authorization: Bearer $LMSAT" \
  -H "Content-Type: application/json" \
  -d '{
  "defaultConfig": {
    "endpoint": "https://prometheus.example.internal/api/v1/write",
    "headers": {
      "Authorization": "Bearer ${env:PROMETHEUS_WRITE_TOKEN}"
    },
    "promote_resource_attributes": true
  },
  "exporterType": "prometheusremotewrite",
  "name": "Prometheus Remote Write",
  "signalTypes": [
    "metrics"
  ]
}'

The rest of the collector config above (otlp, memory_limiter, batch) is not part of this template: in LinkMesh those are separate sources, processors and destinations on the route.

Generated from LinkMesh's template catalogue by linkmesh-server snippet-render 1.464.3, not written by hand.

Download config.yamlValidated with otelcol-contrib v0.161.0 on 2026-10-26

Complete config files, each checked with the collector's own validate command (otelcol-contrib v0.161.0).

The gotcha

Without resource_to_telemetry_conversion your resource attributes are not on the series. In our test, with it off, orders_total arrived with only job and route as labels, and deployment_environment_name existed only on the separate target_info series, so every query needs a join; with it on, every series carried deployment_environment_name and service_name.

Manage this across a fleet

LinkMesh manages collector configuration across a fleet from one self-hosted control plane, so a change like this is made once rather than host by host. The first 25 Collectors are free after a no-card registration in the OpenSight Customer Portal (5 without one).

Doing this in LinkMesh: Destinations