Skip to content

feat(opentelemetry source): allow to add headers to metadata for OpenTelemetry metrics and traces#24942

Open
ozanichkovsky wants to merge 9 commits intovectordotdev:masterfrom
ozanichkovsky:feature/opentelemetry-metrics-traces-headers
Open

feat(opentelemetry source): allow to add headers to metadata for OpenTelemetry metrics and traces#24942
ozanichkovsky wants to merge 9 commits intovectordotdev:masterfrom
ozanichkovsky:feature/opentelemetry-metrics-traces-headers

Conversation

@ozanichkovsky
Copy link
Contributor

@ozanichkovsky ozanichkovsky commented Mar 17, 2026

Summary

Adds header enrichment support to OpenTelemetry source metrics and traces.

Unlike logs, which support either legacy way of adding headers directly to the event or to the event metadata, this implementation adds headers to metric/trace event metadata only and ignores log_namespace settings on the source.

One of the use cases would be a tenant separation by a header.

Vector configuration

api:
  enabled: true
  address: "127.0.0.1:8686"

acknowledgements:
  enabled: true

sources:
  opentelemetry:
    type: "opentelemetry"
    grpc:
      address: 0.0.0.0:4317
    http:
      address: 0.0.0.0:4318
      headers:
        - "X-Tenant-ID"
    use_otlp_decoding: false
    log_namespace: true

transforms:
  debug:
    type: remap
    inputs:
      - "opentelemetry.metrics"
      - "opentelemetry.logs"
      - "opentelemetry.traces" 
    source: |
      log(%opentelemetry.headers."X-Tenant-ID")

sinks:
  console_output:
    type: "console"
    inputs:
      - "debug"
    encoding:
      codec: "native_json"

How did you test this PR?

The code is covered with unit tests and also was tested with different OTLP generators implemented in go, like this one for metrics:

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
	"go.opentelemetry.io/otel/metric"
	sdkmetric "go.opentelemetry.io/otel/sdk/metric"
)

func main() {
	var (
		endpoint = flag.String("endpoint", "http://localhost:4318", "OTLP/HTTP base endpoint, e.g. http://localhost:4318")
		header   = flag.String("header", "12345678", "Value for X-Tenant-ID")
		value    = flag.Int64("value", 1, "Counter increment value")
	)
	flag.Parse()

	ctx := context.Background()

	// Create OTLP metric HTTP exporter with custom headers.
	// For OTLP/HTTP, metrics usually go to <base>/v1/metrics.
	exporter, err := otlpmetrichttp.New(ctx,
		otlpmetrichttp.WithEndpointURL(*endpoint),
		otlpmetrichttp.WithURLPath("/v1/metrics"),
		otlpmetrichttp.WithHeaders(map[string]string{
			"X-Tenant-ID": *header,
			// Example:
			// "Authorization": "Bearer " + *header,
		}),
	)
	if err != nil {
		log.Fatalf("create exporter: %v", err)
	}

	reader := sdkmetric.NewPeriodicReader(exporter,
		sdkmetric.WithInterval(2*time.Second),
	)

	mp := sdkmetric.NewMeterProvider(
		sdkmetric.WithReader(reader),
	)

	defer func() {
		shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		if err := mp.Shutdown(shutdownCtx); err != nil {
			fmt.Fprintf(os.Stderr, "shutdown error: %v\n", err)
		}
	}()

	meter := mp.Meter("example-counter-cli")

	counter, err := meter.Int64Counter(
		"example_counter_total",
		metric.WithDescription("A simple demo counter sent via OTLP/HTTP"),
	)
	if err != nil {
		log.Fatalf("create counter: %v", err)
	}

	counter.Add(ctx, *value,
		metric.WithAttributes(
			attribute.String("service.name", "counter-cli"),
			attribute.String("env", "dev"),
		),
	)

	// Force an export now so the process can exit immediately.
	flushCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := mp.ForceFlush(flushCtx); err != nil {
		log.Fatalf("force flush: %v", err)
	}

	fmt.Println("metric sent")
}

Change Type

  • Bug fix
  • New feature
  • Dependencies
  • Non-functional (chore, refactoring, docs)
  • Performance

Is this a breaking change?

  • Yes
  • No

Does this PR include user facing changes?

  • Yes. Please add a changelog fragment based on our guidelines.
  • No. A maintainer will apply the no-changelog label to this PR.

References

Closes: #24619

Notes

  • Please read our Vector contributor resources.
  • Do not hesitate to use @vectordotdev/vector to reach out to us regarding this PR.
  • Some CI checks run only after we manually approve them.
    • We recommend adding a pre-push hook, please see this template.
    • Alternatively, we recommend running the following locally before pushing to the remote branch:
      • make fmt
      • make check-clippy (if there are failures it's possible some of them can be fixed with make clippy-fix)
      • make test
  • After a review is requested, please avoid force pushes to help us review incrementally.
    • Feel free to push as many commits as you want. They will be squashed into one before merging.
    • For example, you can run git merge origin master and git push.
  • If this PR introduces changes Vector dependencies (modifies Cargo.lock), please
    run make build-licenses to regenerate the license inventory and commit the changes (if any). More details here.

@ozanichkovsky ozanichkovsky requested a review from a team as a code owner March 17, 2026 08:23
@github-actions github-actions bot added the domain: sources Anything related to the Vector's sources label Mar 17, 2026
@ozanichkovsky ozanichkovsky marked this pull request as draft March 17, 2026 08:25
@ozanichkovsky ozanichkovsky changed the title Allow to add headers to metadata for OpenTelemetry metrics and traces feat: allow to add headers to metadata for OpenTelemetry metrics and traces Mar 17, 2026
@ozanichkovsky ozanichkovsky changed the title feat: allow to add headers to metadata for OpenTelemetry metrics and traces feat(opentelemetry): allow to add headers to metadata for OpenTelemetry metrics and traces Mar 17, 2026
@ozanichkovsky ozanichkovsky changed the title feat(opentelemetry): allow to add headers to metadata for OpenTelemetry metrics and traces feat(opentelemetry_source): allow to add headers to metadata for OpenTelemetry metrics and traces Mar 17, 2026
@ozanichkovsky ozanichkovsky marked this pull request as ready for review March 17, 2026 11:02
@ozanichkovsky ozanichkovsky changed the title feat(opentelemetry_source): allow to add headers to metadata for OpenTelemetry metrics and traces feat(opentelemetry source): allow to add headers to metadata for OpenTelemetry metrics and traces Mar 17, 2026
@ozanichkovsky
Copy link
Contributor Author

@vectordotdev/vector please review

@pront
Copy link
Member

pront commented Mar 18, 2026

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Delightful!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ozanichkovsky ozanichkovsky requested a review from a team as a code owner March 18, 2026 18:18
@github-actions github-actions bot added the domain: external docs Anything related to Vector's external, public documentation label Mar 18, 2026
@urseberry
Copy link
Contributor

I approved on behalf of documentation. Engineering will review also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: external docs Anything related to Vector's external, public documentation domain: sources Anything related to the Vector's sources

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introducing HTTP Headers to the OTLP Source for Metrics

3 participants