Skip to content

refactor(telemetry): depend on PSR-18/17 interfaces, inject the client#43

Open
loks0n wants to merge 2 commits into
mainfrom
refactor/telemetry-psr-http-client
Open

refactor(telemetry): depend on PSR-18/17 interfaces, inject the client#43
loks0n wants to merge 2 commits into
mainfrom
refactor/telemetry-psr-http-client

Conversation

@loks0n

@loks0n loks0n commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What

The OpenTelemetry adapter built its default HTTP transport with OtlpHttpTransportFactory, which relies on php-http/discovery to locate a PSR-18 client and PSR-17 factories at runtime. That pulled symfony/http-client and nyholm/psr7 into the package purely as discovery targets — and the discovery composer plugin kept re-adding them on every composer update.

This drops both concretes so telemetry depends only on the PSR interfaces, and injects the client instead:

  • require: symfony/http-client + nyholm/psr7psr/http-client + psr/http-factory
  • Disabled the php-http/discovery composer plugin so it stops re-adding Symfony/Nyholm

Construction

Two explicit paths — each requires exactly what it uses, nothing discarded:

// build the OTLP HTTP transport from a PSR-18 client (factories optional → PSR-17 discovery)
OpenTelemetry::fromClient($endpoint, $ns, $name, $id, new Utopia\Client(new Curl\Client()));
OpenTelemetry::fromClient($endpoint, $ns, $name, $id, $client, new Request\Factory(), new Stream\Factory());

// inject a fully-built transport directly (tests, custom transports)
new OpenTelemetry($ns, $name, $id, $transport);

The constructor now takes the TransportInterface it actually consumes; fromClient() is the convenience that builds one. (An earlier iteration used a single constructor, but that left $endpoint/$client/factories required-but-unused whenever a transport was injected — a transport-only caller had to pass a dummy client to satisfy the type.)

Why not a hard dependency on utopia-php/client?

It would close a telemetry → client → pools → telemetry cycle. That breaks --linked CI (the back-edge pools → telemetry ^0.4 lands on the dev-main root, which can't satisfy it) and couples the release cadence of packages meant to version independently. The client is now wired in by the consumer, where the dependency arrow points the right way.

⚠️ Breaking change

OpenTelemetry's constructor signature changed (now $ns, $name, $id, $transport), and the client-driven default moves to OpenTelemetry::fromClient(...). Existing new OpenTelemetry($endpoint, $ns, $name, $id) call sites (appwrite etc.) must migrate. Warrants a minor version bump when tagged.

Verification

  • bin/monorepo validate → all packages valid
  • bin/monorepo check telemetry → pint ✅ · phpstan No errors ✅ · rector ✅
  • bin/monorepo test telemetry → 30/30 ✅ · --linked → 30/30 ✅ (no cycle)

🤖 Generated with Claude Code

https://claude.ai/code/session_01LQiyHv2cv5SUHsHYBAE8SQ

The OpenTelemetry adapter built its default HTTP transport via
OtlpHttpTransportFactory, which leaned on php-http/discovery to find a
PSR-18 client and PSR-17 factories at runtime. That pulled symfony/http-client
and nyholm/psr7 into the package purely as discovery targets, and the
discovery composer plugin kept re-adding them on every update.

Drop both concretes and depend only on psr/http-client + psr/http-factory.
The adapter now takes a required PSR-18 ClientInterface (the meaningful
choice — which HTTP stack) and builds the transport with PsrTransportFactory.
The PSR-17 factories stay optional and fall back to discovery when null, so
callers only wire the client in the common case. The discovery composer
plugin is disabled so it stops re-adding Symfony/Nyholm.

A hard dependency on utopia-php/client was ruled out: it would close a
telemetry -> client -> pools -> telemetry cycle that breaks --linked CI and
couples the release cadence of packages meant to version independently. The
client is now wired in by the consumer, where the dependency arrow points the
right way.

BREAKING: OpenTelemetry's constructor now requires a PSR-18 client argument.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LQiyHv2cv5SUHsHYBAE8SQ
@loks0n loks0n requested a review from abnegate as a code owner July 3, 2026 16:01
@greptile-apps

greptile-apps Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors the OpenTelemetry adapter to depend only on PSR-18/17 interfaces rather than concrete symfony/http-client and nyholm/psr7 implementations, eliminating a php-http/discovery plugin loop that kept re-adding those concretes on every composer update.

  • The constructor is simplified to accept a pre-built TransportInterface directly (breaking: $endpoint and the old nullable-transport pattern are removed), and a new fromClient() static factory builds the transport via PsrTransportFactory using a caller-supplied PSR-18 client plus optional PSR-17 factories.
  • composer.json swaps the two concrete deps for psr/http-client + psr/http-factory interfaces and disables the discovery plugin; the lock file is regenerated, dropping six transitive Symfony packages.

Confidence Score: 5/5

Safe to merge — the refactoring is well-scoped and the breaking change is intentional and documented; no functional regressions in the changed code paths.

The constructor simplification and static factory introduction are straightforward and correct. The dependency swap from concretes to PSR interfaces is consistent throughout composer.json, the lock file, and the adapter code.

No files require special attention.

Important Files Changed

Filename Overview
packages/telemetry/src/Telemetry/Adapter/OpenTelemetry.php Refactored constructor to accept a pre-built TransportInterface directly (dropping $endpoint and the nullable transport pattern), and added a fromClient() static factory that wires PSR-18/17 into PsrTransportFactory — clean separation of concerns with no logic issues.
packages/telemetry/composer.json Replaced concrete symfony/http-client and nyholm/psr7 dependencies with the psr/http-client and psr/http-factory interfaces; disabled the php-http/discovery composer plugin to stop it re-adding concretes on every update.
packages/telemetry/composer.lock Lock file regenerated to remove nyholm/psr7, symfony/http-client and their transitive deps; consistent with composer.json changes.

Reviews (2): Last reviewed commit: "refactor(telemetry): split transport/cli..." | Re-trigger Greptile

Comment thread packages/telemetry/src/Telemetry/Adapter/OpenTelemetry.php Outdated
Addresses review: with a single constructor, injecting a $transport left
$endpoint, $client and the factories required-but-unused — a transport-only
caller had to pass a dummy client to satisfy the type.

The constructor now takes the TransportInterface it actually consumes; a
static fromClient() builds that transport from a PSR-18 client (+ optional
PSR-17 factories). Each entry point requires exactly what it uses, nothing is
discarded, and the client stays enforced at the type level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LQiyHv2cv5SUHsHYBAE8SQ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant