Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Span::addLink() and Meter::createGauge() #1289

Merged
merged 3 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading