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 support for multi-instrument callbacks #1202

Merged
merged 5 commits into from
Jan 10, 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
12 changes: 12 additions & 0 deletions src/API/Metrics/AsynchronousInstrument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\API\Metrics;

/**
* Marker interface for asynchronous instruments.
*/
interface AsynchronousInstrument
{
}
2 changes: 1 addition & 1 deletion src/API/Metrics/CounterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use OpenTelemetry\Context\ContextInterface;

interface CounterInterface
interface CounterInterface extends SynchronousInstrument
{

/**
Expand Down
2 changes: 1 addition & 1 deletion src/API/Metrics/HistogramInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use OpenTelemetry\Context\ContextInterface;

interface HistogramInterface
interface HistogramInterface extends SynchronousInstrument
{

/**
Expand Down
34 changes: 34 additions & 0 deletions src/API/Metrics/MeterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,40 @@
interface MeterInterface
{

/**
* Reports measurements for multiple asynchronous instrument from a single callback.
*
* The callback receives an {@link ObserverInterface} for each instrument. All provided
* instruments have to be created by this meter.
*
* ```php
* $callback = $meter->batchObserve(
* function(
* ObserverInterface $usageObserver,
* ObserverInterface $pressureObserver,
* ): void {
* [$usage, $pressure] = expensive_system_call();
* $usageObserver->observe($usage);
* $pressureObserver->observe($pressure);
* },
* $meter->createObservableCounter('usage', description: 'count of items used'),
* $meter->createObservableGauge('pressure', description: 'force per unit area'),
* );
* ```
*
* @param callable $callback function responsible for reporting the measurements
* @param AsynchronousInstrument $instrument first instrument to report measurements for
* @param AsynchronousInstrument ...$instruments additional instruments to report measurements for
* @return ObservableCallbackInterface token to detach callback
*
* @see https://opentelemetry.io/docs/specs/otel/metrics/api/#multiple-instrument-callbacks
*/
public function batchObserve(
callable $callback,
AsynchronousInstrument $instrument,
AsynchronousInstrument ...$instruments
): ObservableCallbackInterface;

/**
* Creates a `Counter`.
*
Expand Down
7 changes: 7 additions & 0 deletions src/API/Metrics/Noop/NoopMeter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@

namespace OpenTelemetry\API\Metrics\Noop;

use OpenTelemetry\API\Metrics\AsynchronousInstrument;
use OpenTelemetry\API\Metrics\CounterInterface;
use OpenTelemetry\API\Metrics\HistogramInterface;
use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\API\Metrics\ObservableCallbackInterface;
use OpenTelemetry\API\Metrics\ObservableCounterInterface;
use OpenTelemetry\API\Metrics\ObservableGaugeInterface;
use OpenTelemetry\API\Metrics\ObservableUpDownCounterInterface;
use OpenTelemetry\API\Metrics\UpDownCounterInterface;

final class NoopMeter implements MeterInterface
{
public function batchObserve(callable $callback, AsynchronousInstrument $instrument, AsynchronousInstrument ...$instruments): ObservableCallbackInterface
{
return new NoopObservableCallback();
}

public function createCounter(string $name, ?string $unit = null, ?string $description = null, array $advisory = []): CounterInterface
{
return new NoopCounter();
Expand Down
2 changes: 1 addition & 1 deletion src/API/Metrics/ObservableCounterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace OpenTelemetry\API\Metrics;

interface ObservableCounterInterface
interface ObservableCounterInterface extends AsynchronousInstrument
{

/**
Expand Down
2 changes: 1 addition & 1 deletion src/API/Metrics/ObservableGaugeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace OpenTelemetry\API\Metrics;

interface ObservableGaugeInterface
interface ObservableGaugeInterface extends AsynchronousInstrument
{

/**
Expand Down
2 changes: 1 addition & 1 deletion src/API/Metrics/ObservableUpDownCounterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace OpenTelemetry\API\Metrics;

interface ObservableUpDownCounterInterface
interface ObservableUpDownCounterInterface extends AsynchronousInstrument
{

/**
Expand Down
12 changes: 12 additions & 0 deletions src/API/Metrics/SynchronousInstrument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\API\Metrics;

/**
* Marker interface for synchronous instruments.
*/
interface SynchronousInstrument
{
}
2 changes: 1 addition & 1 deletion src/API/Metrics/UpDownCounterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use OpenTelemetry\Context\ContextInterface;

interface UpDownCounterInterface
interface UpDownCounterInterface extends SynchronousInstrument
{

/**
Expand Down
2 changes: 1 addition & 1 deletion src/API/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"symfony/polyfill-php82": "^1.26"
},
"conflict": {
"open-telemetry/sdk": "<=1.0.1"
"open-telemetry/sdk": "<=1.0.4"
},
"autoload": {
"psr-4": {
Expand Down
43 changes: 43 additions & 0 deletions src/SDK/Metrics/AsynchronousInstruments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\SDK\Metrics;

use ArrayAccess;
use OpenTelemetry\API\Metrics\ObservableCallbackInterface;
use function OpenTelemetry\SDK\Common\Util\closure;
use function OpenTelemetry\SDK\Common\Util\weaken;
use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface;

/**
* @internal
*/
final class AsynchronousInstruments
{
/**
* @param ArrayAccess<object, ObservableCallbackDestructor> $destructors
* @param non-empty-list<Instrument> $instruments
*/
public static function observe(
MetricWriterInterface $writer,
ArrayAccess $destructors,
callable $callback,
array $instruments,
ReferenceCounterInterface $referenceCounter
): ObservableCallbackInterface {
$target = null;
$callback = weaken(closure($callback), $target);

$callbackId = $writer->registerCallback($callback, ...$instruments);
$referenceCounter->acquire();

$destructor = null;
if ($target) {
$destructor = $destructors[$target] ??= new ObservableCallbackDestructor($destructors, $writer);
$destructor->callbackIds[$callbackId] = $referenceCounter;
}

return new ObservableCallback($writer, $referenceCounter, $callbackId, $destructor, $target);
}
}
26 changes: 2 additions & 24 deletions src/SDK/Metrics/Counter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,11 @@
namespace OpenTelemetry\SDK\Metrics;

use OpenTelemetry\API\Metrics\CounterInterface;
use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface;

/**
* @internal
*/
final class Counter implements CounterInterface
final class Counter implements CounterInterface, InstrumentHandle
{
private MetricWriterInterface $writer;
private Instrument $instrument;
private ReferenceCounterInterface $referenceCounter;

public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter)
{
$this->writer = $writer;
$this->instrument = $instrument;
$this->referenceCounter = $referenceCounter;

$this->referenceCounter->acquire();
}

public function __destruct()
{
$this->referenceCounter->release();
}

public function add($amount, iterable $attributes = [], $context = null): void
{
$this->writer->record($this->instrument, $amount, $attributes, $context);
}
use SynchronousInstrumentTrait { write as add; }
}
26 changes: 2 additions & 24 deletions src/SDK/Metrics/Histogram.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,11 @@
namespace OpenTelemetry\SDK\Metrics;

use OpenTelemetry\API\Metrics\HistogramInterface;
use OpenTelemetry\SDK\Metrics\MetricRegistry\MetricWriterInterface;

/**
* @internal
*/
final class Histogram implements HistogramInterface
final class Histogram implements HistogramInterface, InstrumentHandle
{
private MetricWriterInterface $writer;
private Instrument $instrument;
private ReferenceCounterInterface $referenceCounter;

public function __construct(MetricWriterInterface $writer, Instrument $instrument, ReferenceCounterInterface $referenceCounter)
{
$this->writer = $writer;
$this->instrument = $instrument;
$this->referenceCounter = $referenceCounter;

$this->referenceCounter->acquire();
}

public function __destruct()
{
$this->referenceCounter->release();
}

public function record($amount, iterable $attributes = [], $context = null): void
{
$this->writer->record($this->instrument, $amount, $attributes, $context);
}
use SynchronousInstrumentTrait { write as record; }
}
13 changes: 13 additions & 0 deletions src/SDK/Metrics/InstrumentHandle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\SDK\Metrics;

/**
* @internal
*/
interface InstrumentHandle
{
public function getHandle(): Instrument;
}
Loading
Loading