Drop PHP 7.4 support (#1244)
* drop php 7.4 support update composer.json minimums, and run rector over the code to update what it can. changed some static analysis config to fix some rector-induced failures. * adding union typehints * reformat constructor property promotions * updating/removing phpdoc * suppress protobuf extension complaint submitted a PR upstream to fix phan stubs * don't validate packages against 7.4 * remove php8 polyfill * fix readonly comments * apply trailing commas to multiline fixer upgrade php-cs-fixer, and apply a new rule for multiline comments * remove unreachable default match arms for protobuf serializer * adding more union types to vars * use weakmap directly * remove handling for not-supported WeakMap * spacing
This commit is contained in:
parent
cc56628c4d
commit
f798bb6f01
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version: ['7.4', '8.0', '8.1', '8.2', '8.3']
|
||||
php-version: ['8.0', '8.1', '8.2', '8.3']
|
||||
experimental: [false]
|
||||
composer_args: [""]
|
||||
include:
|
||||
|
|
@ -138,4 +138,5 @@ jobs:
|
|||
needs: php
|
||||
with:
|
||||
matrix_extension: '["ast, json, grpc"]'
|
||||
matrix_php_version: '["8.0", "8.1", "8.2", "8.3"]'
|
||||
install_directory: '~/.test/.packages'
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ jobs:
|
|||
name: OpenTelemetry PHP base docker image creation
|
||||
strategy:
|
||||
matrix:
|
||||
php-version: ['7.4', '8.0', '8.1', '8.2', '8.3']
|
||||
php-version: ['8.0', '8.1', '8.2', '8.3']
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ return [
|
|||
//
|
||||
// Note that the **only** effect of choosing `'5.6'` is to infer that functions removed in php 7.0 exist.
|
||||
// (See `backward_compatibility_checks` for additional options)
|
||||
'target_php_version' => '7.4',
|
||||
'target_php_version' => '8.0',
|
||||
|
||||
// If enabled, missing properties will be created when
|
||||
// they are first seen. If false, we'll report an
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ return $config->setRules([
|
|||
'blank_line_before_statement' => true,
|
||||
'cast_spaces' => true,
|
||||
'declare_strict_types' => true,
|
||||
'function_typehint_space' => true,
|
||||
'type_declaration_spaces' => true,
|
||||
'include' => true,
|
||||
'lowercase_cast' => true,
|
||||
'new_with_braces' => true,
|
||||
'new_with_parentheses' => true,
|
||||
'no_extra_blank_lines' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_trailing_whitespace' => true,
|
||||
|
|
@ -41,9 +41,9 @@ return $config->setRules([
|
|||
'phpdoc_scalar' => true,
|
||||
'phpdoc_types' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'single_blank_line_before_namespace' => true,
|
||||
'blank_lines_before_namespace' => true,
|
||||
'single_quote' => true,
|
||||
'trailing_comma_in_multiline' => true,
|
||||
'trailing_comma_in_multiline' => ['elements' => ['arrays', 'parameters', 'match']],
|
||||
])
|
||||
->setRiskyAllowed(true)
|
||||
->setFinder($finder);
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ This does the following things:
|
|||
### Other PHP versions
|
||||
|
||||
We aim to support officially supported PHP versions, according to https://www.php.net/supported-versions.php. The
|
||||
developer image `ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base` is tagged as `7.4`, `8.0`, `8.1` and `8.2`
|
||||
respectively, with `7.4` being the default. You can execute the test suite against other PHP versions by running the
|
||||
developer image `ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base` is tagged as `8.0`, `8.1`, `8.2` and `8.3`
|
||||
respectively, with `8.0` being the default. You can execute the test suite against other PHP versions by running the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
include .env
|
||||
|
||||
PHP_VERSION ?= 7.4
|
||||
PHP_VERSION ?= 8.0
|
||||
DOCKER_COMPOSE ?= docker-compose
|
||||
DC_RUN_PHP = $(DOCKER_COMPOSE) run --rm php
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"readme": "./README.md",
|
||||
"license": "Apache-2.0",
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"ext-json": "*",
|
||||
"google/protobuf": "^3.22",
|
||||
"php-http/discovery": "^1.14",
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
"psr/http-message": "^1.0.1|^2.0",
|
||||
"psr/log": "^1.1|^2.0|^3.0",
|
||||
"symfony/polyfill-mbstring": "^1.23",
|
||||
"symfony/polyfill-php80": "^1.26",
|
||||
"symfony/polyfill-php81": "^1.26",
|
||||
"symfony/polyfill-php82": "^1.26"
|
||||
},
|
||||
|
|
@ -77,9 +76,9 @@
|
|||
"ext-grpc": "*",
|
||||
"grpc/grpc": "^1.30",
|
||||
"assertwell/phpunit-global-state": "^0.2.2",
|
||||
"composer/xdebug-handler": "^2.0",
|
||||
"composer/xdebug-handler": "^3.0",
|
||||
"dg/bypass-finals": "^1.4",
|
||||
"friendsofphp/php-cs-fixer": "^3.4",
|
||||
"friendsofphp/php-cs-fixer": "^3.51",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"guzzlehttp/psr7": "^2.1",
|
||||
"mikey179/vfsstream": "^1.6.11",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
php:
|
||||
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-7.4}
|
||||
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-8.0}
|
||||
volumes:
|
||||
- ./:/usr/src/myapp
|
||||
depends_on:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ services:
|
|||
context: .
|
||||
dockerfile: docker/examples/Dockerfile
|
||||
args:
|
||||
- PHP_VERSION=7.4-fpm
|
||||
- PHP_VERSION=8.0-fpm
|
||||
- EXT_ENABLE=redis
|
||||
volumes:
|
||||
- ./examples/prometheus/index.php:/var/www/public/index.php
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
php:
|
||||
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-7.4}
|
||||
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-8.0}
|
||||
volumes:
|
||||
- ./:/usr/src/myapp
|
||||
- ./:/usr/src/open-telemetry/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
php:
|
||||
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-7.4}
|
||||
image: ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION:-8.0}
|
||||
volumes:
|
||||
- ./:/usr/src/myapp
|
||||
user: "${PHP_USER}:root"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ARG PHP_VERSION=7.4
|
||||
ARG PHP_VERSION=8.0
|
||||
FROM php:${PHP_VERSION}-cli-alpine as php_build
|
||||
|
||||
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Example;
|
||||
|
||||
use OpenTelemetry\API\Globals;
|
||||
|
||||
putenv('OTEL_PHP_AUTOLOAD_ENABLED=true');
|
||||
putenv('OTEL_TRACES_EXPORTER=console');
|
||||
putenv('OTEL_METRICS_EXPORTER=console');
|
||||
putenv('OTEL_PHP_INTERNAL_METRICS_ENABLED=true');
|
||||
|
||||
require __DIR__ . '/../../../vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* Demonstrates batch span processing which also emits metrics for the internal state
|
||||
* of the processor (eg spans received, queue length)
|
||||
*/
|
||||
|
||||
echo 'Starting ConsoleSpanExporter with BatchSpanProcessor and metrics' . PHP_EOL;
|
||||
|
||||
$tracer = Globals::tracerProvider()->getTracer('io.opentelemetry.contrib.php');
|
||||
$tracer->spanBuilder('root')->startSpan()->end();
|
||||
|
||||
echo PHP_EOL . 'Example complete! ' . PHP_EOL;
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"google/protobuf": "^3.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
|
|
|
|||
|
|
@ -18,4 +18,11 @@
|
|||
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
|
||||
<pluginClass class="Psalm\MockeryPlugin\Plugin"/>
|
||||
</plugins>
|
||||
<issueHandlers>
|
||||
<UndefinedClass>
|
||||
<errorLevel type="suppress">
|
||||
<referencedClass name="GMP" />
|
||||
</errorLevel>
|
||||
</UndefinedClass>
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
|
|
|
|||
|
|
@ -5,18 +5,18 @@ declare(strict_types=1);
|
|||
use Rector\CodeQuality\Rector\Array_\CallableThisArrayToAnonymousFunctionRector;
|
||||
use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector;
|
||||
use Rector\Config\RectorConfig;
|
||||
use Rector\Core\ValueObject\PhpVersion;
|
||||
use Rector\ValueObject\PhpVersion;
|
||||
use Rector\Set\ValueObject\SetList;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->phpVersion(PhpVersion::PHP_74);
|
||||
$rectorConfig->phpVersion(PhpVersion::PHP_80);
|
||||
|
||||
$rectorConfig->paths([
|
||||
__DIR__ . '/src',
|
||||
]);
|
||||
|
||||
$rectorConfig->sets([
|
||||
SetList::PHP_74,
|
||||
SetList::PHP_80,
|
||||
SetList::CODE_QUALITY,
|
||||
]);
|
||||
$rectorConfig->skip([
|
||||
|
|
|
|||
|
|
@ -41,13 +41,9 @@ final class Baggage implements BaggageInterface
|
|||
return self::$emptyBaggage;
|
||||
}
|
||||
|
||||
/** @var array<string, Entry> */
|
||||
private array $entries;
|
||||
|
||||
/** @param array<string, Entry> $entries */
|
||||
public function __construct(array $entries = [])
|
||||
public function __construct(private array $entries = [])
|
||||
{
|
||||
$this->entries = $entries;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
|
|||
|
|
@ -6,13 +6,9 @@ namespace OpenTelemetry\API\Baggage;
|
|||
|
||||
final class BaggageBuilder implements BaggageBuilderInterface
|
||||
{
|
||||
/** @var array<string, Entry> */
|
||||
private array $entries;
|
||||
|
||||
/** @param array<string, Entry> $entries */
|
||||
public function __construct(array $entries = [])
|
||||
public function __construct(private array $entries = [])
|
||||
{
|
||||
$this->entries = $entries;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ interface BaggageBuilderInterface
|
|||
{
|
||||
/**
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/baggage/api.md#set-value
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set(string $key, $value, API\MetadataInterface $metadata = null): API\BaggageBuilderInterface;
|
||||
public function set(string $key, mixed $value, API\MetadataInterface $metadata = null): API\BaggageBuilderInterface;
|
||||
|
||||
/**
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/baggage/api.md#remove-value
|
||||
|
|
|
|||
|
|
@ -6,27 +6,13 @@ namespace OpenTelemetry\API\Baggage;
|
|||
|
||||
final class Entry
|
||||
{
|
||||
/** @var mixed */
|
||||
private $value;
|
||||
|
||||
private MetadataInterface $metadata;
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param MetadataInterface $metadata
|
||||
*/
|
||||
public function __construct(
|
||||
$value,
|
||||
MetadataInterface $metadata
|
||||
private mixed $value,
|
||||
private MetadataInterface $metadata,
|
||||
) {
|
||||
$this->value = $value;
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue()
|
||||
public function getValue(): mixed
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,8 @@ final class Metadata implements MetadataInterface
|
|||
return self::$instance ??= new self('');
|
||||
}
|
||||
|
||||
private string $metadata;
|
||||
|
||||
public function __construct(string $metadata)
|
||||
public function __construct(private string $metadata)
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
|
|
|
|||
|
|
@ -17,12 +17,10 @@ final class Parser
|
|||
private const EXCLUDED_VALUE_CHARS = [' ', '"', ',', ';', '\\'];
|
||||
private const EQUALS = '=';
|
||||
|
||||
/** @readonly */
|
||||
private string $baggageHeader;
|
||||
|
||||
public function __construct(string $baggageHeader)
|
||||
{
|
||||
$this->baggageHeader = $baggageHeader;
|
||||
public function __construct(
|
||||
/** @readonly */
|
||||
private string $baggageHeader,
|
||||
) {
|
||||
}
|
||||
|
||||
public function parseInto(BaggageBuilderInterface $baggageBuilder): void
|
||||
|
|
|
|||
|
|
@ -8,11 +8,8 @@ use Psr\Log\LoggerInterface;
|
|||
|
||||
class Psr3LogWriter implements LogWriterInterface
|
||||
{
|
||||
private LoggerInterface $logger;
|
||||
|
||||
public function __construct(LoggerInterface $logger)
|
||||
public function __construct(private LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function write($level, string $message, array $context): void
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class LogWriterFactory
|
|||
return new Psr3LogWriter($logger);
|
||||
}
|
||||
error_log('OpenTelemetry: cannot use OTEL_PHP_LOG_DESTINATION=psr3 without providing a PSR-3 logger');
|
||||
|
||||
//default to error log
|
||||
return new ErrorLogWriter();
|
||||
case 'error_log':
|
||||
|
|
|
|||
|
|
@ -27,21 +27,12 @@ final class Globals
|
|||
private static array $initializers = [];
|
||||
private static ?self $globals = null;
|
||||
|
||||
private TracerProviderInterface $tracerProvider;
|
||||
private MeterProviderInterface $meterProvider;
|
||||
private TextMapPropagatorInterface $propagator;
|
||||
private LoggerProviderInterface $loggerProvider;
|
||||
|
||||
public function __construct(
|
||||
TracerProviderInterface $tracerProvider,
|
||||
MeterProviderInterface $meterProvider,
|
||||
LoggerProviderInterface $loggerProvider,
|
||||
TextMapPropagatorInterface $propagator
|
||||
private TracerProviderInterface $tracerProvider,
|
||||
private MeterProviderInterface $meterProvider,
|
||||
private LoggerProviderInterface $loggerProvider,
|
||||
private TextMapPropagatorInterface $propagator,
|
||||
) {
|
||||
$this->tracerProvider = $tracerProvider;
|
||||
$this->meterProvider = $meterProvider;
|
||||
$this->loggerProvider = $loggerProvider;
|
||||
$this->propagator = $propagator;
|
||||
}
|
||||
|
||||
public static function tracerProvider(): TracerProviderInterface
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\API\Instrumentation;
|
||||
|
||||
use ArrayAccess;
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use OpenTelemetry\API\Globals;
|
||||
use OpenTelemetry\API\Logs\LoggerInterface;
|
||||
use OpenTelemetry\API\Logs\LoggerProviderInterface;
|
||||
|
|
@ -14,7 +11,7 @@ use OpenTelemetry\API\Metrics\MeterInterface;
|
|||
use OpenTelemetry\API\Metrics\MeterProviderInterface;
|
||||
use OpenTelemetry\API\Trace\TracerInterface;
|
||||
use OpenTelemetry\API\Trace\TracerProviderInterface;
|
||||
use const PHP_VERSION_ID;
|
||||
use WeakMap;
|
||||
|
||||
/**
|
||||
* Provides access to cached {@link TracerInterface} and {@link MeterInterface}
|
||||
|
|
@ -26,51 +23,31 @@ use const PHP_VERSION_ID;
|
|||
*/
|
||||
final class CachedInstrumentation
|
||||
{
|
||||
private string $name;
|
||||
private ?string $version;
|
||||
private ?string $schemaUrl;
|
||||
private iterable $attributes;
|
||||
/** @var ArrayAccess<TracerProviderInterface, TracerInterface>|null */
|
||||
private ?ArrayAccess $tracers;
|
||||
/** @var ArrayAccess<MeterProviderInterface, MeterInterface>|null */
|
||||
private ?ArrayAccess $meters;
|
||||
/** @var ArrayAccess<LoggerProviderInterface, LoggerInterface>|null */
|
||||
private ?ArrayAccess $loggers;
|
||||
/** @var WeakMap<TracerProviderInterface, TracerInterface> */
|
||||
private WeakMap $tracers;
|
||||
/** @var WeakMap<MeterProviderInterface, MeterInterface> */
|
||||
private WeakMap $meters;
|
||||
/** @var WeakMap<LoggerProviderInterface, LoggerInterface> */
|
||||
private WeakMap $loggers;
|
||||
|
||||
public function __construct(string $name, ?string $version = null, ?string $schemaUrl = null, iterable $attributes = [])
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->schemaUrl = $schemaUrl;
|
||||
$this->attributes = $attributes;
|
||||
$this->tracers = self::createWeakMap();
|
||||
$this->meters = self::createWeakMap();
|
||||
$this->loggers = self::createWeakMap();
|
||||
}
|
||||
|
||||
private static function createWeakMap(): ?ArrayAccess
|
||||
{
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @phan-suppress-next-line PhanUndeclaredClassReference */
|
||||
assert(class_exists(\WeakMap::class, false));
|
||||
/** @phan-suppress-next-line PhanUndeclaredClassMethod */
|
||||
$map = new \WeakMap();
|
||||
assert($map instanceof ArrayAccess);
|
||||
|
||||
return $map;
|
||||
/**
|
||||
* @psalm-suppress PropertyTypeCoercion
|
||||
*/
|
||||
public function __construct(
|
||||
private string $name,
|
||||
private ?string $version = null,
|
||||
private ?string $schemaUrl = null,
|
||||
private iterable $attributes = [],
|
||||
) {
|
||||
$this->tracers = new \WeakMap();
|
||||
$this->meters = new \WeakMap();
|
||||
$this->loggers = new \WeakMap();
|
||||
}
|
||||
|
||||
public function tracer(): TracerInterface
|
||||
{
|
||||
$tracerProvider = Globals::tracerProvider();
|
||||
|
||||
if ($this->tracers === null) {
|
||||
return $tracerProvider->getTracer($this->name, $this->version, $this->schemaUrl, $this->attributes);
|
||||
}
|
||||
|
||||
return $this->tracers[$tracerProvider] ??= $tracerProvider->getTracer($this->name, $this->version, $this->schemaUrl, $this->attributes);
|
||||
}
|
||||
|
||||
|
|
@ -78,20 +55,12 @@ final class CachedInstrumentation
|
|||
{
|
||||
$meterProvider = Globals::meterProvider();
|
||||
|
||||
if ($this->meters === null) {
|
||||
return $meterProvider->getMeter($this->name, $this->version, $this->schemaUrl, $this->attributes);
|
||||
}
|
||||
|
||||
return $this->meters[$meterProvider] ??= $meterProvider->getMeter($this->name, $this->version, $this->schemaUrl, $this->attributes);
|
||||
}
|
||||
public function logger(): LoggerInterface
|
||||
{
|
||||
$loggerProvider = Globals::loggerProvider();
|
||||
|
||||
if ($this->loggers === null) {
|
||||
return $loggerProvider->getLogger($this->name, $this->version, $this->schemaUrl, $this->attributes);
|
||||
}
|
||||
|
||||
return $this->loggers[$loggerProvider] ??= $loggerProvider->getLogger($this->name, $this->version, $this->schemaUrl, $this->attributes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ trait InstrumentationTrait
|
|||
public function activate(): bool
|
||||
{
|
||||
$this->validateImplementation();
|
||||
|
||||
// activate instrumentation with the API. not implemented yet.
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,10 @@ namespace OpenTelemetry\API\Logs;
|
|||
|
||||
class EventLogger implements EventLoggerInterface
|
||||
{
|
||||
private LoggerInterface $logger;
|
||||
private string $domain;
|
||||
|
||||
public function __construct(LoggerInterface $logger, string $domain)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
$this->domain = $domain;
|
||||
public function __construct(
|
||||
private LoggerInterface $logger,
|
||||
private string $domain,
|
||||
) {
|
||||
}
|
||||
|
||||
public function logEvent(string $eventName, LogRecord $logRecord): void
|
||||
|
|
|
|||
|
|
@ -15,15 +15,10 @@ class LogRecord
|
|||
protected ?ContextInterface $context = null;
|
||||
protected int $severityNumber = 0;
|
||||
protected ?string $severityText = null;
|
||||
protected $body = null;
|
||||
protected array $attributes = [];
|
||||
|
||||
/**
|
||||
* @param mixed $body
|
||||
*/
|
||||
public function __construct($body = null)
|
||||
public function __construct(protected mixed $body = null)
|
||||
{
|
||||
$this->body = $body;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -45,7 +40,6 @@ class LogRecord
|
|||
}
|
||||
|
||||
/**
|
||||
* @param int $severityNumber Severity number
|
||||
* @see https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitynumber
|
||||
*/
|
||||
public function setSeverityNumber(int $severityNumber): self
|
||||
|
|
@ -79,7 +73,7 @@ class LogRecord
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setAttribute(string $name, $value): self
|
||||
public function setAttribute(string $name, mixed $value): self
|
||||
{
|
||||
$this->attributes[$name] = $value;
|
||||
|
||||
|
|
@ -89,7 +83,7 @@ class LogRecord
|
|||
/**
|
||||
* @param mixed $body The log record body
|
||||
*/
|
||||
public function setBody($body = null): self
|
||||
public function setBody(mixed $body = null): self
|
||||
{
|
||||
$this->body = $body;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@ interface LoggerProviderInterface
|
|||
string $name,
|
||||
?string $version = null,
|
||||
?string $schemaUrl = null,
|
||||
iterable $attributes = [] //instrumentation scope attributes
|
||||
iterable $attributes = [], //instrumentation scope attributes
|
||||
): LoggerInterface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,25 +16,16 @@ class Psr3
|
|||
*/
|
||||
public static function severityNumber(string $level): int
|
||||
{
|
||||
switch (strtolower($level)) {
|
||||
case LogLevel::DEBUG:
|
||||
return 5;
|
||||
case LogLevel::INFO:
|
||||
return 9;
|
||||
case LogLevel::NOTICE:
|
||||
return 10;
|
||||
case LogLevel::WARNING:
|
||||
return 13;
|
||||
case LogLevel::ERROR:
|
||||
return 17;
|
||||
case LogLevel::CRITICAL:
|
||||
return 18;
|
||||
case LogLevel::ALERT:
|
||||
return 19;
|
||||
case LogLevel::EMERGENCY:
|
||||
return 21;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return match (strtolower($level)) {
|
||||
LogLevel::DEBUG => 5,
|
||||
LogLevel::INFO => 9,
|
||||
LogLevel::NOTICE => 10,
|
||||
LogLevel::WARNING => 13,
|
||||
LogLevel::ERROR => 17,
|
||||
LogLevel::CRITICAL => 18,
|
||||
LogLevel::ALERT => 19,
|
||||
LogLevel::EMERGENCY => 21,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ interface CounterInterface extends SynchronousInstrument
|
|||
* @param float|int $amount non-negative amount to increment by
|
||||
* @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://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#add
|
||||
*/
|
||||
public function add($amount, iterable $attributes = [], $context = null): void;
|
||||
public function add(float|int $amount, iterable $attributes = [], ContextInterface|false|null $context = null): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ interface HistogramInterface extends SynchronousInstrument
|
|||
*
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#record
|
||||
*/
|
||||
public function record($amount, iterable $attributes = [], $context = null): void;
|
||||
public function record(float|int $amount, iterable $attributes = [], ContextInterface|false|null $context = null): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@ interface MeterInterface
|
|||
public function batchObserve(
|
||||
callable $callback,
|
||||
AsynchronousInstrument $instrument,
|
||||
AsynchronousInstrument ...$instruments
|
||||
AsynchronousInstrument ...$instruments,
|
||||
): ObservableCallbackInterface;
|
||||
|
||||
/**
|
||||
* Creates a `Counter`.
|
||||
*
|
||||
* @param string $name name of the instrument
|
||||
* @param string|null $unit unit of measure
|
||||
* @param string|null $description description of the instrument
|
||||
* @param ?string $unit unit of measure
|
||||
* @param ?string $description description of the instrument
|
||||
* @param array $advisory an optional set of recommendations
|
||||
* @return CounterInterface created instrument
|
||||
*
|
||||
|
|
@ -56,15 +56,15 @@ interface MeterInterface
|
|||
string $name,
|
||||
?string $unit = null,
|
||||
?string $description = null,
|
||||
array $advisory = []
|
||||
array $advisory = [],
|
||||
): CounterInterface;
|
||||
|
||||
/**
|
||||
* Creates an `ObservableCounter`.
|
||||
*
|
||||
* @param string $name name of the instrument
|
||||
* @param string|null $unit unit of measure
|
||||
* @param string|null $description description of the instrument
|
||||
* @param ?string $unit unit of measure
|
||||
* @param ?string $description description of the instrument
|
||||
* @param array|callable $advisory an optional set of recommendations, or
|
||||
* deprecated: the first callback to report measurements
|
||||
* @param callable ...$callbacks responsible for reporting measurements
|
||||
|
|
@ -76,8 +76,8 @@ interface MeterInterface
|
|||
string $name,
|
||||
?string $unit = null,
|
||||
?string $description = null,
|
||||
$advisory = [],
|
||||
callable ...$callbacks
|
||||
array|callable $advisory = [],
|
||||
callable ...$callbacks,
|
||||
): ObservableCounterInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -96,7 +96,7 @@ interface MeterInterface
|
|||
string $name,
|
||||
?string $unit = null,
|
||||
?string $description = null,
|
||||
array $advisory = []
|
||||
array $advisory = [],
|
||||
): HistogramInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -116,8 +116,8 @@ interface MeterInterface
|
|||
string $name,
|
||||
?string $unit = null,
|
||||
?string $description = null,
|
||||
$advisory = [],
|
||||
callable ...$callbacks
|
||||
array|callable $advisory = [],
|
||||
callable ...$callbacks,
|
||||
): ObservableGaugeInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -135,7 +135,7 @@ interface MeterInterface
|
|||
string $name,
|
||||
?string $unit = null,
|
||||
?string $description = null,
|
||||
array $advisory = []
|
||||
array $advisory = [],
|
||||
): UpDownCounterInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -155,7 +155,7 @@ interface MeterInterface
|
|||
string $name,
|
||||
?string $unit = null,
|
||||
?string $description = null,
|
||||
$advisory = [],
|
||||
callable ...$callbacks
|
||||
array|callable $advisory = [],
|
||||
callable ...$callbacks,
|
||||
): ObservableUpDownCounterInterface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,6 @@ interface MeterProviderInterface
|
|||
string $name,
|
||||
?string $version = null,
|
||||
?string $schemaUrl = null,
|
||||
iterable $attributes = []
|
||||
iterable $attributes = [],
|
||||
): MeterInterface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ final class NoopMeterProvider implements MeterProviderInterface
|
|||
string $name,
|
||||
?string $version = null,
|
||||
?string $schemaUrl = null,
|
||||
iterable $attributes = []
|
||||
iterable $attributes = [],
|
||||
): MeterInterface {
|
||||
return new NoopMeter();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ interface ObserverInterface
|
|||
* @param iterable<non-empty-string, string|bool|float|int|array|null> $attributes
|
||||
* attributes of the data point
|
||||
*/
|
||||
public function observe($amount, iterable $attributes = []): void;
|
||||
public function observe(float|int $amount, iterable $attributes = []): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,8 @@ use Throwable;
|
|||
*/
|
||||
final class NonRecordingSpan extends Span
|
||||
{
|
||||
private SpanContextInterface $context;
|
||||
|
||||
public function __construct(
|
||||
SpanContextInterface $context
|
||||
) {
|
||||
$this->context = $context;
|
||||
public function __construct(private SpanContextInterface $context)
|
||||
{
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
|
|||
|
|
@ -10,17 +10,13 @@ use OpenTelemetry\Context\ContextStorageInterface;
|
|||
|
||||
final class NoopSpanBuilder implements SpanBuilderInterface
|
||||
{
|
||||
private ContextStorageInterface $contextStorage;
|
||||
private ContextInterface|false|null $parentContext = null;
|
||||
|
||||
/** @var ContextInterface|false|null */
|
||||
private $parentContext = null;
|
||||
|
||||
public function __construct(ContextStorageInterface $contextStorage)
|
||||
public function __construct(private ContextStorageInterface $contextStorage)
|
||||
{
|
||||
$this->contextStorage = $contextStorage;
|
||||
}
|
||||
|
||||
public function setParent($context): SpanBuilderInterface
|
||||
public function setParent(ContextInterface|false|null $context): SpanBuilderInterface
|
||||
{
|
||||
$this->parentContext = $context;
|
||||
|
||||
|
|
@ -32,7 +28,7 @@ final class NoopSpanBuilder implements SpanBuilderInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setAttribute(string $key, $value): SpanBuilderInterface
|
||||
public function setAttribute(string $key, mixed $value): SpanBuilderInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class NoopTracerProvider implements TracerProviderInterface
|
|||
string $name,
|
||||
?string $version = null,
|
||||
?string $schemaUrl = null,
|
||||
iterable $attributes = []
|
||||
iterable $attributes = [],
|
||||
): TracerInterface {
|
||||
return NoopTracer::getInstance();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,6 @@ class TraceContextValidator
|
|||
public const TRACE_FLAG_LENGTH = 2;
|
||||
public const TRACE_VERSION_REGEX = '/^(?!ff)[\da-f]{2}$/';
|
||||
|
||||
/**
|
||||
* @param string $traceVersion
|
||||
* @return bool Returns a value that indicates whether a trace version is valid.
|
||||
*/
|
||||
public static function isValidTraceVersion(string $traceVersion): bool
|
||||
{
|
||||
return 1 === preg_match(self::TRACE_VERSION_REGEX, $traceVersion);
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ interface SpanBuilderInterface
|
|||
*
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#span-creation
|
||||
*/
|
||||
public function setParent($context): SpanBuilderInterface;
|
||||
public function setParent(ContextInterface|false|null $context): SpanBuilderInterface;
|
||||
|
||||
public function addLink(SpanContextInterface $context, iterable $attributes = []): SpanBuilderInterface;
|
||||
public function setAttribute(string $key, $value): SpanBuilderInterface;
|
||||
public function setAttribute(string $key, mixed $value): SpanBuilderInterface;
|
||||
public function setAttributes(iterable $attributes): SpanBuilderInterface;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -15,35 +15,24 @@ final class SpanContext implements SpanContextInterface
|
|||
* @see https://www.w3.org/TR/trace-context/#sampled-flag
|
||||
*/
|
||||
private bool $isSampled;
|
||||
|
||||
private string $traceId;
|
||||
private string $spanId;
|
||||
private ?TraceStateInterface $traceState;
|
||||
private bool $isValid = true;
|
||||
private bool $isRemote;
|
||||
private int $traceFlags;
|
||||
|
||||
private function __construct(
|
||||
string $traceId,
|
||||
string $spanId,
|
||||
int $traceFlags,
|
||||
bool $isRemote,
|
||||
TraceStateInterface $traceState = null
|
||||
private string $traceId,
|
||||
private string $spanId,
|
||||
private int $traceFlags,
|
||||
private bool $isRemote,
|
||||
private ?TraceStateInterface $traceState = null,
|
||||
) {
|
||||
// TraceId must be exactly 16 bytes (32 chars) and at least one non-zero byte
|
||||
// SpanId must be exactly 8 bytes (16 chars) and at least one non-zero byte
|
||||
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {
|
||||
$traceId = SpanContextValidator::INVALID_TRACE;
|
||||
$spanId = SpanContextValidator::INVALID_SPAN;
|
||||
$this->traceId = SpanContextValidator::INVALID_TRACE;
|
||||
$this->spanId = SpanContextValidator::INVALID_SPAN;
|
||||
$this->isValid=false;
|
||||
}
|
||||
|
||||
$this->traceId = $traceId;
|
||||
$this->spanId = $spanId;
|
||||
$this->traceState = $traceState;
|
||||
$this->isRemote = $isRemote;
|
||||
$this->isSampled = ($traceFlags & TraceFlags::SAMPLED) === TraceFlags::SAMPLED;
|
||||
$this->traceFlags = $traceFlags;
|
||||
}
|
||||
|
||||
public function getTraceId(): string
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ interface SpanInterface extends ImplicitContextKeyedInterface
|
|||
* @param non-empty-string $key
|
||||
* @param bool|int|float|string|array|null $value Note: arrays MUST be homogeneous, i.e. it MUST NOT contain values of different types.
|
||||
*/
|
||||
public function setAttribute(string $key, $value): SpanInterface;
|
||||
public function setAttribute(string $key, bool|int|float|string|array|null $value): SpanInterface;
|
||||
|
||||
/**
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/trace/api.md#set-attributes
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ interface TraceStateInterface
|
|||
* Return a new TraceState object that inherits from this TraceState
|
||||
* and contains the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @return TraceStateInterface
|
||||
*/
|
||||
public function with(string $key, string $value): TraceStateInterface;
|
||||
|
|
@ -34,7 +32,6 @@ interface TraceStateInterface
|
|||
* Return a new TraceState object that inherits from this TraceState
|
||||
* without the given key value pair.
|
||||
*
|
||||
* @param string $key
|
||||
* @return TraceStateInterface
|
||||
*/
|
||||
public function without(string $key): TraceStateInterface;
|
||||
|
|
@ -42,7 +39,6 @@ interface TraceStateInterface
|
|||
/**
|
||||
* Return the value of a given key from this TraceState if it exists
|
||||
*
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
public function get(string $key): ?string;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ interface TracerProviderInterface
|
|||
string $name,
|
||||
?string $version = null,
|
||||
?string $schemaUrl = null,
|
||||
iterable $attributes = []
|
||||
iterable $attributes = [],
|
||||
): TracerInterface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"open-telemetry/context": "^1.0",
|
||||
"psr/log": "^1.1|^2.0|^3.0",
|
||||
"symfony/polyfill-php80": "^1.26",
|
||||
"symfony/polyfill-php81": "^1.26",
|
||||
"symfony/polyfill-php82": "^1.26"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ final class Context implements ContextInterface
|
|||
|
||||
/**
|
||||
* @param ContextStorageInterface&ExecutionContextAwareInterface $storage
|
||||
* @todo update type-hint (php >= 8.1)
|
||||
*/
|
||||
public static function setStorage(ContextStorageInterface $storage): void
|
||||
{
|
||||
|
|
@ -47,6 +48,7 @@ final class Context implements ContextInterface
|
|||
|
||||
/**
|
||||
* @return ContextStorageInterface&ExecutionContextAwareInterface
|
||||
* @todo update return type-hint (php >= 8.1)
|
||||
*/
|
||||
public static function storage(): ContextStorageInterface
|
||||
{
|
||||
|
|
@ -55,11 +57,9 @@ final class Context implements ContextInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @param ContextInterface|false|null $context
|
||||
*
|
||||
* @internal OpenTelemetry
|
||||
*/
|
||||
public static function resolve($context, ?ContextStorageInterface $contextStorage = null): ContextInterface
|
||||
public static function resolve(ContextInterface|false|null $context, ?ContextStorageInterface $contextStorage = null): ContextInterface
|
||||
{
|
||||
return $context
|
||||
?? ($contextStorage ?? self::storage())->current()
|
||||
|
|
|
|||
|
|
@ -9,11 +9,8 @@ namespace OpenTelemetry\Context;
|
|||
*/
|
||||
final class ContextKey implements ContextKeyInterface
|
||||
{
|
||||
private ?string $name;
|
||||
|
||||
public function __construct(?string $name=null)
|
||||
public function __construct(private ?string $name = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function name(): ?string
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@ namespace OpenTelemetry\Context;
|
|||
*/
|
||||
final class ContextStorageHead
|
||||
{
|
||||
public ContextStorage $storage;
|
||||
public ?ContextStorageNode $node = null;
|
||||
|
||||
public function __construct(ContextStorage $storage)
|
||||
public function __construct(public ContextStorage $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,19 +11,13 @@ use function assert;
|
|||
*/
|
||||
final class ContextStorageNode implements ScopeInterface, ContextStorageScopeInterface
|
||||
{
|
||||
public ContextInterface $context;
|
||||
public ContextStorageHead $head;
|
||||
private ?ContextStorageNode $previous;
|
||||
private array $localStorage = [];
|
||||
|
||||
public function __construct(
|
||||
ContextInterface $context,
|
||||
ContextStorageHead $head,
|
||||
?ContextStorageNode $previous = null
|
||||
public ContextInterface $context,
|
||||
public ContextStorageHead $head,
|
||||
private ?ContextStorageNode $previous = null,
|
||||
) {
|
||||
$this->context = $context;
|
||||
$this->head = $head;
|
||||
$this->previous = $previous;
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool
|
||||
|
|
@ -76,8 +70,8 @@ final class ContextStorageNode implements ScopeInterface, ContextStorageScopeInt
|
|||
|
||||
assert($this->head->node !== null);
|
||||
for ($n = $this->head->node, $depth = 1;
|
||||
$n->previous !== $this;
|
||||
$n = $n->previous, $depth++) {
|
||||
$n->previous !== $this;
|
||||
$n = $n->previous, $depth++) {
|
||||
assert($n->previous !== null);
|
||||
}
|
||||
$n->previous = $this->previous;
|
||||
|
|
|
|||
|
|
@ -24,15 +24,12 @@ final class DebugScope implements ScopeInterface
|
|||
{
|
||||
private static bool $shutdownHandlerInitialized = false;
|
||||
private static bool $finalShutdownPhase = false;
|
||||
|
||||
private ContextStorageScopeInterface $scope;
|
||||
private ?int $fiberId;
|
||||
private array $createdAt;
|
||||
private ?array $detachedAt = null;
|
||||
|
||||
public function __construct(ContextStorageScopeInterface $scope)
|
||||
public function __construct(private ContextStorageScopeInterface $scope)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
$this->fiberId = self::currentFiberId();
|
||||
$this->createdAt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,15 +20,11 @@ use function trigger_error;
|
|||
*/
|
||||
final class FiberBoundContextStorage implements ContextStorageInterface, ExecutionContextAwareInterface
|
||||
{
|
||||
/** @var ContextStorageInterface&ExecutionContextAwareInterface */
|
||||
private ContextStorageInterface $storage;
|
||||
|
||||
/**
|
||||
* @param ContextStorageInterface&ExecutionContextAwareInterface $storage
|
||||
*/
|
||||
public function __construct(ContextStorageInterface $storage)
|
||||
public function __construct(private ContextStorageInterface $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
public function fork($id): void
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ use Fiber;
|
|||
*/
|
||||
final class FiberBoundContextStorageScope implements ScopeInterface, ContextStorageScopeInterface
|
||||
{
|
||||
private ContextStorageScopeInterface $scope;
|
||||
|
||||
public function __construct(ContextStorageScopeInterface $scope)
|
||||
public function __construct(private ContextStorageScopeInterface $scope)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool
|
||||
|
|
|
|||
|
|
@ -6,11 +6,8 @@ namespace OpenTelemetry\Context\Propagation;
|
|||
|
||||
use function array_key_first;
|
||||
use ArrayAccess;
|
||||
use function get_class;
|
||||
use function gettype;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
use function strcasecmp;
|
||||
|
|
@ -53,7 +50,7 @@ final class ArrayAccessGetterSetter implements PropagationGetterInterface, Propa
|
|||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Unsupported carrier type: %s.',
|
||||
is_object($carrier) ? get_class($carrier) : gettype($carrier),
|
||||
get_debug_type($carrier),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -75,7 +72,7 @@ final class ArrayAccessGetterSetter implements PropagationGetterInterface, Propa
|
|||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Unsupported carrier type: %s. Unable to get value associated with key:%s',
|
||||
is_object($carrier) ? get_class($carrier) : gettype($carrier),
|
||||
get_debug_type($carrier),
|
||||
$key
|
||||
)
|
||||
);
|
||||
|
|
@ -100,7 +97,7 @@ final class ArrayAccessGetterSetter implements PropagationGetterInterface, Propa
|
|||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Unsupported carrier type: %s. Unable to set value associated with key:%s',
|
||||
is_object($carrier) ? get_class($carrier) : gettype($carrier),
|
||||
get_debug_type($carrier),
|
||||
$key
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,14 +15,6 @@ final class MultiTextMapPropagator implements TextMapPropagatorInterface
|
|||
{
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var list<TextMapPropagatorInterface>
|
||||
*/
|
||||
private array $propagators = [];
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
private array $fields;
|
||||
|
|
@ -32,10 +24,11 @@ final class MultiTextMapPropagator implements TextMapPropagatorInterface
|
|||
*
|
||||
* @param list<TextMapPropagatorInterface> $propagators
|
||||
*/
|
||||
public function __construct(array $propagators)
|
||||
{
|
||||
$this->propagators = $propagators;
|
||||
$this->fields = $this->extractFields($propagators);
|
||||
public function __construct(
|
||||
/** @readonly */
|
||||
private array $propagators,
|
||||
) {
|
||||
$this->fields = $this->extractFields($this->propagators);
|
||||
}
|
||||
|
||||
public function fields(): array
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ final class SanitizeCombinedHeadersPropagationGetter implements PropagationGette
|
|||
private const SERVER_CONCAT_HEADERS_REGEX = '/;(?=[^,=;]*=|$)/';
|
||||
private const TRAILING_LEADING_SEPARATOR_REGEX = '/^' . self::LIST_MEMBERS_SEPARATOR . '+|' . self::LIST_MEMBERS_SEPARATOR . '+$/';
|
||||
|
||||
private PropagationGetterInterface $getter;
|
||||
|
||||
public function __construct(PropagationGetterInterface $getter)
|
||||
public function __construct(private PropagationGetterInterface $getter)
|
||||
{
|
||||
$this->getter = $getter;
|
||||
}
|
||||
|
||||
public function keys($carrier): array
|
||||
|
|
|
|||
|
|
@ -25,10 +25,8 @@ interface TextMapPropagatorInterface
|
|||
* via an {@see PropagationSetterInterface}.
|
||||
*
|
||||
* @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#textmap-inject
|
||||
*
|
||||
* @param mixed $carrier
|
||||
*/
|
||||
public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void;
|
||||
public function inject(mixed &$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void;
|
||||
|
||||
/**
|
||||
* Extracts specific values from the provided carrier into the provided {@see ContextInterface}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"symfony/polyfill-php80": "^1.26",
|
||||
"php": "^8.0",
|
||||
"symfony/polyfill-php81": "^1.26",
|
||||
"symfony/polyfill-php82": "^1.26"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use const Grpc\OP_SEND_INITIAL_METADATA;
|
|||
use const Grpc\OP_SEND_MESSAGE;
|
||||
use const Grpc\STATUS_OK;
|
||||
use Grpc\Timeval;
|
||||
use OpenTelemetry\Contrib\Otlp\ContentTypes;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use OpenTelemetry\SDK\Common\Future\CancellationInterface;
|
||||
use OpenTelemetry\SDK\Common\Future\CompletedFuture;
|
||||
|
|
@ -36,23 +37,21 @@ final class GrpcTransport implements TransportInterface
|
|||
{
|
||||
private array $metadata;
|
||||
private Channel $channel;
|
||||
private string $method;
|
||||
private bool $closed = false;
|
||||
|
||||
public function __construct(
|
||||
string $endpoint,
|
||||
array $opts,
|
||||
string $method,
|
||||
array $headers = []
|
||||
private string $method,
|
||||
array $headers = [],
|
||||
) {
|
||||
$this->channel = new Channel($endpoint, $opts);
|
||||
$this->method = $method;
|
||||
$this->metadata = $this->formatMetadata(array_change_key_case($headers));
|
||||
}
|
||||
|
||||
public function contentType(): string
|
||||
{
|
||||
return 'application/x-protobuf';
|
||||
return ContentTypes::PROTOBUF;
|
||||
}
|
||||
|
||||
public function send(string $payload, ?CancellationInterface $cancellation = null): FutureInterface
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use function in_array;
|
|||
use InvalidArgumentException;
|
||||
use function json_encode;
|
||||
use OpenTelemetry\API\Behavior\LogsMessagesTrait;
|
||||
use OpenTelemetry\Contrib\Otlp\ContentTypes;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
|
||||
use OpenTelemetry\SDK\Common\Export\TransportInterface;
|
||||
use function parse_url;
|
||||
|
|
@ -31,7 +32,7 @@ final class GrpcTransportFactory implements TransportFactoryInterface
|
|||
*/
|
||||
public function create(
|
||||
string $endpoint,
|
||||
string $contentType = 'application/x-protobuf',
|
||||
string $contentType = ContentTypes::PROTOBUF,
|
||||
array $headers = [],
|
||||
$compression = null,
|
||||
float $timeout = 10.,
|
||||
|
|
@ -39,15 +40,15 @@ final class GrpcTransportFactory implements TransportFactoryInterface
|
|||
int $maxRetries = 3,
|
||||
?string $cacert = null,
|
||||
?string $cert = null,
|
||||
?string $key = null
|
||||
?string $key = null,
|
||||
): TransportInterface {
|
||||
$parts = parse_url($endpoint);
|
||||
if (!isset($parts['scheme'], $parts['host'], $parts['path'])) {
|
||||
throw new InvalidArgumentException('Endpoint has to contain scheme, host and path');
|
||||
}
|
||||
/** @phpstan-ignore-next-line */
|
||||
if ($contentType !== 'application/x-protobuf') {
|
||||
throw new InvalidArgumentException(sprintf('Unsupported content type "%s", grpc transport supports only application/x-protobuf', $contentType));
|
||||
if ($contentType !== ContentTypes::PROTOBUF) {
|
||||
throw new InvalidArgumentException(sprintf('Unsupported content type "%s", grpc transport supports only %s', $contentType, ContentTypes::PROTOBUF));
|
||||
}
|
||||
|
||||
$scheme = $parts['scheme'];
|
||||
|
|
@ -86,7 +87,7 @@ final class GrpcTransportFactory implements TransportFactoryInterface
|
|||
$compression,
|
||||
float $timeout,
|
||||
int $maxRetries,
|
||||
int $retryDelay
|
||||
int $retryDelay,
|
||||
): array {
|
||||
$opts = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"ext-grpc": "*",
|
||||
"grpc/grpc": "*",
|
||||
"open-telemetry/sdk": "^1.0"
|
||||
|
|
|
|||
|
|
@ -20,20 +20,17 @@ use Throwable;
|
|||
class LogsExporter implements LogRecordExporterInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private TransportInterface $transport;
|
||||
private ProtobufSerializer $serializer;
|
||||
|
||||
/**
|
||||
* @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
|
||||
*/
|
||||
public function __construct(TransportInterface $transport)
|
||||
public function __construct(private TransportInterface $transport)
|
||||
{
|
||||
if (!class_exists('\Google\Protobuf\Api')) {
|
||||
throw new RuntimeException('No protobuf implementation found (ext-protobuf or google/protobuf)');
|
||||
}
|
||||
$this->transport = $transport;
|
||||
$this->serializer = ProtobufSerializer::forTransport($transport);
|
||||
$this->serializer = ProtobufSerializer::forTransport($this->transport);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ class LogsExporterFactory implements LogRecordExporterFactoryInterface
|
|||
{
|
||||
private const DEFAULT_COMPRESSION = 'none';
|
||||
|
||||
private ?TransportFactoryInterface $transportFactory;
|
||||
|
||||
public function __construct(?TransportFactoryInterface $transportFactory = null)
|
||||
public function __construct(private ?TransportFactoryInterface $transportFactory = null)
|
||||
{
|
||||
$this->transportFactory = $transportFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -132,15 +132,11 @@ final class MetricConverter
|
|||
|
||||
private function convertTemporality($temporality): int
|
||||
{
|
||||
switch ($temporality) {
|
||||
case SDK\Metrics\Data\Temporality::DELTA:
|
||||
return AggregationTemporality::AGGREGATION_TEMPORALITY_DELTA;
|
||||
case SDK\Metrics\Data\Temporality::CUMULATIVE:
|
||||
return AggregationTemporality::AGGREGATION_TEMPORALITY_CUMULATIVE;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return AggregationTemporality::AGGREGATION_TEMPORALITY_UNSPECIFIED;
|
||||
return match ($temporality) {
|
||||
SDK\Metrics\Data\Temporality::DELTA => AggregationTemporality::AGGREGATION_TEMPORALITY_DELTA,
|
||||
SDK\Metrics\Data\Temporality::CUMULATIVE => AggregationTemporality::AGGREGATION_TEMPORALITY_CUMULATIVE,
|
||||
default => AggregationTemporality::AGGREGATION_TEMPORALITY_UNSPECIFIED,
|
||||
};
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,27 +22,19 @@ use Throwable;
|
|||
final class MetricExporter implements PushMetricExporterInterface, AggregationTemporalitySelectorInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private TransportInterface $transport;
|
||||
private ProtobufSerializer $serializer;
|
||||
/**
|
||||
* @var string|Temporality|null
|
||||
*/
|
||||
private $temporality;
|
||||
|
||||
/**
|
||||
* @param string|Temporality|null $temporality
|
||||
*
|
||||
* @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
|
||||
*/
|
||||
public function __construct(TransportInterface $transport, $temporality = null)
|
||||
{
|
||||
public function __construct(
|
||||
private TransportInterface $transport,
|
||||
private string|Temporality|null $temporality = null,
|
||||
) {
|
||||
if (!class_exists('\Google\Protobuf\Api')) {
|
||||
throw new RuntimeException('No protobuf implementation found (ext-protobuf or google/protobuf)');
|
||||
}
|
||||
$this->transport = $transport;
|
||||
$this->serializer = ProtobufSerializer::forTransport($transport);
|
||||
$this->temporality = $temporality;
|
||||
$this->serializer = ProtobufSerializer::forTransport($this->transport);
|
||||
}
|
||||
|
||||
public function temporality(MetricMetadataInterface $metric)
|
||||
|
|
|
|||
|
|
@ -19,11 +19,8 @@ class MetricExporterFactory implements MetricExporterFactoryInterface
|
|||
{
|
||||
private const DEFAULT_COMPRESSION = 'none';
|
||||
|
||||
private ?TransportFactoryInterface $transportFactory;
|
||||
|
||||
public function __construct(?TransportFactoryInterface $transportFactory = null)
|
||||
public function __construct(private ?TransportFactoryInterface $transportFactory = null)
|
||||
{
|
||||
$this->transportFactory = $transportFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,21 +63,18 @@ class MetricExporterFactory implements MetricExporterFactoryInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @todo return string|Temporality|null (php >= 8.0)
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private function getTemporality()
|
||||
private function getTemporality(): string|Temporality|null
|
||||
{
|
||||
$value = Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE);
|
||||
switch (strtolower($value)) {
|
||||
case 'cumulative':
|
||||
return Temporality::CUMULATIVE;
|
||||
case 'delta':
|
||||
return Temporality::DELTA;
|
||||
case 'lowmemory':
|
||||
return null;
|
||||
default:
|
||||
throw new \UnexpectedValueException('Unknown temporality: ' . $value);
|
||||
}
|
||||
|
||||
return match (strtolower($value)) {
|
||||
'cumulative' => Temporality::CUMULATIVE,
|
||||
'delta' => Temporality::DELTA,
|
||||
'lowmemory' => null,
|
||||
default => throw new \UnexpectedValueException('Unknown temporality: ' . $value),
|
||||
};
|
||||
}
|
||||
|
||||
private function getCompression(): string
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class OtlpHttpTransportFactory implements TransportFactoryInterface
|
|||
int $maxRetries = 3,
|
||||
?string $cacert = null,
|
||||
?string $cert = null,
|
||||
?string $key = null
|
||||
?string $key = null,
|
||||
): PsrTransport {
|
||||
if ($compression === self::DEFAULT_COMPRESSION) {
|
||||
$compression = null;
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace OpenTelemetry\Contrib\Otlp;
|
||||
|
||||
use AssertionError;
|
||||
use function base64_decode;
|
||||
use function bin2hex;
|
||||
use Exception;
|
||||
use function get_class;
|
||||
use Google\Protobuf\Descriptor;
|
||||
use Google\Protobuf\DescriptorPool;
|
||||
use Google\Protobuf\FieldDescriptor;
|
||||
|
|
@ -28,25 +26,17 @@ use function ucwords;
|
|||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @psalm-type SUPPORTED_CONTENT_TYPES = self::PROTOBUF|self::JSON|self::NDJSON
|
||||
* @psalm-type SUPPORTED_CONTENT_TYPES = ContentTypes::PROTOBUF|ContentTypes::JSON|ContentTypes::NDJSON
|
||||
*/
|
||||
final class ProtobufSerializer
|
||||
{
|
||||
private const PROTOBUF = 'application/x-protobuf';
|
||||
private const JSON = 'application/json';
|
||||
private const NDJSON = 'application/x-ndjson';
|
||||
|
||||
private string $contentType;
|
||||
|
||||
private function __construct(string $contentType)
|
||||
private function __construct(private string $contentType)
|
||||
{
|
||||
$this->contentType = $contentType;
|
||||
}
|
||||
|
||||
public static function getDefault(): ProtobufSerializer
|
||||
{
|
||||
return new self(self::PROTOBUF);
|
||||
return new self(ContentTypes::PROTOBUF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -54,75 +44,51 @@ final class ProtobufSerializer
|
|||
*/
|
||||
public static function forTransport(TransportInterface $transport): ProtobufSerializer
|
||||
{
|
||||
switch ($contentType = $transport->contentType()) {
|
||||
case self::PROTOBUF:
|
||||
case self::JSON:
|
||||
case self::NDJSON:
|
||||
return new self($contentType);
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('Not supported content type "%s"', $contentType));
|
||||
}
|
||||
return match ($contentType = $transport->contentType()) {
|
||||
ContentTypes::PROTOBUF, ContentTypes::JSON, ContentTypes::NDJSON => new self($contentType),
|
||||
default => throw new InvalidArgumentException(sprintf('Not supported content type "%s"', $contentType)),
|
||||
};
|
||||
}
|
||||
|
||||
public function serializeTraceId(string $traceId): string
|
||||
{
|
||||
switch ($this->contentType) {
|
||||
case self::PROTOBUF:
|
||||
return $traceId;
|
||||
case self::JSON:
|
||||
case self::NDJSON:
|
||||
return base64_decode(bin2hex($traceId));
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
// @phpstan-ignore-next-line
|
||||
return match ($this->contentType) {
|
||||
ContentTypes::PROTOBUF => $traceId,
|
||||
ContentTypes::JSON, ContentTypes::NDJSON => base64_decode(bin2hex($traceId)),
|
||||
};
|
||||
}
|
||||
|
||||
public function serializeSpanId(string $spanId): string
|
||||
{
|
||||
switch ($this->contentType) {
|
||||
case self::PROTOBUF:
|
||||
return $spanId;
|
||||
case self::JSON:
|
||||
case self::NDJSON:
|
||||
return base64_decode(bin2hex($spanId));
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
// @phpstan-ignore-next-line
|
||||
return match ($this->contentType) {
|
||||
ContentTypes::PROTOBUF => $spanId,
|
||||
ContentTypes::JSON, ContentTypes::NDJSON => base64_decode(bin2hex($spanId)),
|
||||
};
|
||||
}
|
||||
|
||||
public function serialize(Message $message): string
|
||||
{
|
||||
switch ($this->contentType) {
|
||||
case self::PROTOBUF:
|
||||
return $message->serializeToString();
|
||||
case self::JSON:
|
||||
return self::postProcessJsonEnumValues($message, $message->serializeToJsonString());
|
||||
case self::NDJSON:
|
||||
return self::postProcessJsonEnumValues($message, $message->serializeToJsonString()) . "\n";
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
// @phpstan-ignore-next-line
|
||||
return match ($this->contentType) {
|
||||
ContentTypes::PROTOBUF => $message->serializeToString(),
|
||||
ContentTypes::JSON => self::postProcessJsonEnumValues($message, $message->serializeToJsonString()),
|
||||
ContentTypes::NDJSON => self::postProcessJsonEnumValues($message, $message->serializeToJsonString()) . "\n",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @phan-suppress PhanParamTooManyInternal (@see https://github.com/phan/phan/pull/4840)
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hydrate(Message $message, string $payload): void
|
||||
{
|
||||
switch ($this->contentType) {
|
||||
case self::PROTOBUF:
|
||||
$message->mergeFromString($payload);
|
||||
|
||||
break;
|
||||
case self::JSON:
|
||||
case self::NDJSON:
|
||||
// @phan-suppress-next-line PhanParamTooManyInternal
|
||||
$message->mergeFromJsonString($payload, true);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
// @phpstan-ignore-next-line
|
||||
match ($this->contentType) {
|
||||
ContentTypes::PROTOBUF => $message->mergeFromString($payload),
|
||||
ContentTypes::JSON, ContentTypes::NDJSON => $message->mergeFromJsonString($payload, true),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -137,7 +103,7 @@ final class ProtobufSerializer
|
|||
private static function postProcessJsonEnumValues(Message $message, string $payload): string
|
||||
{
|
||||
$pool = DescriptorPool::getGeneratedPool();
|
||||
$desc = $pool->getDescriptorByClassName(get_class($message));
|
||||
$desc = $pool->getDescriptorByClassName($message::class);
|
||||
if (!$desc instanceof Descriptor) {
|
||||
return $payload;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,15 +121,14 @@ final class SpanConverter
|
|||
|
||||
private function convertSpanKind(int $kind): int
|
||||
{
|
||||
switch ($kind) {
|
||||
case API\SpanKind::KIND_INTERNAL: return SpanKind::SPAN_KIND_INTERNAL;
|
||||
case API\SpanKind::KIND_CLIENT: return SpanKind::SPAN_KIND_CLIENT;
|
||||
case API\SpanKind::KIND_SERVER: return SpanKind::SPAN_KIND_SERVER;
|
||||
case API\SpanKind::KIND_PRODUCER: return SpanKind::SPAN_KIND_PRODUCER;
|
||||
case API\SpanKind::KIND_CONSUMER: return SpanKind::SPAN_KIND_CONSUMER;
|
||||
}
|
||||
|
||||
return SpanKind::SPAN_KIND_UNSPECIFIED;
|
||||
return match ($kind) {
|
||||
API\SpanKind::KIND_INTERNAL => SpanKind::SPAN_KIND_INTERNAL,
|
||||
API\SpanKind::KIND_CLIENT => SpanKind::SPAN_KIND_CLIENT,
|
||||
API\SpanKind::KIND_SERVER => SpanKind::SPAN_KIND_SERVER,
|
||||
API\SpanKind::KIND_PRODUCER => SpanKind::SPAN_KIND_PRODUCER,
|
||||
API\SpanKind::KIND_CONSUMER => SpanKind::SPAN_KIND_CONSUMER,
|
||||
default => SpanKind::SPAN_KIND_UNSPECIFIED,
|
||||
};
|
||||
}
|
||||
|
||||
private function convertStatusCode(string $status): int
|
||||
|
|
|
|||
|
|
@ -19,20 +19,17 @@ use Throwable;
|
|||
final class SpanExporter implements SpanExporterInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private TransportInterface $transport;
|
||||
private ProtobufSerializer $serializer;
|
||||
|
||||
/**
|
||||
* @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
|
||||
*/
|
||||
public function __construct(TransportInterface $transport)
|
||||
public function __construct(private TransportInterface $transport)
|
||||
{
|
||||
if (!class_exists('\Google\Protobuf\Api')) {
|
||||
throw new RuntimeException('No protobuf implementation found (ext-protobuf or google/protobuf)');
|
||||
}
|
||||
$this->transport = $transport;
|
||||
$this->serializer = ProtobufSerializer::forTransport($transport);
|
||||
$this->serializer = ProtobufSerializer::forTransport($this->transport);
|
||||
}
|
||||
|
||||
public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface
|
||||
|
|
|
|||
|
|
@ -19,13 +19,10 @@ class SpanExporterFactory implements SpanExporterFactoryInterface
|
|||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private ?TransportFactoryInterface $transportFactory;
|
||||
|
||||
private const DEFAULT_COMPRESSION = 'none';
|
||||
|
||||
public function __construct(?TransportFactoryInterface $transportFactory = null)
|
||||
public function __construct(private ?TransportFactoryInterface $transportFactory = null)
|
||||
{
|
||||
$this->transportFactory = $transportFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"php-http/discovery": "^1.14",
|
||||
"open-telemetry/gen-otlp-protobuf": "^1.1",
|
||||
"open-telemetry/api": "^1.0",
|
||||
|
|
|
|||
|
|
@ -23,13 +23,10 @@ class Exporter implements SpanExporterInterface
|
|||
use LogsMessagesTrait;
|
||||
use UsesSpanConverterTrait;
|
||||
|
||||
private TransportInterface $transport;
|
||||
|
||||
public function __construct(
|
||||
TransportInterface $transport,
|
||||
SpanConverterInterface $spanConverter = null
|
||||
private TransportInterface $transport,
|
||||
SpanConverterInterface $spanConverter = null,
|
||||
) {
|
||||
$this->transport = $transport;
|
||||
$this->setSpanConverter($spanConverter ?? new SpanConverter());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,20 +171,14 @@ class SpanConverter implements SpanConverterInterface
|
|||
|
||||
private static function toSpanKind(SpanDataInterface $span): ?string
|
||||
{
|
||||
switch ($span->getKind()) {
|
||||
case SpanKind::KIND_SERVER:
|
||||
return ZipkinSpanKind::SERVER;
|
||||
case SpanKind::KIND_CLIENT:
|
||||
return ZipkinSpanKind::CLIENT;
|
||||
case SpanKind::KIND_PRODUCER:
|
||||
return ZipkinSpanKind::PRODUCER;
|
||||
case SpanKind::KIND_CONSUMER:
|
||||
return ZipkinSpanKind::CONSUMER;
|
||||
case SpanKind::KIND_INTERNAL:
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return match ($span->getKind()) {
|
||||
SpanKind::KIND_SERVER => ZipkinSpanKind::SERVER,
|
||||
SpanKind::KIND_CLIENT => ZipkinSpanKind::CLIENT,
|
||||
SpanKind::KIND_PRODUCER => ZipkinSpanKind::PRODUCER,
|
||||
SpanKind::KIND_CONSUMER => ZipkinSpanKind::CONSUMER,
|
||||
SpanKind::KIND_INTERNAL => null,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
private static function toAnnotation(EventInterface $event): array
|
||||
|
|
@ -231,17 +225,15 @@ class SpanConverter implements SpanConverterInterface
|
|||
return null;
|
||||
}
|
||||
|
||||
switch ($key) {
|
||||
case SpanConverter::NET_PEER_IP_KEY:
|
||||
return SpanConverter::getRemoteEndpointDataFromIpAddressAndPort(
|
||||
$value,
|
||||
SpanConverter::getPortNumberFromSpanAttributes($span)
|
||||
);
|
||||
default:
|
||||
return [
|
||||
'serviceName' => $value,
|
||||
];
|
||||
}
|
||||
return match ($key) {
|
||||
SpanConverter::NET_PEER_IP_KEY => SpanConverter::getRemoteEndpointDataFromIpAddressAndPort(
|
||||
$value,
|
||||
SpanConverter::getPortNumberFromSpanAttributes($span)
|
||||
),
|
||||
default => [
|
||||
'serviceName' => $value,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
private static function findRemoteEndpointPreferredAttribute(SpanDataInterface $span): ?array
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"open-telemetry/api": "^1.0",
|
||||
"open-telemetry/sdk": "^1.0",
|
||||
"php-http/async-client-implementation": "^1.0",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"ext-json": "*",
|
||||
"open-telemetry/api": "^1.0",
|
||||
"open-telemetry/context": "^1.0",
|
||||
|
|
@ -23,7 +23,6 @@
|
|||
"psr/http-factory-implementation": "^1.0",
|
||||
"psr/log": "^1.1|^2.0|^3.0",
|
||||
"symfony/polyfill-mbstring": "^1.23",
|
||||
"symfony/polyfill-php80": "^1.26",
|
||||
"symfony/polyfill-php81": "^1.26",
|
||||
"symfony/polyfill-php82": "^1.26"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
|
|||
*/
|
||||
final class B3Propagator implements TextMapPropagatorInterface
|
||||
{
|
||||
private TextMapPropagatorInterface $propagator;
|
||||
|
||||
private function __construct(TextMapPropagatorInterface $propagator)
|
||||
private function __construct(private TextMapPropagatorInterface $propagator)
|
||||
{
|
||||
$this->propagator = $propagator;
|
||||
}
|
||||
|
||||
public static function getB3SingleHeaderInstance(): self
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"open-telemetry/api": "^1.0",
|
||||
"open-telemetry/context": "^1.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ final class CloudTraceFormatter
|
|||
|
||||
/**
|
||||
* Generate a SpanContext object from the Trace Context header
|
||||
*
|
||||
* @param string $header
|
||||
* @return SpanContextInterface
|
||||
*/
|
||||
public static function deserialize(string $header) : SpanContextInterface
|
||||
{
|
||||
|
|
@ -47,9 +44,6 @@ final class CloudTraceFormatter
|
|||
|
||||
/**
|
||||
* Convert a SpanContextInterface to header string
|
||||
*
|
||||
* @param SpanContextInterface $context
|
||||
* @return string
|
||||
*/
|
||||
public static function serialize(SpanContextInterface $context) : string
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,11 +46,8 @@ final class CloudTracePropagator implements TextMapPropagatorInterface
|
|||
self::XCLOUD,
|
||||
];
|
||||
|
||||
private bool $oneWay;
|
||||
|
||||
private function __construct(bool $oneWay)
|
||||
private function __construct(private bool $oneWay)
|
||||
{
|
||||
$this->oneWay = $oneWay;
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php": "^8.0",
|
||||
"open-telemetry/api": "^1.0",
|
||||
"open-telemetry/context": "^1.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class JaegerBaggagePropagator implements TextMapPropagatorInterface
|
|||
$baggageBuilder = Baggage::getBuilder();
|
||||
|
||||
foreach ($baggageKeys as $key) {
|
||||
if (strpos($key, self::UBER_BAGGAGE_HEADER_PREFIX) === 0) {
|
||||
if (str_starts_with($key, self::UBER_BAGGAGE_HEADER_PREFIX)) {
|
||||
$baggageKey = substr($key, strlen(self::UBER_BAGGAGE_HEADER_PREFIX));
|
||||
$value = $getter->get($carrier, $key) ?? '';
|
||||
$baggageBuilder->set($baggageKey, rawurldecode($value));
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ final class DependencyResolver implements DependencyResolverInterface
|
|||
public function __construct(
|
||||
?MessageFactoryResolverInterface $messageFactoryResolver = null,
|
||||
?PsrClientResolverInterface $psrClientResolver = null,
|
||||
?HttpPlugClientResolverInterface $httpPlugClientResolver = null
|
||||
?HttpPlugClientResolverInterface $httpPlugClientResolver = null,
|
||||
) {
|
||||
$this->messageFactoryResolver = $messageFactoryResolver ?? MessageFactoryResolver::create();
|
||||
$this->psrClientResolver = $psrClientResolver ?? PsrClientResolver::create();
|
||||
|
|
@ -36,7 +36,7 @@ final class DependencyResolver implements DependencyResolverInterface
|
|||
public static function create(
|
||||
?MessageFactoryResolverInterface $messageFactoryResolver = null,
|
||||
?PsrClientResolverInterface $psrClientResolver = null,
|
||||
?HttpPlugClientResolverInterface $httpPlugClientResolver = null
|
||||
?HttpPlugClientResolverInterface $httpPlugClientResolver = null,
|
||||
): self {
|
||||
return new self($messageFactoryResolver, $psrClientResolver, $httpPlugClientResolver);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,8 @@ use OpenTelemetry\SDK\Common\Http\HttpPlug\Client\ResolverInterface;
|
|||
|
||||
final class HttpPlugClientResolver implements ResolverInterface
|
||||
{
|
||||
private ?HttpAsyncClient $httpAsyncClient;
|
||||
|
||||
public function __construct(?HttpAsyncClient $httpAsyncClient = null)
|
||||
public function __construct(private ?HttpAsyncClient $httpAsyncClient = null)
|
||||
{
|
||||
$this->httpAsyncClient = $httpAsyncClient;
|
||||
}
|
||||
|
||||
public static function create(?HttpAsyncClient $httpAsyncClient = null): self
|
||||
|
|
|
|||
|
|
@ -15,27 +15,14 @@ use Psr\Http\Message\UriFactoryInterface;
|
|||
|
||||
final class MessageFactoryResolver implements FactoryResolverInterface
|
||||
{
|
||||
private ?RequestFactoryInterface $requestFactory;
|
||||
private ?ResponseFactoryInterface $responseFactory;
|
||||
private ?ServerRequestFactoryInterface $serverRequestFactory;
|
||||
private ?StreamFactoryInterface $streamFactory;
|
||||
private ?UploadedFileFactoryInterface $uploadedFileFactory;
|
||||
private ?UriFactoryInterface $uriFactory;
|
||||
|
||||
public function __construct(
|
||||
?RequestFactoryInterface $requestFactory = null,
|
||||
?ResponseFactoryInterface $responseFactory = null,
|
||||
?ServerRequestFactoryInterface $serverRequestFactory = null,
|
||||
?StreamFactoryInterface $streamFactory = null,
|
||||
?UploadedFileFactoryInterface $uploadedFileFactory = null,
|
||||
?UriFactoryInterface $uriFactory = null
|
||||
private ?RequestFactoryInterface $requestFactory = null,
|
||||
private ?ResponseFactoryInterface $responseFactory = null,
|
||||
private ?ServerRequestFactoryInterface $serverRequestFactory = null,
|
||||
private ?StreamFactoryInterface $streamFactory = null,
|
||||
private ?UploadedFileFactoryInterface $uploadedFileFactory = null,
|
||||
private ?UriFactoryInterface $uriFactory = null,
|
||||
) {
|
||||
$this->requestFactory = $requestFactory;
|
||||
$this->responseFactory = $responseFactory;
|
||||
$this->serverRequestFactory = $serverRequestFactory;
|
||||
$this->streamFactory = $streamFactory;
|
||||
$this->uploadedFileFactory = $uploadedFileFactory;
|
||||
$this->uriFactory = $uriFactory;
|
||||
}
|
||||
|
||||
public static function create(
|
||||
|
|
@ -44,7 +31,7 @@ final class MessageFactoryResolver implements FactoryResolverInterface
|
|||
?ServerRequestFactoryInterface $serverRequestFactory = null,
|
||||
?StreamFactoryInterface $streamFactory = null,
|
||||
?UploadedFileFactoryInterface $uploadedFileFactory = null,
|
||||
?UriFactoryInterface $uriFactory = null
|
||||
?UriFactoryInterface $uriFactory = null,
|
||||
): self {
|
||||
return new self(
|
||||
$requestFactory,
|
||||
|
|
|
|||
|
|
@ -10,11 +10,8 @@ use Psr\Http\Client\ClientInterface;
|
|||
|
||||
final class PsrClientResolver implements ResolverInterface
|
||||
{
|
||||
private ?ClientInterface $client;
|
||||
|
||||
public function __construct(?ClientInterface $client = null)
|
||||
public function __construct(private ?ClientInterface $client = null)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
public static function create(?ClientInterface $client = null): self
|
||||
|
|
|
|||
|
|
@ -10,16 +10,13 @@ use Traversable;
|
|||
|
||||
final class Attributes implements AttributesInterface, IteratorAggregate
|
||||
{
|
||||
private array $attributes;
|
||||
private int $droppedAttributesCount;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __construct(array $attributes, int $droppedAttributesCount)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
$this->droppedAttributesCount = $droppedAttributesCount;
|
||||
public function __construct(
|
||||
private array $attributes,
|
||||
private int $droppedAttributesCount,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function create(iterable $attributes): AttributesInterface
|
||||
|
|
|
|||
|
|
@ -17,24 +17,15 @@ use OpenTelemetry\API\Behavior\LogsMessagesTrait;
|
|||
final class AttributesBuilder implements AttributesBuilderInterface
|
||||
{
|
||||
use LogsMessagesTrait;
|
||||
|
||||
private array $attributes;
|
||||
private ?int $attributeCountLimit;
|
||||
private ?int $attributeValueLengthLimit;
|
||||
private int $droppedAttributesCount;
|
||||
private AttributeValidatorInterface $attributeValidator;
|
||||
|
||||
public function __construct(
|
||||
array $attributes,
|
||||
?int $attributeCountLimit,
|
||||
?int $attributeValueLengthLimit,
|
||||
int $droppedAttributesCount,
|
||||
?AttributeValidatorInterface $attributeValidator
|
||||
private array $attributes,
|
||||
private ?int $attributeCountLimit,
|
||||
private ?int $attributeValueLengthLimit,
|
||||
private int $droppedAttributesCount,
|
||||
?AttributeValidatorInterface $attributeValidator,
|
||||
) {
|
||||
$this->attributes = $attributes;
|
||||
$this->attributeCountLimit = $attributeCountLimit;
|
||||
$this->attributeValueLengthLimit = $attributeValueLengthLimit;
|
||||
$this->droppedAttributesCount = $droppedAttributesCount;
|
||||
$this->attributeValidator = $attributeValidator ?? new AttributeValidator();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,10 @@ namespace OpenTelemetry\SDK\Common\Attribute;
|
|||
*/
|
||||
final class AttributesFactory implements AttributesFactoryInterface
|
||||
{
|
||||
private ?int $attributeCountLimit;
|
||||
private ?int $attributeValueLengthLimit;
|
||||
|
||||
public function __construct(?int $attributeCountLimit = null, ?int $attributeValueLengthLimit = null)
|
||||
{
|
||||
$this->attributeCountLimit = $attributeCountLimit;
|
||||
$this->attributeValueLengthLimit = $attributeValueLengthLimit;
|
||||
public function __construct(
|
||||
private ?int $attributeCountLimit = null,
|
||||
private ?int $attributeValueLengthLimit = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function builder(iterable $attributes = [], ?AttributeValidatorInterface $attributeValidator = null): AttributesBuilderInterface
|
||||
|
|
|
|||
|
|
@ -11,17 +11,15 @@ use function in_array;
|
|||
*/
|
||||
final class FilteredAttributesBuilder implements AttributesBuilderInterface
|
||||
{
|
||||
private AttributesBuilderInterface $builder;
|
||||
private array $rejectedKeys;
|
||||
private int $rejected = 0;
|
||||
|
||||
/**
|
||||
* @param list<string> $rejectedKeys
|
||||
*/
|
||||
public function __construct(AttributesBuilderInterface $builder, array $rejectedKeys)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->rejectedKeys = $rejectedKeys;
|
||||
public function __construct(
|
||||
private AttributesBuilderInterface $builder,
|
||||
private array $rejectedKeys,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
|
|
|
|||
|
|
@ -9,16 +9,13 @@ namespace OpenTelemetry\SDK\Common\Attribute;
|
|||
*/
|
||||
final class FilteredAttributesFactory implements AttributesFactoryInterface
|
||||
{
|
||||
private AttributesFactoryInterface $factory;
|
||||
private array $rejectedKeys;
|
||||
|
||||
/**
|
||||
* @param list<string> $rejectedKeys
|
||||
*/
|
||||
public function __construct(AttributesFactoryInterface $factory, array $rejectedKeys)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
$this->rejectedKeys = $rejectedKeys;
|
||||
public function __construct(
|
||||
private AttributesFactoryInterface $factory,
|
||||
private array $rejectedKeys,
|
||||
) {
|
||||
}
|
||||
|
||||
public function builder(iterable $attributes = [], ?AttributeValidatorInterface $attributeValidator = null): AttributesBuilderInterface
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class Configuration
|
|||
|
||||
try {
|
||||
return BooleanParser::parse($resolved);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
} catch (InvalidArgumentException) {
|
||||
self::logWarning(sprintf('Invalid boolean value "%s" interpreted as "false" for %s', $resolved, $key));
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class MapParser
|
|||
|
||||
private static function validateKeyValuePair(string $pair)
|
||||
{
|
||||
if (strpos($pair, self::KEY_VALUE_SEPARATOR) === false) {
|
||||
if (!str_contains($pair, self::KEY_VALUE_SEPARATOR)) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Key-Value pair "%s" does not contain separator "%s"',
|
||||
$pair,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class Util
|
|||
public static function triggerMethodDeprecationNotice(
|
||||
string $methodName,
|
||||
string $alternativeMethodName = null,
|
||||
string $alternativeClassName = null
|
||||
string $alternativeClassName = null,
|
||||
): void {
|
||||
if (self::getErrorLevel() === self::E_NONE) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ namespace OpenTelemetry\SDK\Common\Exception;
|
|||
|
||||
use function basename;
|
||||
use function count;
|
||||
use function get_class;
|
||||
use function sprintf;
|
||||
use function str_repeat;
|
||||
|
||||
|
|
@ -77,8 +76,8 @@ final class StackTraceFormatter
|
|||
$n = count($frames);
|
||||
if ($enclosing) {
|
||||
for ($m = count($enclosing);
|
||||
$n && $m && $frames[$n - 1] === $enclosing[$m - 1];
|
||||
$n--, $m--) {
|
||||
$n && $m && $frames[$n - 1] === $enclosing[$m - 1];
|
||||
$n--, $m--) {
|
||||
}
|
||||
}
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
|
|
@ -110,7 +109,7 @@ final class StackTraceFormatter
|
|||
|
||||
private static function writeInlineHeader(string &$s, Throwable $e): void
|
||||
{
|
||||
$s .= self::formatName(get_class($e));
|
||||
$s .= self::formatName($e::class);
|
||||
if ($e->getMessage() !== '') {
|
||||
$s .= ': ';
|
||||
$s .= $e->getMessage();
|
||||
|
|
|
|||
|
|
@ -30,42 +30,22 @@ use function trim;
|
|||
*/
|
||||
final class PsrTransport implements TransportInterface
|
||||
{
|
||||
private ClientInterface $client;
|
||||
private RequestFactoryInterface $requestFactory;
|
||||
private StreamFactoryInterface $streamFactory;
|
||||
|
||||
private string $endpoint;
|
||||
private string $contentType;
|
||||
private array $headers;
|
||||
private array $compression;
|
||||
private int $retryDelay;
|
||||
private int $maxRetries;
|
||||
|
||||
private bool $closed = false;
|
||||
|
||||
/**
|
||||
* @psalm-param CONTENT_TYPE $contentType
|
||||
*/
|
||||
public function __construct(
|
||||
ClientInterface $client,
|
||||
RequestFactoryInterface $requestFactory,
|
||||
StreamFactoryInterface $streamFactory,
|
||||
string $endpoint,
|
||||
string $contentType,
|
||||
array $headers,
|
||||
array $compression,
|
||||
int $retryDelay,
|
||||
int $maxRetries
|
||||
private ClientInterface $client,
|
||||
private RequestFactoryInterface $requestFactory,
|
||||
private StreamFactoryInterface $streamFactory,
|
||||
private string $endpoint,
|
||||
private string $contentType,
|
||||
private array $headers,
|
||||
private array $compression,
|
||||
private int $retryDelay,
|
||||
private int $maxRetries,
|
||||
) {
|
||||
$this->client = $client;
|
||||
$this->requestFactory = $requestFactory;
|
||||
$this->streamFactory = $streamFactory;
|
||||
$this->endpoint = $endpoint;
|
||||
$this->contentType = $contentType;
|
||||
$this->headers = $headers;
|
||||
$this->compression = $compression;
|
||||
$this->retryDelay = $retryDelay;
|
||||
$this->maxRetries = $maxRetries;
|
||||
}
|
||||
|
||||
public function contentType(): string
|
||||
|
|
|
|||
|
|
@ -16,18 +16,11 @@ use Psr\Http\Message\StreamFactoryInterface;
|
|||
|
||||
final class PsrTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
private ClientInterface $client;
|
||||
private RequestFactoryInterface $requestFactory;
|
||||
private StreamFactoryInterface $streamFactory;
|
||||
|
||||
public function __construct(
|
||||
ClientInterface $client,
|
||||
RequestFactoryInterface $requestFactory,
|
||||
StreamFactoryInterface $streamFactory
|
||||
private ClientInterface $client,
|
||||
private RequestFactoryInterface $requestFactory,
|
||||
private StreamFactoryInterface $streamFactory,
|
||||
) {
|
||||
$this->client = $client;
|
||||
$this->requestFactory = $requestFactory;
|
||||
$this->streamFactory = $streamFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -43,7 +36,7 @@ final class PsrTransportFactory implements TransportFactoryInterface
|
|||
int $maxRetries = 3,
|
||||
?string $cacert = null,
|
||||
?string $cert = null,
|
||||
?string $key = null
|
||||
?string $key = null,
|
||||
): PsrTransport {
|
||||
if (!filter_var($endpoint, FILTER_VALIDATE_URL)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid endpoint url "%s"', $endpoint));
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ final class PsrUtils
|
|||
|
||||
try {
|
||||
$value = $encoder($value);
|
||||
} catch (Throwable $e) {
|
||||
} catch (Throwable) {
|
||||
unset($encodings[$i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ final class PsrUtils
|
|||
if (!$compression) {
|
||||
return [];
|
||||
}
|
||||
if (strpos($compression, ',') === false) {
|
||||
if (!str_contains($compression, ',')) {
|
||||
return [$compression];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,20 +28,14 @@ use Throwable;
|
|||
final class StreamTransport implements TransportInterface
|
||||
{
|
||||
/**
|
||||
* @var resource|null
|
||||
*/
|
||||
private $stream;
|
||||
private string $contentType;
|
||||
|
||||
/**
|
||||
* @param resource $stream
|
||||
* @param resource|null $stream
|
||||
*
|
||||
* @psalm-param CONTENT_TYPE $contentType
|
||||
*/
|
||||
public function __construct($stream, string $contentType)
|
||||
{
|
||||
$this->stream = $stream;
|
||||
$this->contentType = $contentType;
|
||||
public function __construct(
|
||||
private $stream,
|
||||
private string $contentType,
|
||||
) {
|
||||
}
|
||||
|
||||
public function contentType(): string
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue