TelemetryFlow PHP SDK v1.0.0 — Domain-Driven Design + CQRS
The PHP SDK mirrors the Go SDK architecture, adapted to PHP idioms: strict types, readonly properties, backed enums, and PSR standards.
flowchart TD
subgraph App["Your Application"]
CODE["Business Code"]
FW["Framework (Laravel / PSR-15 / Guzzle)"]
end
subgraph SDK["TelemetryFlow PHP SDK"]
PUB["Interface Layer\nClient · Builder · TelemetryFlow facade"]
APP["Application Layer (CQRS)\nCommands · Queries · Buses"]
DOM["Domain Layer (DDD)\nCredentials · TelemetryConfig · Enums"]
INFRA["Infrastructure Layer\nOtlpExporterFactory · Handler · AuthHeaders"]
INSTR["Instrumentation\nPSR-15 · Guzzle"]
end
subgraph OTEL["OpenTelemetry PHP SDK"]
TP["TracerProvider"]
MP["MeterProvider"]
end
subgraph BACKEND["TelemetryFlow"]
COLLECTOR["TFO-Collector"]
PLATFORM["TFO-Platform"]
end
CODE --> PUB
FW --> INSTR
FW --> PUB
PUB --> APP
APP --> INFRA
INFRA --> DOM
INFRA --> OTEL
INSTR --> OTEL
OTEL -- OTLP gRPC/HTTP --> COLLECTOR
COLLECTOR --> PLATFORM
packages/
├── php-native/ # Framework-agnostic core
│ └── src/
│ ├── Domain/ # Pure value objects & aggregate root
│ │ ├── Credentials.php
│ │ ├── TelemetryConfig.php
│ │ ├── GrpcKeepaliveConfig.php
│ │ ├── Protocol.php (enum: grpc|http)
│ │ └── SignalType.php (enum: metrics|logs|traces)
│ ├── Application/ # CQRS
│ │ ├── Commands/ # Record*, Emit*, Start/EndSpan, lifecycle
│ │ └── Queries/ # Get*, Search*, Health, Status + results
│ ├── Infrastructure/ # OTel SDK integration
│ │ ├── OtlpExporterFactory.php
│ │ ├── TelemetryCommandHandler.php
│ │ ├── AuthHeaders.php
│ │ └── ResourceBuilder.php
│ ├── Instrumentation/
│ │ └── Http/ # PSR-15 + Guzzle middleware
│ ├── Client.php # Public API
│ ├── Builder.php # Fluent builder
│ └── TelemetryFlow.php # Static factories
├── laravel/ # Laravel wrapper
│ └── src/
│ ├── TelemetryFlowServiceProvider.php
│ ├── TelemetryFlowManager.php
│ ├── Facades/TelemetryFlow.php
│ ├── Middleware/TelemetryMiddleware.php
│ ├── Logging/TelemetryFlowLogHandler.php
│ └── Http/{GuzzleFactory, Controllers/HealthController}
└── generator/ # Symfony Console CLI
├── bin/telemetryflow-gen
└── src/Commands/
sequenceDiagram
participant App
participant Client
participant CmdBus as CommandBus
participant Handler as TelemetryCommandHandler
participant OTel as OpenTelemetry SDK
participant Collector
App->>Client: incrementCounter('requests', 1, attrs)
Client->>Handler: handle(RecordCounterCommand)
Handler->>OTel: counter.add(value, attrs)
Note over OTel: Batched in MeterProvider
OTel-->>Collector: OTLP/protobuf (periodic flush)
Every export carries authentication and collector-identity headers aligned with the TFO-Collector components:
| Header | Source component | Purpose |
|---|---|---|
Authorization: Bearer tfk_:tfs_ |
tfoauthextension |
API key auth |
X-TelemetryFlow-Key-ID / -Key-Secret |
tfoauthextension |
Redundant key headers |
X-TelemetryFlow-Collector-ID/Name/Hostname |
tfoidentityextension |
Collector identity |
X-TelemetryFlow-Environment / -Datacenter |
tfoidentityextension |
Topology |
X-TelemetryFlow-API-Version: v2 |
tfoexporter |
v2 endpoint indicator |
See Infrastructure/AuthHeaders.php.
- DDD aggregate root:
TelemetryConfigcentralizes all invariants and exposes a fluentwith*()API. - Value objects:
Credentialsvalidates thetfk_/tfs_format and never leaks the secret in__toString. - CQRS separation: writes (commands) and reads (queries) flow through dedicated buses, keeping the handler testable.
- Backed enums:
ProtocolandSignalTypereplace stringly-typed config. - Readonly DTOs: every command is a
readonlyclass — immutable intent records. - Framework-agnostic core: the
php-nativepackage has zero Laravel/Symfony dependencies; only PSR interfaces and the OTel SDK.