Need to understand the difference between SpanKind and links. From the documentation: // SpanKind // describes the relationship between the Span, its parents, and its children in a Trace. SpanKind describes two independent properties that benefit tracing systems during analysis. // This was also updated recently -> https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#spankind // Links // A Span may be linked to zero or more other Spans (defined by SpanContext) that are causally related. Links can point to SpanContexts inside a single Trace // or across different Traces. Links can be used to represent batched operations where a Span was initiated by multiple initiating Spans, // each representing a single incoming item being processed in the batch. // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#links-between-spans public function __construct( string $name, API\SpanContext $spanContext, ?API\SpanContext $parentSpanContext = null, ?Sampler $sampler = null, ?ResourceInfo $resource = null, int $spanKind = API\SpanKind::KIND_INTERNAL ) { $this->name = $name; $this->spanContext = $spanContext; $this->parentSpanContext = $parentSpanContext; $this->spanKind = $spanKind; $this->sampler = $sampler; $this->resource = $resource ?? ResourceInfo::emptyResource(); $moment = Clock::get()->moment(); $this->startEpochTimestamp = $moment[0]; $this->start = $moment[1]; $this->statusCode = API\SpanStatus::OK; $this->statusDescription = API\SpanStatus::DESCRIPTION[$this->statusCode]; // todo: set these to null until needed $this->attributes = new Attributes(); $this->events = new Events(); } public function getResource(): ResourceInfo { return clone $this->resource; } public function getContext(): API\SpanContext { return clone $this->spanContext; } public function getParent(): ?API\SpanContext { // todo: Spec says a parent is a Span, SpanContext, or null -> should we implement this here? return $this->parentSpanContext !== null ? clone $this->parentSpanContext : null; } public function setSpanStatus(string $code, ?string $description = null): API\Span { if ($this->isRecording()) { $this->statusCode = $code; $this->statusDescription = $description ?? self::DESCRIPTION[$code] ?? self::DESCRIPTION[self::UNKNOWN]; } return $this; } public function getStart(): int { return $this->start; } public function setStart(int $start): Span { $this->start = $start; return $this; } public function end(?int $now = null): API\Span { if (!isset($this->end)) { $this->end = $now ?? Clock::get()->now(); $this->ended = true; } return $this; } public function ended(): bool { return $this->ended; } public function setStartEpochTimestamp(int $timestamp): Span { $this->startEpochTimestamp = $timestamp; return $this; } public function getStartEpochTimestamp(): int { return $this->startEpochTimestamp; } public function getEnd(): ?int { return $this->end; } public function getStatus(): API\SpanStatus { return SpanStatus::new($this->statusCode, $this->statusDescription); } public function isRecording(): bool { return null === $this->end; } public function getDuration(): ?int { if (!$this->end) { return null; } return ($this->end - $this->start); } public function getSpanName(): string { return $this->name; } public function updateName(string $name): API\Span { $this->name = $name; return $this; } public function getAttribute(string $key): ?Attribute { return $this->attributes->getAttribute($key); } public function setAttribute(string $key, $value): API\Span { if ($this->isRecording()) { $this->attributes->setAttribute($key, $value); } return $this; } public function getAttributes(): API\Attributes { return $this->attributes; } public function replaceAttributes(API\Attributes $attributes): self { if ($this->isRecording()) { $this->attributes = $attributes; } return $this; } // todo: is accepting an Iterator enough to satisfy AddLazyEvent? -> Looks like the spec might have been updated here: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-tracing.md#add-events public function addEvent(string $name, int $timestamp, ?API\Attributes $attributes = null): API\Span { if ($this->isRecording()) { $this->events->addEvent($name, $attributes, $timestamp); } return $this; } public function getEvents(): API\Events { return $this->events; } /* A Span is said to have a remote parent if it is the child of a Span * created in another process. Each propagators' deserialization must * set IsRemote to true on a parent * SpanContext so Span creation knows if the parent is remote. * Returns true if the SpanContext was propagated from a * remote parent. When creating children * from remote spans, their IsRemote flag MUST be set to false. */ public function isRemote(): bool { return $this->spanContext->isRemoteContext(); } public function isSampled(): bool { return $this->spanContext->isSampled(); } public function setLinks(API\Links $links): Span { $this->links = $links; return $this; } public function getLinks(): API\Links { // TODO: Implement getLinks() method. return $this->links; } /** * @inheritDoc */ public function addLink(API\SpanContext $context, ?API\Attributes $attributes = null): API\Span { return $this; } public function getSpanKind(): int { return $this->spanKind; } public function getCanonicalStatusCode(): string { return $this->statusCode; } public function getStatusDescription(): string { return $this->statusDescription; } public function isStatusOk(): bool { return $this->statusCode == API\SpanStatus::OK; } }