承接 specoto/trace-reference 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

specoto/trace-reference

Composer 安装命令:

composer require specoto/trace-reference

包简介

PSR-22 Application Tracing: reference implementation with exporters, propagation, and in-memory tracers

README 文档

README

This repository is a prototype implementation of the PSR-22 Application Tracing draft proposal.

The proposed PSR-22 interfaces live in the separate specoto/trace package; this package depends on specoto/trace and provides concrete implementations (tracers, span storage, exporters, propagation). This separation mirrors psr/log / Monolog: the PSR would define the contracts, an implementation demonstrates them.

Status

PSR-22 is currently Draft (proposed standard). This prototype explores the interface boundaries, tests design decisions, and validates the scope described in the meta document.

Architecture

The PSR-22 draft scopes itself to what library and framework authors need to emit tracing signals, and nothing more. The meta document is explicit:

"This standard aims to create an intentionally minimalist set of interfaces that can be used to provide tracing signals to 3rd party libraries in a unified manner." — PSR-22 Meta, §1

"By taking transmission mechanisms out of scope for this PSR, we drastically increase the simple adoptability of tracing for all parties involved." — PSR-22 Meta, §2

PSR Surface (what goes in the standard)

InterfaceRole
TracerProviderInterfaceEntry point — factory for named tracers
TracerInterfaceCreates spans. No flush() or shutdown()
SpanInterfaceRead/write span data
SpanContextInterfaceTrace identity + W3C traceparent
SpanKind enumINTERNAL, CLIENT, SERVER, PRODUCER, CONSUMER
SpanStatus enumUNSET, OK, ERROR

Non-PSR surface (implementation detail, not standardized)

  • Exporter\* — transmission is out of scope
  • Propagation\* — context propagation is an SDK concern
  • TracingFactory — convenience wiring, not part of PSR
  • Tracer\DefaultTracer, InMemoryTracer, NoopTracer — concrete implementations
  • Tracer\SpanContextGeneratorTrait — shared ID generation
  • Attribute\*#[Traceable] / #[SpanName] attributes + TracingProxy for declarative tracing

The distinction mirrors the PSR-3 / Monolog relationship: the PSR defines the contract; implementations handle transport, batching, and configuration.

Attribute-based Tracing

This prototype includes a declarative tracing approach using PHP 8.3 attributes. Any service class can opt into tracing by marking methods with #[Traceable] — no modifications to the class itself are needed.

Attributes

AttributeScopePurpose
#[Traceable]MethodMarks the method for auto-tracing
#[SpanName]MethodOverrides the span name (defaults to method name)

Usage

use Psr\Trace\Attribute\SpanName;
use Psr\Trace\Attribute\Traceable;

class OrderService
{
    #[Traceable]
    #[SpanName('order.create')]
    public function createOrder(string $product, int $qty): array { ... }

    #[Traceable]
    public function processPayment(int $orderId, float $amount): string { ... }
}

Wrapping

TracingProxy wraps any object and intercepts traced methods via __call + reflection:

use Psr\Trace\Attribute\TracingProxy;
use Psr\Trace\Tracer\InMemoryTracer;

$tracer = new InMemoryTracer('my_app', '1.0.0');
$service = new TracingProxy(new OrderService(), $tracer);

$service->createOrder('Widget', 2);   // auto-traced via #[Traceable]
$service->processPayment(1234, 39.99); // auto-traced via #[Traceable]

Real Runtime Data

Each traced span automatically captures the following from reflection:

AttributeSource
class$method->class — fully-qualified class name
method$method->name — the method called
file$method->getFileName() — source file path
line$method->getStartLine() — method declaration line
argsParameter names and values — JSON-encoded

No hardcoded metadata needed.

Performance

Benchmarked at 10,000 iterations on PHP 8.3 (opcache hot):

Pathµs/callOverhead
Direct call0.125baseline
Proxy (untraced method)0.442+0.32 µs
Proxy (traced + span lifecycle)7.567+7.44 µs

The 7.6 µs per traced call is negligible for typical request-scoped tracing (a few dozen spans per request adds ~150 µs total). The overhead is dominated by span object allocation and attribute setting — not reflection — making it suitable for most applications. For hot-path inner loops, skip tracing or check $span->isRecording() first.

Design Decisions

1. No flush() or shutdown() on TracerInterface

The meta document lists transmission mechanisms as a non-goal:

"This PSR does not define the mechanisms used for transmitting the data to 3rd party systems." — PSR-22 Meta, §3.1 (Non-goals)

flush() and shutdown() imply a lifecycle that knows about exporters, batching, and connection management — all transmission concerns. Removing them from the interface keeps the PSR focused on signal emission. Implementations like DefaultTracer still provide them as concrete methods for callers that need them.

2. toTraceState() removed from SpanContextInterface

The method previously named toTraceState() emitted 00-{trace_id}-{span_id}-{flags} — the W3C traceparent format, not the W3C tracestate format (vendor1=val1,vendor2=val2). This naming collision was a bug risk. The method was renamed to toTraceParent() and the erroneous toTraceState()/fromTraceState() methods were removed. The W3C tracestate is exposed as a plain ?string property via getTracestate().

3. TracerProviderInterface added

The meta document says:

"This PSR may provide a minimal TraceProvider, etc. for other providers to extend, should they choose." — PSR-22 Meta, §3.1 (Goals)

getTracer(string $name, ?string $version = null) is the minimal surface needed for framework integration. It mirrors OpenTelemetry's TracerProvider::getTracer() signature.

4. SpanContextGeneratorTrait deduplicates ID generation

Both DefaultTracer and InMemoryTracer share the same logic for generating new trace/span IDs and building child contexts. A trait avoids forcing an abstract base class while eliminating the ~50 lines of duplication.

5. W3C traceparent parsing is self-contained in SpanContext

fromTraceParent() no longer delegates to a misnamed method. Parsing is inline and validates trace ID length (32 hex chars), span ID length (16 hex chars), and the 00- version prefix.

Community Context

PSR-22 vs OpenTelemetry PHP

The OpenTelemetry PHP SDK (open-telemetry/opentelemetry) is the de facto standard for distributed tracing in PHP (~1.3M installs). It carries a heavy dependency tree (PSR-7, PSR-17, PSR-18, Symfony HTTP Client, OTLP/Zipkin exporters) and is governed by the CNCF cross-language specification process.

A PSR-22-like interface would serve a different role, analogous to PSR-3 vs Monolog:

  • PSR-22 (if accepted): vendor-neutral interface contract governed by PHP-FIG
  • OTel PHP SDK: full-featured implementation with exporters, propagators, and SDK lifecycle

Library authors who only need to emit spans could depend on psr/trace without pulling in HTTP factories, gRPC exporters, or the CNCF specification weight. Providers (Datadog, New Relic, Sentry, etc.) could implement the PSR-22 interfaces behind their existing SDKs.

PHP-FIG vs CNCF

The PHP-FIG serves the PHP ecosystem specifically — its mission is interoperability between PHP frameworks and libraries. The CNCF serves the cross-language cloud-native ecosystem. The two are complementary: PSR-22 (if accepted) would define what PHP libraries need, while the OTel spec defines what distributed systems need.

Repository

GitLab: gitlab.com/specoto/trace-reference Packagist: specoto/trace-reference

Running Tests

ddev exec /var/www/html/vendor/bin/phpunit -c /var/www/html/trace/phpunit.xml.dist

77 tests, 178 assertions (PHP 8.3).

Key Principles

  • Minimalist surface: only interfaces that library authors need to emit traces
  • No transmission: exporters, batching, and shipping are implementation concerns
  • OTel compatible: data model aligns with OpenTelemetry; interface surface is narrower
  • No breaking changes for OTel adopters: DefaultTracer provides flush()/shutdown() as concrete methods even though they are not on the interface

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-17

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固