1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
<?php
namespace Wikimedia\Telemetry;
use Wikimedia\Assert\Assert;
/**
* Represents an OpenTelemetry span, i.e. a single operation within a trace.
*
* @since 1.43
* @see https://opentelemetry.io/docs/specs/otel/trace/api/#span
*/
class Span implements SpanInterface {
private Clock $clock;
private TracerState $tracerState;
private SpanContext $context;
public function __construct(
Clock $clock,
TracerState $tracerState,
SpanContext $context
) {
$this->clock = $clock;
$this->tracerState = $tracerState;
$this->context = $context;
}
public function __destruct() {
$this->end();
$activeSpanContext = $this->tracerState->getActiveSpanContext();
if ( $this->context->equals( $activeSpanContext ) ) {
$this->deactivate();
}
}
/** @inheritDoc */
public function getContext(): SpanContext {
return $this->context;
}
/** @inheritDoc */
public function setAttributes( array $attributes ): SpanInterface {
$this->context->setAttributes( $attributes );
return $this;
}
/** @inheritDoc */
public function setSpanKind( int $spanKind ): SpanInterface {
$this->context->setSpanKind( $spanKind );
return $this;
}
/** @inheritDoc */
public function start( ?int $epochNanos = null ): SpanInterface {
Assert::precondition(
!$this->context->wasStarted(),
'Cannot start a span more than once'
);
$this->context->setStartEpochNanos( $epochNanos ?? $this->clock->getCurrentNanoTime() );
return $this;
}
/** @inheritDoc */
public function end( ?int $epochNanos = null ): void {
Assert::precondition(
$this->context->wasStarted(),
'Cannot end a span that has not been started'
);
// Make duplicate end() calls a no-op, since it may occur legitimately,
// e.g. when a span wrapped in an RAII ScopedSpan wrapper is ended explicitly.
if ( !$this->context->wasEnded() ) {
$this->context->setEndEpochNanos( $epochNanos ?? $this->clock->getCurrentNanoTime() );
$this->tracerState->addSpanContext( $this->context );
}
}
/** @inheritDoc */
public function activate(): void {
$this->tracerState->activateSpan( $this->getContext() );
}
/** @inheritDoc */
public function deactivate(): void {
$this->tracerState->deactivateSpan( $this->getContext() );
}
}
|