Skip to content

Commit

Permalink
Add Span::addLink() and Meter::createGauge() (#1289)
Browse files Browse the repository at this point in the history
* Add `Span::addLink()`

https://opentelemetry.io/docs/specs/otel/trace/api/#add-link

* Bump API version to `1.1.x-dev`

* Add experimental `Meter::createGauge()`

https://opentelemetry.io/docs/specs/otel/metrics/api/#gauge
  • Loading branch information
Nevay authored Apr 27, 2024
1 parent 5a395e0 commit 8a6dd47
Show file tree
Hide file tree
Showing 18 changed files with 194 additions and 7 deletions.
28 changes: 28 additions & 0 deletions src/API/Metrics/GaugeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\API\Metrics;

use OpenTelemetry\Context\ContextInterface;

/**
* A synchronous instrument which can be used to record non-additive values.
*
* @see https://opentelemetry.io/docs/specs/otel/metrics/api/#gauge
*
* @experimental
*/
interface GaugeInterface
{

/**
* @param float|int $amount current absolute value
* @param iterable<non-empty-string, string|bool|float|int|array|null> $attributes
* attributes of the data point
* @param ContextInterface|false|null $context execution context
*
* @see https://opentelemetry.io/docs/specs/otel/metrics/api/#record-1
*/
public function record(float|int $amount, iterable $attributes = [], ContextInterface|false|null $context = null): void;
}
20 changes: 20 additions & 0 deletions src/API/Metrics/MeterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,26 @@ public function createHistogram(
array $advisory = [],
): HistogramInterface;

/**
* Creates a `Gauge`.
*
* @param string $name name of the instrument
* @param string|null $unit unit of measure
* @param string|null $description description of the instrument
* @param array $advisory an optional set of recommendations
* @return GaugeInterface created instrument
*
* @see https://opentelemetry.io/docs/specs/otel/metrics/api/#gauge-creation
*
* @experimental
*/
public function createGauge(
string $name,
?string $unit = null,
?string $description = null,
array $advisory = [],
): GaugeInterface;

/**
* Creates an `ObservableGauge`.
*
Expand Down
18 changes: 18 additions & 0 deletions src/API/Metrics/Noop/NoopGauge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\API\Metrics\Noop;

use OpenTelemetry\API\Metrics\GaugeInterface;

/**
* @internal
*/
final class NoopGauge implements GaugeInterface
{
public function record(float|int $amount, iterable $attributes = [], $context = null): void
{
// no-op
}
}
6 changes: 6 additions & 0 deletions src/API/Metrics/Noop/NoopMeter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use OpenTelemetry\API\Metrics\AsynchronousInstrument;
use OpenTelemetry\API\Metrics\CounterInterface;
use OpenTelemetry\API\Metrics\GaugeInterface;
use OpenTelemetry\API\Metrics\HistogramInterface;
use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\API\Metrics\ObservableCallbackInterface;
Expand Down Expand Up @@ -36,6 +37,11 @@ public function createHistogram(string $name, ?string $unit = null, ?string $des
return new NoopHistogram();
}

public function createGauge(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): GaugeInterface
{
return new NoopGauge();
}

public function createObservableGauge(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableGaugeInterface
{
return new NoopObservableGauge();
Expand Down
5 changes: 5 additions & 0 deletions src/API/Trace/NonRecordingSpan.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public function setAttributes(iterable $attributes): SpanInterface
return $this;
}

public function addLink(SpanContextInterface $context, iterable $attributes = []): SpanInterface
{
return $this;
}

/** @inheritDoc */
public function addEvent(string $name, iterable $attributes = [], int $timestamp = null): SpanInterface
{
Expand Down
15 changes: 15 additions & 0 deletions src/API/Trace/SpanInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ public function setAttribute(string $key, bool|int|float|string|array|null $valu
*/
public function setAttributes(iterable $attributes): SpanInterface;

/**
* Records a link to another `SpanContext`.
*
* Adding links at span creation via {@link SpanBuilderInterface::addLink()} is preferred to calling
* {@link SpanInterface::addLink()} later, for contexts that are available during span creation, because head
* sampling decisions can only consider information present during span creation.
*
* @param SpanContextInterface $context span context to link
* @param iterable $attributes attributes to associate with the link
* @return SpanInterface this span
*
* @see https://opentelemetry.io/docs/specs/otel/trace/api/#add-link
*/
public function addLink(SpanContextInterface $context, iterable $attributes = []): SpanInterface;

/**
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/trace/api.md#add-events
*/
Expand Down
4 changes: 2 additions & 2 deletions src/API/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"symfony/polyfill-php82": "^1.26"
},
"conflict": {
"open-telemetry/sdk": "<=1.0.4"
"open-telemetry/sdk": "<=1.0.8"
},
"autoload": {
"psr-4": {
Expand All @@ -35,7 +35,7 @@
},
"extra": {
"branch-alias": {
"dev-main": "1.0.x-dev"
"dev-main": "1.1.x-dev"
}
}
}
2 changes: 1 addition & 1 deletion src/SDK/Metrics/DefaultAggregationProviderTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function defaultAggregation($instrumentType, array $advisory = []): ?Aggr
InstrumentType::COUNTER, InstrumentType::ASYNCHRONOUS_COUNTER => new Aggregation\SumAggregation(true),
InstrumentType::UP_DOWN_COUNTER, InstrumentType::ASYNCHRONOUS_UP_DOWN_COUNTER => new Aggregation\SumAggregation(),
InstrumentType::HISTOGRAM => new Aggregation\ExplicitBucketHistogramAggregation($advisory['ExplicitBucketBoundaries'] ?? [0, 5, 10, 25, 50, 75, 100, 250, 500, 1000]),
InstrumentType::ASYNCHRONOUS_GAUGE => new Aggregation\LastValueAggregation(),
InstrumentType::GAUGE, InstrumentType::ASYNCHRONOUS_GAUGE => new Aggregation\LastValueAggregation(),
default => null,
};
// @codeCoverageIgnoreEnd
Expand Down
15 changes: 15 additions & 0 deletions src/SDK/Metrics/Gauge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\SDK\Metrics;

use OpenTelemetry\API\Metrics\GaugeInterface;

/**
* @internal
*/
final class Gauge implements GaugeInterface, InstrumentHandle
{
use SynchronousInstrumentTrait { write as record; }
}
2 changes: 2 additions & 0 deletions src/SDK/Metrics/InstrumentType.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ final class InstrumentType
public const COUNTER = 'Counter';
public const UP_DOWN_COUNTER = 'UpDownCounter';
public const HISTOGRAM = 'Histogram';
/** @experimental */
public const GAUGE = 'Gauge';

public const ASYNCHRONOUS_COUNTER = 'AsynchronousCounter';
public const ASYNCHRONOUS_UP_DOWN_COUNTER = 'AsynchronousUpDownCounter';
Expand Down
14 changes: 14 additions & 0 deletions src/SDK/Metrics/Meter.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use OpenTelemetry\API\Behavior\LogsMessagesTrait;
use OpenTelemetry\API\Metrics\AsynchronousInstrument;
use OpenTelemetry\API\Metrics\CounterInterface;
use OpenTelemetry\API\Metrics\GaugeInterface;
use OpenTelemetry\API\Metrics\HistogramInterface;
use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\API\Metrics\ObservableCallbackInterface;
Expand Down Expand Up @@ -153,6 +154,19 @@ public function createHistogram(string $name, ?string $unit = null, ?string $des
return new Histogram($this->writer, $instrument, $referenceCounter);
}

public function createGauge(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): GaugeInterface
{
[$instrument, $referenceCounter] = $this->createSynchronousWriter(
InstrumentType::GAUGE,
$name,
$unit,
$description,
$advisory,
);

return new Gauge($this->writer, $instrument, $referenceCounter);
}

public function createObservableGauge(string $name, ?string $unit = null, ?string $description = null, $advisory = [], callable ...$callbacks): ObservableGaugeInterface
{
if (is_callable($advisory)) {
Expand Down
3 changes: 2 additions & 1 deletion src/SDK/Trace/ImmutableSpan.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function __construct(
private readonly array $links,
private readonly array $events,
private readonly AttributesInterface $attributes,
private readonly int $totalRecordedLinks,
private readonly int $totalRecordedEvents,
private readonly StatusDataInterface $status,
private readonly int $endEpochNanos,
Expand Down Expand Up @@ -112,7 +113,7 @@ public function getTotalDroppedEvents(): int

public function getTotalDroppedLinks(): int
{
return max(0, $this->span->getTotalRecordedLinks() - count($this->links));
return max(0, $this->totalRecordedLinks - count($this->links));
}

public function getStatus(): StatusDataInterface
Expand Down
29 changes: 27 additions & 2 deletions src/SDK/Trace/Span.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace OpenTelemetry\SDK\Trace;

use OpenTelemetry\API\Trace as API;
use OpenTelemetry\API\Trace\SpanContextInterface;
use OpenTelemetry\Context\ContextInterface;
use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface;
use OpenTelemetry\SDK\Common\Dev\Compatibility\Util as BcUtil;
Expand Down Expand Up @@ -38,8 +39,8 @@ private function __construct(
private readonly SpanProcessorInterface $spanProcessor,
private readonly ResourceInfo $resource,
private AttributesBuilderInterface $attributesBuilder,
private readonly array $links,
private readonly int $totalRecordedLinks,
private array $links,
private int $totalRecordedLinks,
private readonly int $startEpochNanos,
) {
$this->status = StatusData::unset();
Expand Down Expand Up @@ -142,6 +143,29 @@ public function setAttributes(iterable $attributes): self
return $this;
}

public function addLink(SpanContextInterface $context, iterable $attributes = []): self
{
if ($this->hasEnded) {
return $this;
}
if (!$context->isValid()) {
return $this;
}
if (++$this->totalRecordedLinks > $this->spanLimits->getLinkCountLimit()) {
return $this;
}

$this->links[] = new Link(
$context,
$this->spanLimits
->getLinkAttributesFactory()
->builder($attributes)
->build(),
);

return $this;
}

/** @inheritDoc */
public function addEvent(string $name, iterable $attributes = [], ?int $timestamp = null): self
{
Expand Down Expand Up @@ -260,6 +284,7 @@ public function toSpanData(): SpanDataInterface
$this->links,
$this->events,
$this->attributesBuilder->build(),
$this->totalRecordedLinks,
$this->totalRecordedEvents,
$this->status,
$this->endEpochNanos,
Expand Down
2 changes: 1 addition & 1 deletion src/SDK/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"require": {
"php": "^8.1",
"ext-json": "*",
"open-telemetry/api": "^1.0",
"open-telemetry/api": "~1.0 || ~1.1",
"open-telemetry/context": "^1.0",
"open-telemetry/sem-conv": "^1.0",
"php-http/discovery": "^1.14",
Expand Down
16 changes: 16 additions & 0 deletions tests/Integration/SDK/SpanBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ public function test_add_link(): void
$this->assertCount(2, $span->toSpanData()->getLinks());
}

/**
* @group trace-compliance
*/
public function test_add_link_after_span_creation(): void
{
/** @var Span $span */
$span = $this
->tracer
->spanBuilder(self::SPAN_NAME)
->addLink($this->sampledSpanContext)
->startSpan()
->addLink($this->sampledSpanContext);

$this->assertCount(2, $span->toSpanData()->getLinks());
}

public function test_add_link_invalid(): void
{
/** @var Span $span */
Expand Down
20 changes: 20 additions & 0 deletions tests/Unit/SDK/Metrics/MeterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,26 @@ public function test_create_histogram_advisory(): void
);
}

public function test_create_gauge(): void
{
$metricFactory = $this->createMock(MetricFactoryInterface::class);
$metricFactory->expects($this->once())->method('createSynchronousWriter')
->with(
$this->anything(),
$this->anything(),
new InstrumentationScope('test', null, null, Attributes::create([])),
new Instrument(InstrumentType::GAUGE, 'name', 'unit', 'description'),
$this->anything(),
$this->anything(),
$this->anything(),
)
->willReturn([]);

$meterProvider = $this->createMeterProviderForMetricFactory($metricFactory);
$meter = $meterProvider->getMeter('test');
$meter->createGauge('name', 'unit', 'description');
}

public function test_create_up_down_counter(): void
{
$metricFactory = $this->createMock(MetricFactoryInterface::class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function test_default_aggregation_returns_default_aggregation(): void
$this->assertEquals(new SumAggregation(), $reader->defaultAggregation(InstrumentType::UP_DOWN_COUNTER));
$this->assertEquals(new SumAggregation(), $reader->defaultAggregation(InstrumentType::ASYNCHRONOUS_UP_DOWN_COUNTER));
$this->assertEquals(new ExplicitBucketHistogramAggregation([0, 5, 10, 25, 50, 75, 100, 250, 500, 1000]), $reader->defaultAggregation(InstrumentType::HISTOGRAM));
$this->assertEquals(new LastValueAggregation(), $reader->defaultAggregation(InstrumentType::GAUGE));
$this->assertEquals(new LastValueAggregation(), $reader->defaultAggregation(InstrumentType::ASYNCHRONOUS_GAUGE));
}

Expand Down
1 change: 1 addition & 0 deletions tests/Unit/SDK/Trace/ImmutableSpanTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public function test_getters(): void
[],
[],
$this->attributes,
$this->totalRecordedLinks,
$this->totalRecordedEvents,
$this->status,
$this->endEpochNanos,
Expand Down

0 comments on commit 8a6dd47

Please sign in to comment.