open-telemetry / open-telemetry/opentelemetry-php

Periodic exporting MetricReader not working

Open
#1,884 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
PHP
Stars
912
Forks
232
Avg merge
7d 16h
Merged PRs (30d)
4

Description

Environment:

Symfony 5.4 with OpenTelemetry auto-instrumentation
PHP-FPM with configurable worker count (runing several pods in kubernetes)
Grafana Alloy as OTLP collector
http.server.request.duration histogram metric with semantic conventions

Steps to reproduce
POC is in repo: https://github.com/remunda/php-fpm-otel-poc
run ./k3drun.sh to deploy the whole app in local k8s cluster in docker with alloy (extended otel collector)

  • set OTEL_METRIC_EXPORT_INTERVAL=60000
  • run PHP with autoloaded OTEL PHP SDK
  • obtain meter from cachedInstrumentation (or globals)
  • create cumulative histogram
  • record timing of every request in histogram
  • get OTLP messages (eg. port-forward to grafana alloy and livedebug on otel receiver)

What is the expected behavior?

  • metrics are exported every 60s

What is the actual behavior?

  • metrics are exported after every HTTP Request (sample data of 1 push bellow)

Additional context
It looks like its not implementet at all, there is some TODO :-/ https://github.com/open-telemetry/opentelemetry-php/blob/main/src/Contrib/Otlp/MetricExporterFactory.php#L47 But I'm new in this codebase.

Although its marked in compatibility matrix as supported https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md

Maybe I'm missing something, but I've spent on this issues tens of hours wondering whats going on and honestly I'm without ideas :D. I've tried to aggregate histograms on alloy but it broke my cluster how it spiked on CPU/RAM. On this site is decent load.

I will be wery thankful for any advice.
Is there for example another way to aggregate histogram metrics in process and push them according to the interval specifications?

----OTLP sample----
StartTimestamp: 2026-02-09 21:33:20.479847024 +0000 UTC
Timestamp: 2026-02-09 21:33:20.525514411 +0000 UTC
Count: 1
Sum: 0.044489
Min: 0.044489
Max: 0.044489
ExplicitBounds #0: 0.000000
ExplicitBounds #1: 5.000000
ExplicitBounds #2: 10.000000
ExplicitBounds #3: 25.000000
ExplicitBounds #4: 50.000000
ExplicitBounds #5: 75.000000
ExplicitBounds #6: 100.000000
ExplicitBounds #7: 250.000000
ExplicitBounds #8: 500.000000
ExplicitBounds #9: 1000.000000
Buckets #0, Count: 0
Buckets #1, Count: 1
Buckets #2, Count: 0
Buckets #3, Count: 0
Buckets #4, Count: 0
Buckets #5, Count: 0
Buckets #6, Count: 0
Buckets #7, Count: 0
Buckets #8, Count: 0
Buckets #9, Count: 0
Buckets #10, Count: 0
Exemplars:
Exemplar #0
     -> Trace ID: f7d3edf99d26e69921aa3b1c49e464ca
     -> Span ID: 936cb76028d1c8da
     -> Timestamp: 2026-02-09 21:33:20.524447749 +0000 UTC
     -> Value: 0.044489
ResourceMetrics #0
Resource SchemaURL: https://opentelemetry.io/schemas/1.38.0
Resource attributes:
     -> service.name: Str(oteltest-web)
     -> host.name: Str(php-app-5c8d5f9f8f-nh9cv)
     -> host.arch: Str(x86_64)
     -> os.type: Str(linux)
     -> os.description: Str(6.6.87.2-microsoft-standard-WSL2)
     -> os.name: Str(Linux)
     -> os.version: Str(#1 SMP PREEMPT_DYNAMIC Thu Jun  5 18:30:46 UTC 2025)
     -> process.runtime.name: Str(fpm-fcgi)
     -> process.runtime.version: Str(8.3.23)
     -> process.pid: Int(8)
     -> process.executable.path: Str(/usr/local/sbin/php-fpm)
     -> process.owner: Str(www-data)
     -> telemetry.sdk.name: Str(opentelemetry)
     -> telemetry.sdk.language: Str(php)
     -> telemetry.sdk.version: Str(1.12.0)
     -> telemetry.distro.name: Str(opentelemetry-php-instrumentation)
     -> telemetry.distro.version: Str(1.2.1)
ScopeMetrics #0
ScopeMetrics SchemaURL: 
InstrumentationScope oteltest-http 
Metric #0
Descriptor:
     -> Name: http.server.request.duration
     -> Description: Duration of HTTP server requests
     -> Unit: s
     -> DataType: Histogram
     -> AggregationTemporality: Cumulative
HistogramDataPoints #0
Data point attributes:
     -> http.request.method: Str(GET)
     -> http.response.status_code: Int(200)
     -> url.scheme: Str(http)
     -> network.protocol.version: Str(HTTP/1.1)
     -> http.route: Str(api_test)
--------

Thank you!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/Contrib/Otlp/MetricExporterFactory.php at the TODO referenced in the issue, then reproduce the behavior using ./k3drun.sh in the linked PHP-FPM proof of concept. Compare OTLP output with OTEL_METRIC_EXPORT_INTERVAL=60000; done means metrics are exported on the configured interval rather than after every HTTP request.

Written by the indexing model from the issue text.

Assessment

Tech stack
kubernetes, php, symfony
Domain
observability
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.