fix: #3586473 Finalize streaming OTel spans on the terminal event

Summary

Fixes #3586473 (closed). Streaming OTel spans dropped final token usage: the span was ended on the first event (un-consumed iterator), before the real usage arrived on the terminal PostStreamingResponseEvent.

Changes

  • Defer span finalization to the terminal event for streaming, and unset the stored span after ending it (also fixes unbounded $otelSpans growth).
  • Add a shutdown guard (DestructableInterface) so spans left open by iterators that never dispatch the terminal event are ended at request shutdown.
  • Tests: the bug repro and the leak guard.

Out of scope, tracked on the issue: metrics operation_type dimension, operationType/configuration on the terminal event, finish-reason preservation.

Verification

Against drupal/ai 1.4.0 (PHP 8.4, PHPUnit 11.5, real OTel in-memory exporter): ai_observability Unit suite 17/17, phpstan and phpcs clean.

AI-Generated: Yes (Claude Code; verified against drupal/ai 1.4.0 with a real OpenTelemetry SDK.)

Edited by George Kastanis

Merge request reports

Loading