Skip to content

Periodic exporting MetricReader not working #1884

@remunda

Description

@remunda

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions