diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index ab56e2006..8f1351eba 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['8.0', '8.1', '8.2', '8.3'] + php-version: ['8.1', '8.2', '8.3', '8.4'] # Sorted alphabetically to ease finding the desired run in the GitHub Workflow UI. project: [ 'Aws', @@ -55,46 +55,18 @@ jobs: 'Symfony', ] exclude: - - project: 'Instrumentation/IO' - php-version: 8.0 - project: 'Instrumentation/IO' php-version: 8.1 - - project: 'Instrumentation/Curl' - php-version: 7.4 - - project: 'Instrumentation/Curl' - php-version: 8.0 - project: 'Instrumentation/Curl' php-version: 8.1 - - project: 'Instrumentation/MySqli' - php-version: 7.4 - - project: 'Instrumentation/MySqli' - php-version: 8.0 - project: 'Instrumentation/MySqli' php-version: 8.1 - - project: 'Instrumentation/PDO' - php-version: 8.0 - project: 'Instrumentation/PDO' php-version: 8.1 - - project: 'Instrumentation/Psr3' - php-version: 8.0 - - project: 'Instrumentation/ExtAmqp' - php-version: 8.0 - project: 'Instrumentation/ExtAmqp' php-version: 8.1 - - project: 'Instrumentation/ExtRdKafka' - php-version: 7.4 - - project: 'Instrumentation/ExtRdKafka' - php-version: 8.0 - project: 'Instrumentation/ExtRdKafka' php-version: 8.1 - - project: 'Instrumentation/OpenAIPHP' - php-version: 8.0 - - project: 'Logs/Monolog' - php-version: 8.0 - - project: 'Sampler/RuleBased' - php-version: 8.0 - - project: 'Symfony' - php-version: 8.0 steps: - uses: actions/checkout@v4 @@ -130,7 +102,7 @@ jobs: - name: Check Style working-directory: src/${{ matrix.project }} - run: vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php -v --dry-run --stop-on-violation --using-cache=no -vvv + run: PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php -v --dry-run --stop-on-violation --using-cache=no -vvv - name: Run Phan working-directory: src/${{ matrix.project }} @@ -179,7 +151,7 @@ jobs: - name: Code Coverage uses: codecov/codecov-action@v4 # only generate coverage against the latest PHP version - if: ${{ matrix.php-version == '8.3' }} + if: ${{ matrix.php-version == '8.4' }} with: token: ${{ secrets.CODECOV_TOKEN }} directory: src/${{ matrix.project }} diff --git a/Makefile b/Makefile index de4792958..07706512b 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ packages-composer: ## Validate all composer packages bash: ## Bash shell $(DC_RUN_PHP) bash style: ## Run php-cs-fixer - $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --using-cache=no -vvv + $(DC_RUN_PHP) env XDEBUG_MODE=off PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --using-cache=no -vvv split: ## git-split dry run ${DOCKER_COMPOSE} -f docker/gitsplit/docker-compose.yaml --env-file ./.env up FORCE: diff --git a/composer.json b/composer.json index 7db6e192a..edee34038 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "ext-json": "*" }, "require-dev": { diff --git a/docker/Dockerfile b/docker/Dockerfile index ebfc9b258..ccfe5b5c7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -ARG PHP_VERSION=8.0 +ARG PHP_VERSION=8.1 FROM ghcr.io/open-telemetry/opentelemetry-php/opentelemetry-php-base:${PHP_VERSION} USER root diff --git a/src/Aws/composer.json b/src/Aws/composer.json index 930f4db76..de89c7459 100644 --- a/src/Aws/composer.json +++ b/src/Aws/composer.json @@ -13,7 +13,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "open-telemetry/api": "^1.0", "open-telemetry/sdk": "^1.0", "aws/aws-sdk-php": "^3.232" @@ -28,8 +28,8 @@ "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "~9", - "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.0" + "psalm/plugin-phpunit": "^0.19.2", + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Aws/src/AwsSdkInstrumentation.php b/src/Aws/src/AwsSdkInstrumentation.php index b1496b152..4c45582b5 100644 --- a/src/Aws/src/AwsSdkInstrumentation.php +++ b/src/Aws/src/AwsSdkInstrumentation.php @@ -78,6 +78,7 @@ public function getTracer(): TracerInterface return $this->tracerProvider->getTracer('io.opentelemetry.contrib.php'); } + /** @psalm-api */ public function instrumentClients($clientsArray) : void { $this->clients = $clientsArray; @@ -87,7 +88,7 @@ public function instrumentClients($clientsArray) : void public function activate(): bool { try { - $middleware = Middleware::tap(function ($cmd, $req) { + $middleware = Middleware::tap(function ($cmd, $_req) { $tracer = $this->getTracer(); $propagator = $this->getPropagator(); diff --git a/src/Aws/src/Ecs/Detector.php b/src/Aws/src/Ecs/Detector.php index 9ee846d6e..5b0826279 100644 --- a/src/Aws/src/Ecs/Detector.php +++ b/src/Aws/src/Ecs/Detector.php @@ -175,7 +175,7 @@ private function getMetadataEndpointV4Resource(): ResourceInfo $containerMetadata = json_decode($containerResponse->getBody()->getContents(), true); $taskMetadata = json_decode($taskResponse->getBody()->getContents(), true); - + $launchType = isset($taskMetadata['LaunchType']) ? strtolower($taskMetadata['LaunchType']) : null; $taskFamily = isset($taskMetadata['Family']) ? $taskMetadata['Family'] : null; $taskRevision = isset($taskMetadata['Revision']) ? $taskMetadata['Revision'] : null; @@ -208,7 +208,7 @@ private function getMetadataEndpointV4Resource(): ResourceInfo } $containerArn = isset($containerMetadata['ContainerARN']) ? $containerMetadata['ContainerARN'] : null; - + $logResource = ResourceInfoFactory::emptyResource(); if (isset($containerMetadata['LogOptions']) && isset($containerMetadata['LogDriver']) && $containerMetadata['LogDriver'] === 'awslogs') { $logOptions = $containerMetadata['LogOptions']; @@ -218,7 +218,7 @@ private function getMetadataEndpointV4Resource(): ResourceInfo $logsGroupArns = []; $logsStreamArns = []; if (isset($containerMetadata['ContainerARN']) && preg_match('/arn:aws:ecs:([^:]+):([^:]+):.*/', $containerMetadata['ContainerARN'], $matches)) { - [$arn, $awsRegion, $awsAccount] = $matches; + [$_arn, $awsRegion, $awsAccount] = $matches; $logsGroupArns = ['arn:aws:logs:' . $awsRegion . ':' . $awsAccount . ':log-group:' . $logsGroupName]; $logsStreamArns = ['arn:aws:logs:' . $awsRegion . ':' . $awsAccount . ':log-group:' . $logsGroupName . ':log-stream:' . $logsStreamName]; diff --git a/src/Aws/src/Eks/DataProvider.php b/src/Aws/src/Eks/DataProvider.php index eac0cbc26..e7da40cd4 100644 --- a/src/Aws/src/Eks/DataProvider.php +++ b/src/Aws/src/Eks/DataProvider.php @@ -28,7 +28,7 @@ public function getK8sHeader(): ?string return null; } - return 'Bearer' . file_get_contents($this->k8sTokenPath); + return 'Bearer' . (file_get_contents($this->k8sTokenPath) ?: ''); } // Check if there exists a k8s certification file @@ -43,6 +43,6 @@ public function getCgroupData(): ?array return null; } - return file($this->cGroupPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + return file($this->cGroupPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: null; } } diff --git a/src/Aws/src/Xray/IdGenerator.php b/src/Aws/src/Xray/IdGenerator.php index cb0ad39c1..fa5c853ab 100644 --- a/src/Aws/src/Xray/IdGenerator.php +++ b/src/Aws/src/Xray/IdGenerator.php @@ -1,4 +1,5 @@ handler = new SwooleContextHandler($storage); } - public function fork($id): void + public function fork(int|string $id): void { $this->handler->switchToActiveCoroutine(); $this->storage->fork($id); } - public function switch($id): void + public function switch(int|string $id): void { $this->handler->switchToActiveCoroutine(); $this->storage->switch($id); } - public function destroy($id): void + public function destroy(int|string $id): void { $this->handler->switchToActiveCoroutine(); diff --git a/src/Instrumentation/CakePHP/composer.json b/src/Instrumentation/CakePHP/composer.json index e559c368c..75ca45542 100644 --- a/src/Instrumentation/CakePHP/composer.json +++ b/src/Instrumentation/CakePHP/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "cakephp/cakephp": "^4 || ^5", "open-telemetry/api": "^1.0", @@ -23,10 +23,10 @@ "phpstan/phpstan-mockery": "^1.1.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5|^10.5", - "vimeo/psalm": "^5.24", + "vimeo/psalm": "6.4.0", "symfony/http-client": "^6 || ^7" }, "suggest": { @@ -54,4 +54,4 @@ "php-http/discovery": true } } -} \ No newline at end of file +} diff --git a/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php b/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php index a1f77f186..b4af29c26 100644 --- a/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php +++ b/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php @@ -6,6 +6,7 @@ use Cake\Console\TestSuite\ConsoleIntegrationTestTrait; +/** @psalm-suppress UnusedClass */ class CommandTest extends TestCase { use ConsoleIntegrationTestTrait; diff --git a/src/Instrumentation/CodeIgniter/composer.json b/src/Instrumentation/CodeIgniter/composer.json index 8053360b6..2628401c2 100644 --- a/src/Instrumentation/CodeIgniter/composer.json +++ b/src/Instrumentation/CodeIgniter/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "codeigniter4/framework": "^4.3", "open-telemetry/api": "^1.0", @@ -22,9 +22,9 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php index 9345190e1..02519cec8 100644 --- a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php +++ b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php @@ -21,6 +21,7 @@ class CodeIgniterInstrumentation { public const NAME = 'codeigniter'; + /** @psalm-api */ public static function register(): void { $instrumentation = new CachedInstrumentation( @@ -34,12 +35,16 @@ public static function register(): void // properties, thus reflection is required to read them. $reflectedIgniter = new \ReflectionClass(CodeIgniter::class); $requestProperty = $reflectedIgniter->getProperty('request'); + /** @psalm-suppress UnusedMethodCall */ $requestProperty->setAccessible(true); $controllerProperty = $reflectedIgniter->getProperty('controller'); + /** @psalm-suppress UnusedMethodCall */ $controllerProperty->setAccessible(true); $controllerMethodProperty = $reflectedIgniter->getProperty('method'); + /** @psalm-suppress UnusedMethodCall */ $controllerMethodProperty->setAccessible(true); + /** @psalm-suppress UnusedFunctionCall */ hook( CodeIgniter::class, 'handleRequest', @@ -66,7 +71,7 @@ public static function register(): void ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno); $parent = Context::getCurrent(); - + if ($request) { $parent = Globals::propagator()->extract($request, RequestPropagationGetter::instance()); @@ -135,7 +140,7 @@ public static function register(): void $prop->inject($response, ResponsePropagationSetter::instance(), $scope->context()); } } - + $controller = $controllerProperty->getValue($igniter); $controllerClassName = CodeIgniterInstrumentation::getControllerClassName($controller); $controllerMethod = $controllerMethodProperty->getValue($igniter); @@ -169,7 +174,7 @@ protected static function getControllerClassName(mixed $controller): ?string protected static function normalizeRouteName(string $controllerClassName, string $controllerMethod): string { $lastSegment = strrchr($controllerClassName, '\\'); - + if ($lastSegment === false) { return $controllerClassName . '.' . $controllerMethod; } diff --git a/src/Instrumentation/CodeIgniter/src/ResponsePropagationSetter.php b/src/Instrumentation/CodeIgniter/src/ResponsePropagationSetter.php index a012c06c0..b494d03ac 100644 --- a/src/Instrumentation/CodeIgniter/src/ResponsePropagationSetter.php +++ b/src/Instrumentation/CodeIgniter/src/ResponsePropagationSetter.php @@ -20,7 +20,9 @@ public static function instance(): self return $instance ??= new self(); } - /** @psalm-suppress InvalidReturnType */ + /** @psalm-suppress InvalidReturnType + * @psalm-suppress PossiblyUnusedMethod + */ public function keys($carrier): array { assert($carrier instanceof MessageInterface); diff --git a/src/Instrumentation/Curl/composer.json b/src/Instrumentation/Curl/composer.json index 441f9f794..673832f20 100644 --- a/src/Instrumentation/Curl/composer.json +++ b/src/Instrumentation/Curl/composer.json @@ -28,10 +28,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/Curl/src/CurlInstrumentation.php b/src/Instrumentation/Curl/src/CurlInstrumentation.php index f18475355..7d0c3f78f 100644 --- a/src/Instrumentation/Curl/src/CurlInstrumentation.php +++ b/src/Instrumentation/Curl/src/CurlInstrumentation.php @@ -57,6 +57,7 @@ public static function register(): void if ($retVal instanceof CurlHandle) { $curlHandleToAttributes[$retVal] = new CurlHandleMetadata(); if (($fullUrl = $params[0] ?? null) !== null) { + /** @psalm-suppress PossiblyNullReference */ $curlHandleToAttributes[$retVal]->setAttribute(TraceAttributes::URL_FULL, CurlHandleMetadata::redactUrlString($fullUrl)); } } @@ -67,11 +68,12 @@ public static function register(): void null, 'curl_setopt', pre: null, - post: static function ($obj, array $params, mixed $retVal) use ($curlHandleToAttributes, &$curlSetOptInstrumentationSuppressed) { + post: static function ($_obj, array $params, mixed $retVal) use ($curlHandleToAttributes, &$curlSetOptInstrumentationSuppressed) { if ($retVal != true || $curlSetOptInstrumentationSuppressed) { return; } + /** @psalm-suppress PossiblyNullReference */ $curlHandleToAttributes[$params[0]]->updateFromCurlOption($params[1], $params[2]); } ); @@ -80,13 +82,11 @@ public static function register(): void null, 'curl_setopt_array', pre: null, - post: static function ($obj, array $params, mixed $retVal) use ($curlHandleToAttributes) { + post: static function ($_obj, array $params, mixed $retVal) use ($curlHandleToAttributes) { if ($retVal != true) { - if (curl_error($params[0])) { - foreach ($params[1] as $option => $value) { - if (!curl_setopt($params[0], $option, $value)) { - break; - } + foreach ($params[1] as $option => $value) { + if (!curl_setopt($params[0], $option, $value)) { + break; } } @@ -94,6 +94,7 @@ public static function register(): void } foreach ($params[1] as $option => $value) { + /** @psalm-suppress PossiblyNullReference */ $curlHandleToAttributes[$params[0]]->updateFromCurlOption($option, $value); } } @@ -116,6 +117,9 @@ public static function register(): void pre: null, post: static function ($obj, array $params, mixed $retVal) use ($curlHandleToAttributes) { if ($params[0] instanceof CurlHandle && $retVal instanceof CurlHandle) { + /** @psalm-suppress PossiblyNullReference + * @psalm-suppress PossiblyNullArgument + */ $curlHandleToAttributes[$retVal] = $curlHandleToAttributes[$params[0]]; } } @@ -140,11 +144,13 @@ public static function register(): void return; } + /** @psalm-suppress PossiblyNullReference */ $spanName = $curlHandleToAttributes[$params[0]]->getAttributes()[TraceAttributes::HTTP_REQUEST_METHOD] ?? 'curl_exec'; $propagator = Globals::propagator(); $parent = Context::getCurrent(); + /** @psalm-suppress PossiblyNullReference */ $builder = $instrumentation->tracer() ->spanBuilder($spanName) ->setParent($parent) @@ -162,15 +168,19 @@ public static function register(): void $curlSetOptInstrumentationSuppressed = true; + /** @psalm-suppress PossiblyNullReference */ $headers = $curlHandleToAttributes[$params[0]]->getRequestHeadersToSend(); if ($headers) { curl_setopt($params[0], CURLOPT_HTTPHEADER, $headers); } if (self::isResponseHeadersCapturingEnabled()) { + /** @psalm-suppress PossiblyNullReference */ curl_setopt($params[0], CURLOPT_HEADERFUNCTION, $curlHandleToAttributes[$params[0]]->getResponseHeaderCaptureFunction()); } + if (self::isRequestHeadersCapturingEnabled()) { + /** @psalm-suppress PossiblyNullReference */ if (!$curlHandleToAttributes[$params[0]]->isVerboseEnabled()) { // we let go of captuing request headers because CURLINFO_HEADER_OUT is disabling CURLOPT_VERBOSE curl_setopt($params[0], CURLINFO_HEADER_OUT, true); } @@ -204,6 +214,7 @@ public static function register(): void $span->setAttribute(TraceAttributes::ERROR_TYPE, 'cURL error (' . $errno . ')'); } + /** @psalm-suppress PossiblyNullReference */ $capturedHeaders = $curlHandleToAttributes[$params[0]]->getCapturedResponseHeaders(); foreach (self::getResponseHeadersToCapture() as $headerToCapture) { if (($value = $capturedHeaders[strtolower($headerToCapture)] ?? null) != null) { @@ -233,6 +244,7 @@ public static function register(): void pre: null, post: static function ($obj, array $params, mixed $retVal) use ($curlMultiToHandle) { if ($retVal == 0) { + /** @psalm-suppress PossiblyNullArrayAssignment */ $curlMultiToHandle[$params[0]]['handles'][$params[1]] = ['finished' => false, 'span' => null]; } } @@ -245,6 +257,9 @@ public static function register(): void pre: null, post: static function ($obj, array $params, mixed $retVal) use ($curlMultiToHandle) { if ($retVal == 0) { + /** @psalm-suppress PossiblyNullArrayAccess + * @psalm-suppress PossiblyNullReference + */ $curlMultiToHandle[$params[0]]['handles']->offsetUnset($params[1]); } } @@ -271,14 +286,19 @@ public static function register(): void if ($retVal == CURLM_OK) { $mHandle = &$curlMultiToHandle[$params[0]]; + /** @psalm-suppress PossiblyNullArrayAccess */ $handles = &$mHandle['handles']; + /** @psalm-suppress PossiblyNullArrayAccess */ if (!$mHandle['started']) { // on first call to curl_multi_exec we're marking it's a transfer start for all curl handles attached to multi handle $parent = Context::getCurrent(); $propagator = Globals::propagator(); + /** @psalm-suppress PossiblyNullIterator */ foreach ($handles as $cHandle => &$metadata) { + /** @psalm-suppress PossiblyNullReference */ $spanName = $curlHandleToAttributes[$cHandle]->getAttributes()[TraceAttributes::HTTP_REQUEST_METHOD] ?? 'curl_multi_exec'; + /** @psalm-suppress PossiblyNullReference */ $builder = $instrumentation->tracer() ->spanBuilder($spanName) ->setParent($parent) @@ -304,8 +324,6 @@ public static function register(): void if (!$curlHandleToAttributes[$cHandle]->isVerboseEnabled()) { // we let go of captuing request headers because CURLINFO_HEADER_OUT is disabling CURLOPT_VERBOSE curl_setopt($cHandle, CURLINFO_HEADER_OUT, true); } - //TODO log? - } $curlSetOptInstrumentationSuppressed = false; @@ -317,10 +335,11 @@ public static function register(): void $isRunning = $params[1]; if ($isRunning == 0) { // it is the last call to multi - in case curl_multi_info_read might not not be called anytime, we need to finish all spans left + /** @psalm-suppress PossiblyNullIterator */ foreach ($handles as $cHandle => &$metadata) { if ($metadata['finished'] == false) { $metadata['finished'] = true; - self::finishMultiSpan(CURLE_OK, $cHandle, $curlHandleToAttributes, $metadata['span']->get()); // there is no way to get information if it was OK or not without calling curl_multi_info_read + self::finishMultiSpan(CURLE_OK, $cHandle, $curlHandleToAttributes, $metadata['span']?->get()); // there is no way to get information if it was OK or not without calling curl_multi_info_read } } @@ -344,25 +363,35 @@ public static function register(): void if ($retVal != false) { if ($retVal['msg'] == CURLMSG_DONE) { + /** @psalm-suppress PossiblyNullArrayAccess + * @psalm-suppress PossiblyNullReference + */ if (!$mHandle['handles']->offsetExists($retVal['handle'])) { return; } + /** @psalm-suppress PossiblyNullArrayAccess */ $currentHandle = &$mHandle['handles'][$retVal['handle']]; + /** @psalm-suppress PossiblyNullArrayAccess */ if ($currentHandle['finished']) { return; } + /** @psalm-suppress PossiblyNullArrayAccess */ $currentHandle['finished'] = true; - self::finishMultiSpan($retVal['result'], $retVal['handle'], $curlHandleToAttributes, $currentHandle['span']->get()); + self::finishMultiSpan($retVal['result'], $retVal['handle'], $curlHandleToAttributes, $currentHandle['span']?->get()); } } } ); } - private static function finishMultiSpan(int $curlResult, CurlHandle $curlHandle, $curlHandleToAttributes, SpanInterface $span) + private static function finishMultiSpan(int $curlResult, CurlHandle $curlHandle, $curlHandleToAttributes, ?SpanInterface $span) { + if ($span === null) { + return; + } + $scope = Context::storage()->scope(); $scope?->detach(); diff --git a/src/Instrumentation/Curl/tests/Integration/CurlInstrumentationTest.php b/src/Instrumentation/Curl/tests/Integration/CurlInstrumentationTest.php index 90f928be2..8bf573cbf 100644 --- a/src/Instrumentation/Curl/tests/Integration/CurlInstrumentationTest.php +++ b/src/Instrumentation/Curl/tests/Integration/CurlInstrumentationTest.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Tests\Instrumentation\Curl\Integration; use ArrayObject; +use CurlHandle; use OpenTelemetry\API\Instrumentation\Configurator; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; use OpenTelemetry\Context\ScopeInterface; @@ -44,6 +45,7 @@ public function tearDown(): void public function test_curl_reset(): void { $ch = curl_init(); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, 'http://gugugaga.gugugaga/'); curl_reset($ch); @@ -59,6 +61,7 @@ public function test_curl_reset(): void public function test_curl_setopt(): void { $ch = curl_init(); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, 'http://gugugaga.gugugaga/'); curl_exec($ch); @@ -74,6 +77,7 @@ public function test_curl_setopt(): void public function test_curl_setopt_overrides_url(): void { $ch = curl_init('http://example.com'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, 'http://gugugaga.gugugaga/'); curl_exec($ch); @@ -86,6 +90,7 @@ public function test_curl_setopt_overrides_url(): void public function test_curl_setopt_array(): void { $ch = curl_init(); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt_array($ch, [CURLOPT_POST => 1, CURLOPT_URL => 'http://gugugaga.gugugaga/']); curl_exec($ch); @@ -99,6 +104,7 @@ public function test_curl_setopt_array(): void public function test_curl_setopt_array_partial_success(): void { $ch = curl_init(); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt_array($ch, [CURLOPT_POST => 1, CURLOPT_URL => 'http://gugugaga.gugugaga/', CURLOPT_SSLVERSION => 1000 ]); curl_exec($ch); @@ -112,9 +118,11 @@ public function test_curl_setopt_array_partial_success(): void public function test_curl_copy_handle(): void { $ch = curl_init('http://gugugaga.gugugaga/'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_POST, 1); $ch_copy = curl_copy_handle($ch); + $this->assertInstanceOf(CurlHandle::class, $ch_copy); curl_close($ch); curl_exec($ch_copy); @@ -129,6 +137,7 @@ public function test_curl_copy_handle(): void public function test_curl_exec_with_error(): void { $ch = curl_init('http://gugugaga.gugugaga/'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_exec($ch); $this->assertCount(1, $this->storage); @@ -144,6 +153,7 @@ public function test_curl_exec_with_error(): void public function test_curl_exec(): void { $ch = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_exec($ch); @@ -163,6 +173,7 @@ public function test_curl_exec_calls_user_defined_headerfunc(): void putenv('OTEL_PHP_INSTRUMENTATION_HTTP_REQUEST_HEADERS=host'); $ch = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $func = function (\CurlHandle $ch, string $headerLine) { @@ -194,6 +205,7 @@ public function test_curl_exec_headers_capturing(): void putenv('OTEL_PHP_INSTRUMENTATION_HTTP_REQUEST_HEADERS=host'); $ch = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_exec($ch); @@ -212,6 +224,7 @@ public function test_curl_exec_sets_traceparent(): void putenv('OTEL_PHP_INSTRUMENTATION_HTTP_REQUEST_HEADERS=traceparent'); $ch = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_exec($ch); diff --git a/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php b/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php index 13f825659..f2fd90e87 100644 --- a/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php +++ b/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Tests\Instrumentation\Curl\Integration; use ArrayObject; +use CurlHandle; use OpenTelemetry\API\Instrumentation\Configurator; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; use OpenTelemetry\Context\ScopeInterface; @@ -45,9 +46,11 @@ public function test_curl_multi() { $mh = curl_multi_init(); $ch1 = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch1); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); $ch2 = curl_copy_handle($ch1); + $this->assertInstanceOf(CurlHandle::class, $ch2); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); @@ -78,6 +81,7 @@ public function test_curl_multi_error() { $mh = curl_multi_init(); $ch1 = curl_init('unknown://scheme.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch1); curl_multi_add_handle($mh, $ch1); @@ -103,6 +107,8 @@ public function test_curl_multi_remove_handle() $mh = curl_multi_init(); $ch1 = curl_init('unknown://scheme.com/'); $ch2 = curl_init('other://scheme.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch1); + $this->assertInstanceOf(CurlHandle::class, $ch2); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); @@ -131,6 +137,7 @@ public function test_curl_multi_exec_calls_user_defined_headerfunc(): void $mh = curl_multi_init(); $ch1 = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch1); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); $func = function (\CurlHandle $ch, string $headerLine) { @@ -148,6 +155,7 @@ public function test_curl_multi_exec_calls_user_defined_headerfunc(): void curl_setopt($ch1, CURLOPT_HEADERFUNCTION, $mockedFunc); $ch2 = curl_copy_handle($ch1); + $this->assertInstanceOf(CurlHandle::class, $ch2); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); @@ -181,9 +189,11 @@ public function test_curl_multi_exec_headers_capturing(): void $mh = curl_multi_init(); $ch1 = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch1); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); $ch2 = curl_copy_handle($ch1); + $this->assertInstanceOf(CurlHandle::class, $ch2); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); @@ -218,9 +228,11 @@ public function test_curl_multi_exec_sets_traceparent(): void $mh = curl_multi_init(); $ch1 = curl_init('http://example.com/'); + $this->assertInstanceOf(CurlHandle::class, $ch1); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); $ch2 = curl_copy_handle($ch1); + $this->assertInstanceOf(CurlHandle::class, $ch2); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); diff --git a/src/Instrumentation/ExtAmqp/composer.json b/src/Instrumentation/ExtAmqp/composer.json index e1e20dd24..d50ecb503 100644 --- a/src/Instrumentation/ExtAmqp/composer.json +++ b/src/Instrumentation/ExtAmqp/composer.json @@ -21,10 +21,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php b/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php index d6fd972ad..b929c767d 100644 --- a/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php +++ b/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php @@ -22,6 +22,7 @@ * This uses SemConv 1.24, until messaging SemConv becomes stable. * @see https://opentelemetry.io/docs/specs/semconv/messaging/rabbitmq/ * @phan-file-suppress PhanDeprecatedClassConstant + * @psalm-suppress UnusedClass */ final class ExtAmqpInstrumentation { @@ -35,6 +36,7 @@ public static function register(): void 'https://opentelemetry.io/schemas/1.24.0', ); + /** @psalm-suppress UnusedFunctionCall */ hook( AMQPExchange::class, 'publish', @@ -54,10 +56,10 @@ public static function register(): void ->spanBuilder(sprintf('%s%s', $exchange->getName() != '' ? $exchange->getName() . ' ': '', $routingKey) . ' publish') ->setSpanKind(SpanKind::KIND_PRODUCER) // code - ->setAttribute(TraceAttributes::CODE_FUNCTION, $function) + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) ->setAttribute(TraceAttributes::CODE_NAMESPACE, $class) ->setAttribute(TraceAttributes::CODE_FILEPATH, $filename) - ->setAttribute(TraceAttributes::CODE_LINENO, $lineno) + ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno) // messaging ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, 'amqp') ->setAttribute(TraceAttributes::MESSAGING_OPERATION, 'publish') @@ -148,6 +150,7 @@ public static function register(): void protected static function createInteractionWithQueueSpan(CachedInstrumentation $instrumentation, $class, string $method) { + /** @psalm-suppress UnusedFunctionCall */ hook( $class, $method, @@ -167,10 +170,10 @@ protected static function createInteractionWithQueueSpan(CachedInstrumentation $ ->spanBuilder($queueName . ' ' . $method) ->setSpanKind(SpanKind::KIND_CLIENT) // code - ->setAttribute(TraceAttributes::CODE_FUNCTION, $function) + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) ->setAttribute(TraceAttributes::CODE_NAMESPACE, $class) ->setAttribute(TraceAttributes::CODE_FILEPATH, $filename) - ->setAttribute(TraceAttributes::CODE_LINENO, $lineno) + ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno) // messaging ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, 'amqp') ->setAttribute(TraceAttributes::MESSAGING_OPERATION, $method) diff --git a/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php b/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php index f92b70f14..4f2c46ffe 100644 --- a/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php +++ b/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php @@ -44,7 +44,7 @@ public function tearDown(): void public function test_rabbit_basic_publish_without_args_works(): void { - list($connection, $routing_key, $channel, $exchange, $queue) = $this->setUpQueue(); + list($connection, $routing_key, $_channel, $exchange, $queue) = $this->setUpQueue(); try { $exchange->publish('test', $routing_key); @@ -78,7 +78,7 @@ public function test_rabbit_basic_publish_without_args_works(): void */ public function test_rabbit_basic_publish(string $messageInteraction): void { - list($connection, $routing_key, $channel, $exchange, $queue) = $this->setUpQueue(); + list($connection, $routing_key, $_channel, $exchange, $queue) = $this->setUpQueue(); try { $exchange->publish('test', $routing_key, AMQP_NOPARAM, []); @@ -106,7 +106,6 @@ public function test_rabbit_basic_publish(string $messageInteraction): void $this->assertCount(2, $this->storage); - /** @var ImmutableSpan $publishSpan */ $interactionSpan = $this->storage[1]; $this->assertEquals(SpanKind::KIND_CLIENT, $interactionSpan->getKind()); $this->assertEquals($queue->getName() . ' ' . $messageInteraction, $interactionSpan->getName()); diff --git a/src/Instrumentation/ExtRdKafka/composer.json b/src/Instrumentation/ExtRdKafka/composer.json index 152f79261..13c2c6c22 100644 --- a/src/Instrumentation/ExtRdKafka/composer.json +++ b/src/Instrumentation/ExtRdKafka/composer.json @@ -23,10 +23,10 @@ "mockery/mockery": "^1.5", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php b/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php index c0360c731..981399ef5 100644 --- a/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php +++ b/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php @@ -9,6 +9,7 @@ use OpenTelemetry\API\Instrumentation\CachedInstrumentation; use OpenTelemetry\API\Trace\Span; use OpenTelemetry\API\Trace\SpanKind; +use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; @@ -22,6 +23,7 @@ use Throwable; +/** @psalm-suppress UnusedClass */ class ExtRdKafkaInstrumentation { public const NAME = 'ext_rdkafka'; @@ -44,6 +46,7 @@ public static function register(): void private static function addCommitHooks($functionName) { + /** @psalm-suppress UnusedFunctionCall */ hook( KafkaConsumer::class, $functionName, @@ -61,6 +64,7 @@ private static function addCommitHooks($functionName) private static function addProductionHooks($instrumentation) { + /** @psalm-suppress UnusedFunctionCall */ hook( ProducerTopic::class, 'producev', @@ -120,6 +124,10 @@ private static function addProductionHooks($instrumentation) $scope->detach(); $span = Span::fromContext($scope->context()); + if ($exception) { + $span->recordException($exception); + $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); + } $span->end(); return $returnValue; @@ -129,6 +137,7 @@ private static function addProductionHooks($instrumentation) private static function addConsumeHooks($instrumentation) { + /** @psalm-suppress UnusedFunctionCall */ hook( KafkaConsumer::class, 'consume', @@ -136,7 +145,7 @@ private static function addConsumeHooks($instrumentation) ?KafkaConsumer $exchange, array $params, ?Message $message, - ?Throwable $exception + ?Throwable $_exception ) use ($instrumentation) : void { // This is to ensure that there is data. Packages periodically poll this method in order to // determine if there is a message there. If there is not, we don't want to create a span. diff --git a/src/Instrumentation/Guzzle/composer.json b/src/Instrumentation/Guzzle/composer.json index a9edb66c9..095260c34 100644 --- a/src/Instrumentation/Guzzle/composer.json +++ b/src/Instrumentation/Guzzle/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -23,10 +23,10 @@ "phpstan/phpstan-mockery": "^1.1.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php index 8327f8f4f..62722e850 100644 --- a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php +++ b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php @@ -21,6 +21,7 @@ use function strtolower; use Throwable; +/** @psalm-suppress UnusedClass */ class GuzzleInstrumentation { /** @psalm-suppress ArgumentTypeCoercion */ @@ -34,6 +35,7 @@ public static function register(): void 'https://opentelemetry.io/schemas/1.30.0', ); + /** @psalm-suppress UnusedFunctionCall */ hook( Client::class, 'transfer', diff --git a/src/Instrumentation/Guzzle/tests/Integration/GuzzleInstrumentationTest.php b/src/Instrumentation/Guzzle/tests/Integration/GuzzleInstrumentationTest.php index 35b026aee..64fdc8ccc 100644 --- a/src/Instrumentation/Guzzle/tests/Integration/GuzzleInstrumentationTest.php +++ b/src/Instrumentation/Guzzle/tests/Integration/GuzzleInstrumentationTest.php @@ -139,7 +139,7 @@ public function test_concurrent_async(): void 'two' => $this->client->getAsync('www.example.com/two'), ]; $this->assertCount(0, $this->storage); - $responses = Utils::unwrap($promises); + $_responses = Utils::unwrap($promises); $this->assertCount(2, $this->storage); $spanOne = $this->storage->offsetGet(0); diff --git a/src/Instrumentation/HttpAsyncClient/composer.json b/src/Instrumentation/HttpAsyncClient/composer.json index 4635cf403..7222bc0be 100644 --- a/src/Instrumentation/HttpAsyncClient/composer.json +++ b/src/Instrumentation/HttpAsyncClient/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -32,10 +32,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "config": { "allow-plugins": { diff --git a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php index 516eb4345..4ffb61614 100644 --- a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php +++ b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php @@ -18,6 +18,7 @@ use Psr\Http\Message\ResponseInterface; use Throwable; +/** @psalm-suppress UnusedClass */ class HttpAsyncClientInstrumentation { public const NAME = 'http-async-client'; @@ -29,6 +30,7 @@ public static function register(): void schemaUrl: 'https://opentelemetry.io/schemas/1.30.0', ); + /** @psalm-suppress UnusedFunctionCall */ hook( HttpAsyncClient::class, 'sendAsyncRequest', diff --git a/src/Instrumentation/IO/composer.json b/src/Instrumentation/IO/composer.json index 54182a66a..493b260d2 100644 --- a/src/Instrumentation/IO/composer.json +++ b/src/Instrumentation/IO/composer.json @@ -20,10 +20,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/IO/src/IOInstrumentation.php b/src/Instrumentation/IO/src/IOInstrumentation.php index 106ae7f9e..ca39c7104 100644 --- a/src/Instrumentation/IO/src/IOInstrumentation.php +++ b/src/Instrumentation/IO/src/IOInstrumentation.php @@ -14,6 +14,7 @@ use OpenTelemetry\SemConv\Version; use Throwable; +/** @psalm-suppress UnusedClass */ class IOInstrumentation { public const NAME = 'io'; @@ -38,6 +39,7 @@ public static function register(): void /** * Simple generic hook function which starts and ends a minimal span + * @psalm-suppress UnusedFunctionCall */ private static function _hook(CachedInstrumentation $instrumentation, ?string $class, string $function, string $name): void { diff --git a/src/Instrumentation/IO/tests/Integration/IOInstrumentationTest.php b/src/Instrumentation/IO/tests/Integration/IOInstrumentationTest.php index 6cb241342..f9f49044e 100644 --- a/src/Instrumentation/IO/tests/Integration/IOInstrumentationTest.php +++ b/src/Instrumentation/IO/tests/Integration/IOInstrumentationTest.php @@ -5,6 +5,7 @@ namespace OpenTelemetry\Tests\Instrumentation\IO\tests\Integration; use ArrayObject; +use CurlHandle; use OpenTelemetry\API\Instrumentation\Configurator; use OpenTelemetry\Context\ScopeInterface; use OpenTelemetry\SDK\Trace\ImmutableSpan; @@ -41,6 +42,7 @@ public function tearDown(): void public function test_io_calls(): void { $resource = fopen('php://memory', 'r'); + $this->assertIsResource($resource); $this->assertCount(1, $this->storage); $this->span = $this->storage->offsetGet(0); $this->assertSame('fopen', $this->span->getName()); @@ -52,8 +54,8 @@ public function test_io_calls(): void $this->span = $this->storage->offsetGet(1); $this->assertSame('file_put_contents', $this->span->getName()); $this->assertSame('php://memory', $this->span->getAttributes()->get('code.params.filename')); - - $str = file_get_contents('php://memory'); + + file_get_contents('php://memory'); $this->assertCount(3, $this->storage); $this->span = $this->storage->offsetGet(2); $this->assertSame('file_get_contents', $this->span->getName()); @@ -70,6 +72,7 @@ public function test_io_calls(): void $this->assertSame('fread', $this->span->getName()); $ch = curl_init('foo'); + $this->assertInstanceOf(CurlHandle::class, $ch); $this->assertCount(6, $this->storage); $this->span = $this->storage->offsetGet(5); $this->assertSame('curl_init', $this->span->getName()); diff --git a/src/Instrumentation/Laravel/composer.json b/src/Instrumentation/Laravel/composer.json index bc5ba619f..ffbbb8d20 100644 --- a/src/Instrumentation/Laravel/composer.json +++ b/src/Instrumentation/Laravel/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-json": "*", "ext-opentelemetry": "*", "laravel/framework": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", @@ -27,9 +27,9 @@ "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^9.5", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "spatie/laravel-ignition": "*", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php index 171626c24..48b23d516 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php @@ -24,6 +24,7 @@ public function instrument(): void $this->hookExecute(); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookExecute(): bool { return hook( diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php index 70f23ef05..8afa2947a 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php @@ -32,6 +32,7 @@ public function instrument(): void } } + /** @psalm-suppress UnusedReturnValue */ private function hookHandle(): bool { return hook( diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php index 0a0bc54ed..2b5975140 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php @@ -33,6 +33,7 @@ public function instrument(): void $this->hookHandle(); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookHandle(): bool { return hook( diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php index 197c05e1f..96ec455e1 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php @@ -31,6 +31,7 @@ public function instrument(): void $this->hookPushRaw(); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookBulk(): bool { return hook( @@ -67,6 +68,7 @@ protected function hookBulk(): bool ); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookLater(): bool { return hook( @@ -110,12 +112,13 @@ protected function hookLater(): bool ); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookPushRaw(): bool { return hook( QueueContract::class, 'pushRaw', - pre: function (QueueContract $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) { + pre: function (QueueContract $queue, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) { /** @phan-suppress-next-line PhanParamTooFewUnpack */ $attributes = $this->buildMessageAttributes($queue, ...$params); diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php index 54aa70d80..794ce0f21 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php @@ -24,10 +24,11 @@ class Application implements LaravelHook public function instrument(): void { + /** @psalm-suppress UnusedFunctionCall */ hook( FoundationalApplication::class, '__construct', - post: function (FoundationalApplication $application, array $params, mixed $returnValue, ?Throwable $exception) { + post: function (FoundationalApplication $application, array $_params, mixed $_returnValue, ?Throwable $_exception) { $this->registerWatchers($application, new CacheWatcher()); $this->registerWatchers($application, new ClientRequestWatcher($this->instrumentation)); $this->registerWatchers($application, new ExceptionWatcher()); diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php index 190113d85..873f63b8b 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php @@ -18,15 +18,16 @@ class ServeCommand implements LaravelHook public function instrument(): void { + /** @psalm-suppress UnusedFunctionCall */ hook( FoundationServeCommand::class, 'handle', - pre: static function (FoundationServeCommand $serveCommand, array $params, string $class, string $function, ?string $filename, ?int $lineno) { + pre: static function (FoundationServeCommand $_serveCommand, array $_params, string $_class, string $_function, ?string $_filename, ?int $_lineno) { if (!property_exists(FoundationServeCommand::class, 'passthroughVariables')) { return; } - foreach ($_ENV as $key => $value) { + foreach ($_ENV as $key => $_value) { if (str_starts_with($key, 'OTEL_') && !in_array($key, FoundationServeCommand::$passthroughVariables)) { FoundationServeCommand::$passthroughVariables[] = $key; } diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php index 011d0efdb..766179f39 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php @@ -50,7 +50,7 @@ private function contextualMessageSystemAttributes( }; } - private function beanstalkContextualAttributes(BeanstalkdQueue $queue, array $payload, ?string $queueName = null, array $options = [], mixed ...$params): array + private function beanstalkContextualAttributes(BeanstalkdQueue $queue, array $_payload, ?string $queueName = null, array $_options = [], mixed ...$_params): array { return [ TraceAttributes::MESSAGING_SYSTEM => 'beanstalk', @@ -58,7 +58,7 @@ private function beanstalkContextualAttributes(BeanstalkdQueue $queue, array $pa ]; } - private function redisContextualAttributes(RedisQueue $queue, array $payload, ?string $queueName = null, array $options = [], mixed ...$params): array + private function redisContextualAttributes(RedisQueue $queue, array $_payload, ?string $queueName = null, array $_options = [], mixed ...$_params): array { return [ TraceAttributes::MESSAGING_SYSTEM => 'redis', @@ -66,7 +66,7 @@ private function redisContextualAttributes(RedisQueue $queue, array $payload, ?s ]; } - private function awsSqsContextualAttributes(SqsQueue $queue, array $payload, ?string $queueName = null, array $options = [], mixed ...$params): array + private function awsSqsContextualAttributes(SqsQueue $queue, array $_payload, ?string $queueName = null, array $_options = [], mixed ...$_params): array { return [ TraceAttributes::MESSAGING_SYSTEM => TraceAttributeValues::MESSAGING_SYSTEM_AWS_SQS, diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php index b1a0c7aa3..c4a21f590 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php @@ -21,12 +21,13 @@ public function instrument(): void $this->hookAbstractQueueCreatePayloadArray(); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookAbstractQueueCreatePayloadArray(): bool { return hook( AbstractQueue::class, 'createPayloadArray', - post: function (AbstractQueue $queue, array $params, array $payload, ?Throwable $exception): array { + post: function (AbstractQueue $_queue, array $_params, array $payload, ?Throwable $_exception): array { TraceContextPropagator::getInstance()->inject($payload); return $payload; diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php index ed21dadba..2845f253d 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php @@ -25,6 +25,7 @@ public function instrument(): void $this->hookPush(); } + /** @psalm-suppress PossiblyUnusedReturnValue */ protected function hookPush(): bool { return hook( diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php index fb012cbae..783b67ac0 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php @@ -30,12 +30,13 @@ public function instrument(): void $this->hookWorkerGetNextJob(); } + /** @psalm-suppress UnusedReturnValue */ private function hookWorkerProcess(): bool { return hook( QueueWorker::class, 'process', - pre: function (QueueWorker $worker, array $params, string $class, string $function, ?string $filename, ?int $lineno) { + pre: function (QueueWorker $worker, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) { $connectionName = $params[0]; /** @var Job $job */ $job = $params[1]; @@ -82,12 +83,13 @@ private function hookWorkerProcess(): bool ); } + /** @psalm-suppress UnusedReturnValue */ private function hookWorkerGetNextJob(): bool { return hook( QueueWorker::class, 'getNextJob', - pre: function (QueueWorker $worker, array $params, string $class, string $function, ?string $filename, ?int $lineno) { + pre: function (QueueWorker $_worker, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) { /** @var \Illuminate\Contracts\Queue\Queue $connection */ $connection = $params[0]; $queue = $params[1]; @@ -109,7 +111,7 @@ private function hookWorkerGetNextJob(): bool return $params; }, - post: function (QueueWorker $worker, array $params, ?Job $job, ?Throwable $exception) { + post: function (QueueWorker $_worker, array $params, ?Job $job, ?Throwable $exception) { $scope = Context::storage()->scope(); if (!$scope) { return; diff --git a/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php b/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php index 83b8f0808..e36284ad8 100644 --- a/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php +++ b/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php @@ -8,6 +8,7 @@ interface LaravelHook { + /** @psalm-suppress PossiblyUnusedReturnValue */ public static function hook(CachedInstrumentation $instrumentation): LaravelHook; public function instrument(): void; diff --git a/src/Instrumentation/Laravel/src/Hooks/LaravelHookTrait.php b/src/Instrumentation/Laravel/src/Hooks/LaravelHookTrait.php index 1bbdc9709..eeb39403c 100644 --- a/src/Instrumentation/Laravel/src/Hooks/LaravelHookTrait.php +++ b/src/Instrumentation/Laravel/src/Hooks/LaravelHookTrait.php @@ -17,6 +17,7 @@ protected function __construct( abstract public function instrument(): void; + /** @psalm-suppress PossiblyUnusedReturnValue */ public static function hook(CachedInstrumentation $instrumentation): LaravelHook { /** @psalm-suppress RedundantPropertyInitializationCheck */ diff --git a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php index 2af06f418..df543246e 100644 --- a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php +++ b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php @@ -11,6 +11,7 @@ class LaravelInstrumentation { public const NAME = 'laravel'; + /** @psalm-suppress PossiblyUnusedMethod */ public static function register(): void { $instrumentation = new CachedInstrumentation( diff --git a/src/Instrumentation/Laravel/src/Watchers/CacheWatcher.php b/src/Instrumentation/Laravel/src/Watchers/CacheWatcher.php index 59e1fb717..9a3e88507 100644 --- a/src/Instrumentation/Laravel/src/Watchers/CacheWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/CacheWatcher.php @@ -27,6 +27,7 @@ public function register(Application $app): void $app['events']->listen(KeyForgotten::class, [$this, 'recordCacheForget']); } + /** @psalm-suppress PossiblyUnusedMethod */ public function recordCacheHit(CacheHit $event): void { $this->addEvent('cache hit', [ @@ -35,6 +36,7 @@ public function recordCacheHit(CacheHit $event): void ]); } + /** @psalm-suppress PossiblyUnusedMethod */ public function recordCacheMiss(CacheMissed $event): void { $this->addEvent('cache miss', [ @@ -44,6 +46,7 @@ public function recordCacheMiss(CacheMissed $event): void } /** * @psalm-suppress UndefinedPropertyFetch + * @psalm-suppress PossiblyUnusedMethod * @suppress PhanUndeclaredProperty */ public function recordCacheSet(KeyWritten $event): void @@ -67,6 +70,7 @@ public function recordCacheSet(KeyWritten $event): void ]); } + /** @psalm-suppress PossiblyUnusedMethod */ public function recordCacheForget(KeyForgotten $event): void { $this->addEvent('cache forget', [ diff --git a/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php b/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php index cc6b3d535..3cf025dd4 100644 --- a/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php @@ -42,11 +42,12 @@ public function register(Application $app): void /** * @psalm-suppress ArgumentTypeCoercion + * @psalm-suppress PossiblyUnusedMethod * @suppress PhanEmptyFQSENInCallable,PhanUndeclaredFunctionInCallable */ public function recordRequest(RequestSending $request): void { - $parsedUrl = collect(parse_url($request->request->url())); + $parsedUrl = collect(parse_url($request->request->url()) ?: []); $processedUrl = $parsedUrl->get('scheme', 'http') . '://' . $parsedUrl->get('host') . $parsedUrl->get('path', ''); if ($parsedUrl->has('query')) { @@ -66,6 +67,7 @@ public function recordRequest(RequestSending $request): void $this->spans[$this->createRequestComparisonHash($request->request)] = $span; } + /** @psalm-suppress PossiblyUnusedMethod */ public function recordConnectionFailed(ConnectionFailed $request): void { $requestHash = $this->createRequestComparisonHash($request->request); @@ -81,6 +83,7 @@ public function recordConnectionFailed(ConnectionFailed $request): void unset($this->spans[$requestHash]); } + /** @psalm-suppress PossiblyUnusedMethod */ public function recordResponse(ResponseReceived $request): void { $requestHash = $this->createRequestComparisonHash($request->request); diff --git a/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php b/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php index 176575a26..d9d10a51f 100644 --- a/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php @@ -21,7 +21,8 @@ public function register(Application $app): void } /** * Record an exception. - */ + * @psalm-suppress PossiblyUnusedMethod + */ public function recordException(MessageLogged $log): void { if (! isset($log->context['exception']) || diff --git a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php index bdeb64588..65b5751ac 100644 --- a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php @@ -9,7 +9,7 @@ use Illuminate\Log\LogManager; use OpenTelemetry\API\Instrumentation\CachedInstrumentation; use OpenTelemetry\API\Logs\LogRecord; -use OpenTelemetry\API\Logs\Map\Psr3; +use OpenTelemetry\API\Logs\Severity; use TypeError; class LogWatcher extends Watcher @@ -33,6 +33,7 @@ public function register(Application $app): void /** * Record a log. * @phan-suppress PhanDeprecatedFunction + * @psalm-suppress PossiblyUnusedMethod */ public function recordLog(MessageLogged $log): void { @@ -59,7 +60,7 @@ public function recordLog(MessageLogged $log): void $record = (new LogRecord($log->message)) ->setSeverityText($log->level) - ->setSeverityNumber(Psr3::severityNumber($log->level)) + ->setSeverityNumber(Severity::fromPsr3($log->level)) ->setAttributes($attributes); $logger->emit($record); diff --git a/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php b/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php index cfd438096..9cb5ac7b6 100644 --- a/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php @@ -27,8 +27,8 @@ public function register(Application $app): void /** * Record a query. + * @psalm-suppress PossiblyUnusedMethod */ - /** @psalm-suppress UndefinedThisPropertyFetch */ public function recordQuery(QueryExecuted $query): void { $nowInNs = (int) (microtime(true) * 1E9); diff --git a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php index 31de0a2b5..db8e84992 100644 --- a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php @@ -37,8 +37,8 @@ public function register(Application $app): void /** * Record a Redis command. + * @psalm-suppress PossiblyUnusedMethod */ - /** @psalm-suppress UndefinedThisPropertyFetch */ public function recordRedisCommand(CommandExecuted $event): void { $nowInNs = (int) (microtime(true) * 1E9); diff --git a/src/Instrumentation/Laravel/tests/Fixtures/Jobs/DummyJob.php b/src/Instrumentation/Laravel/tests/Fixtures/Jobs/DummyJob.php index cf14062cf..69bb546a5 100644 --- a/src/Instrumentation/Laravel/tests/Fixtures/Jobs/DummyJob.php +++ b/src/Instrumentation/Laravel/tests/Fixtures/Jobs/DummyJob.php @@ -12,11 +12,13 @@ class DummyJob implements ShouldQueue { use Queueable; + /** @psalm-suppress PossiblyUnusedMethod */ public function __construct( private string $name, ) { } + /** @psalm-suppress PossiblyUnusedMethod */ public function handle(LoggerInterface $logger): void { $logger->info("Task: {$this->name}"); diff --git a/src/Instrumentation/Laravel/tests/Integration/Console/CommandTest.php b/src/Instrumentation/Laravel/tests/Integration/Console/CommandTest.php index 1d46fbcac..ce63a8e13 100644 --- a/src/Instrumentation/Laravel/tests/Integration/Console/CommandTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/Console/CommandTest.php @@ -8,6 +8,7 @@ use Illuminate\Contracts\Console\Kernel; use OpenTelemetry\Tests\Contrib\Instrumentation\Laravel\Integration\TestCase; +/** @psalm-suppress UnusedClass */ class CommandTest extends TestCase { public function test_command_tracing(): void diff --git a/src/Instrumentation/Laravel/tests/Integration/Http/ClientTest.php b/src/Instrumentation/Laravel/tests/Integration/Http/ClientTest.php index 1fd528a64..39dd678a5 100644 --- a/src/Instrumentation/Laravel/tests/Integration/Http/ClientTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/Http/ClientTest.php @@ -13,6 +13,7 @@ use OpenTelemetry\SemConv\TraceAttributes; use OpenTelemetry\Tests\Contrib\Instrumentation\Laravel\Integration\TestCase; +/** @psalm-suppress UnusedClass */ class ClientTest extends TestCase { public function test_it_records_requests(): void diff --git a/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php b/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php index 8f9bd1355..1471b7f4c 100644 --- a/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Log; use OpenTelemetry\SemConv\TraceAttributes; +/** @psalm-suppress UnusedClass */ class LaravelInstrumentationTest extends TestCase { public function test_request_response(): void diff --git a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php index 63991dccf..43a4996b9 100644 --- a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php @@ -19,6 +19,7 @@ use OpenTelemetry\Tests\Contrib\Instrumentation\Laravel\Integration\TestCase; use Psr\Log\LoggerInterface; +/** @psalm-suppress UnusedClass */ class QueueTest extends TestCase { private Queue $queue; diff --git a/src/Instrumentation/Laravel/tests/Integration/TestCase.php b/src/Instrumentation/Laravel/tests/Integration/TestCase.php index 56c1abbbf..2ed778d86 100644 --- a/src/Instrumentation/Laravel/tests/Integration/TestCase.php +++ b/src/Instrumentation/Laravel/tests/Integration/TestCase.php @@ -18,6 +18,7 @@ use OpenTelemetry\SDK\Trace\TracerProvider; use Orchestra\Testbench\TestCase as BaseTestCase; +/** @psalm-suppress UnusedClass */ abstract class TestCase extends BaseTestCase { protected ScopeInterface $scope; diff --git a/src/Instrumentation/MongoDB/composer.json b/src/Instrumentation/MongoDB/composer.json index 24810b7ce..29d175ebe 100644 --- a/src/Instrumentation/MongoDB/composer.json +++ b/src/Instrumentation/MongoDB/composer.json @@ -7,7 +7,7 @@ "readme": "./README.md", "license": "Apache-2.0", "require": { - "php": ">=8.0", + "php": ">=8.1", "ext-mongodb": "^1.13", "ext-json": "*", "mongodb/mongodb": "^1.15", @@ -19,10 +19,10 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php b/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php index 8add3f2c0..83da4a8a8 100644 --- a/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php +++ b/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php @@ -68,8 +68,9 @@ public function commandStarted(CommandStartedEvent $event): void $collectionName = MongoDBCollectionExtractor::extract($command); $databaseName = $event->getDatabaseName(); $commandName = $event->getCommandName(); - /** @phpstan-ignore-next-line */ - if (version_compare(phpversion('mongodb'), '1.20.0', '>=')) { + + $version = phpversion('mongodb'); + if ($version !== false && version_compare($version, '1.20.0', '>=')) { $host = $event->getHost(); $port = $event->getPort(); } else { diff --git a/src/Instrumentation/MySqli/composer.json b/src/Instrumentation/MySqli/composer.json index e55f750ab..608678aed 100644 --- a/src/Instrumentation/MySqli/composer.json +++ b/src/Instrumentation/MySqli/composer.json @@ -33,10 +33,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/MySqli/src/MySqliTracker.php b/src/Instrumentation/MySqli/src/MySqliTracker.php index 5e67162a9..230937a9e 100644 --- a/src/Instrumentation/MySqli/src/MySqliTracker.php +++ b/src/Instrumentation/MySqli/src/MySqliTracker.php @@ -167,6 +167,9 @@ private function splitQueries(string $sql) { // Normalize line endings to \n $sql = preg_replace("/\r\n|\n\r|\r/", "\n", $sql); + if ($sql === null) { + return []; + } $queries = []; $buffer = ''; @@ -176,6 +179,10 @@ private function splitQueries(string $sql) $singleQuotes = 0; $doubleQuotes = 0; + if (empty($tokens)) { + return []; + } + foreach ($tokens as $token) { if ($token === '') { continue; diff --git a/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php b/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php index 7cf024ca2..cb7ed78eb 100644 --- a/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php +++ b/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php @@ -310,6 +310,9 @@ public function test_mysqli_query_procedural(): void } + /** + * @requires PHP >= 8.2 + */ public function test_mysqli_execute_query_objective(): void { mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); @@ -368,12 +371,17 @@ public function test_mysqli_execute_query_objective(): void $this->assertDatabaseAttributesForAllSpans($offset); } + /** + * @requires PHP >= 8.2 + */ public function test_mysqli_execute_query_procedural(): void { mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $mysqli = mysqli_connect($this->mysqlHost, $this->user, $this->passwd, $this->database); + $this->assertInstanceOf(mysqli::class, $mysqli); + $offset = 0; $this->assertSame('mysqli_connect', $this->storage->offsetGet($offset)->getName()); @@ -542,6 +550,7 @@ public function test_mysqli_multi_query_procedural(): void mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $mysqli = mysqli_connect($this->mysqlHost, $this->user, $this->passwd, $this->database); + $this->assertInstanceOf(mysqli::class, $mysqli); $offset = 0; $this->assertSame('mysqli_connect', $this->storage->offsetGet($offset)->getName()); @@ -709,12 +718,14 @@ public function test_mysqli_prepare_procedural(): void mysqli_report(MYSQLI_REPORT_ERROR); $mysqli = new mysqli($this->mysqlHost, $this->user, $this->passwd, $this->database); + $this->assertInstanceOf(mysqli::class, $mysqli); $offset = 0; $this->assertSame('mysqli::__construct', $this->storage->offsetGet($offset)->getName()); try { $stmt = mysqli_prepare($mysqli, 'SELECT * FROM otel_db.users'); + $this->assertInstanceOf(mysqli_stmt::class, $stmt); $offset++; $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); @@ -833,6 +844,7 @@ public function test_mysqli_transaction_rollback_procedural(): void mysqli_report(MYSQLI_REPORT_ERROR); $mysqli = mysqli_connect($this->mysqlHost, $this->user, $this->passwd, $this->database); + $this->assertInstanceOf(mysqli::class, $mysqli); $offset = 0; $this->assertSame('mysqli_connect', $this->storage->offsetGet($offset)->getName()); @@ -865,6 +877,8 @@ public function test_mysqli_transaction_rollback_procedural(): void $language_code = 'FR'; $native_speakers = 'Unknown'; $stmt = mysqli_prepare($mysqli, 'INSERT INTO language(Code, Speakers) VALUES (?,?)'); + $this->assertInstanceOf(mysqli_stmt::class, $stmt); + $offset++; $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ @@ -976,6 +990,7 @@ public function test_mysqli_transaction_commit_procedural(): void mysqli_report(MYSQLI_REPORT_ERROR); $mysqli = mysqli_connect($this->mysqlHost, $this->user, $this->passwd, $this->database); + $this->assertInstanceOf(mysqli::class, $mysqli); $offset = 0; $this->assertSame('mysqli_connect', $this->storage->offsetGet($offset)->getName()); @@ -1008,6 +1023,8 @@ public function test_mysqli_transaction_commit_procedural(): void $language_code = 'FR'; $native_speakers = 66000002; $stmt = mysqli_prepare($mysqli, 'INSERT INTO language(Code, Speakers) VALUES (?,?)'); + $this->assertInstanceOf(mysqli_stmt::class, $stmt); + $offset++; $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ diff --git a/src/Instrumentation/OpenAIPHP/composer.json b/src/Instrumentation/OpenAIPHP/composer.json index 00c03b2f4..a1346d231 100644 --- a/src/Instrumentation/OpenAIPHP/composer.json +++ b/src/Instrumentation/OpenAIPHP/composer.json @@ -22,11 +22,11 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "nyholm/psr7": "^1", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php b/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php index 0379d92df..2218b6aaf 100644 --- a/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php +++ b/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php @@ -75,6 +75,7 @@ public static function register(): void private static function hookApi(CachedInstrumentation $instrumentation, $class, string $resource, string $operation) { + /** @psalm-suppress UnusedFunctionCall */ hook( $class, $operation, diff --git a/src/Instrumentation/OpenAIPHP/tests/Integration/OpenAIPHPInstrumentationTest.php b/src/Instrumentation/OpenAIPHP/tests/Integration/OpenAIPHPInstrumentationTest.php index 560762f85..47b0cad9e 100644 --- a/src/Instrumentation/OpenAIPHP/tests/Integration/OpenAIPHPInstrumentationTest.php +++ b/src/Instrumentation/OpenAIPHP/tests/Integration/OpenAIPHPInstrumentationTest.php @@ -52,7 +52,7 @@ public function tearDown(): void private function loadFile(string $file): string { - return file_get_contents(__DIR__ . '/../resources/' . $file . '.json'); + return file_get_contents(__DIR__ . '/../resources/' . $file . '.json') ?: ''; } private function createClient(string $fixture): Client @@ -99,7 +99,7 @@ public function dataProvider(): array public function test_openai_operation($api, $operation, $args, $fixture, array $spanAttributes): void { $client = $this->createClient($fixture); - $response = $client->$api()->$operation(...$args); + $client->$api()->$operation(...$args); $this->assertCount(1, $this->storage); @@ -127,7 +127,7 @@ public function test_will_set_status() ->make(); try { - $response = $client->completions()->create([ + $client->completions()->create([ 'model' => 'gpt-3.5-turbo-instruct', 'prompt' => 'Say this is a test', 'max_tokens' => 7, diff --git a/src/Instrumentation/PDO/composer.json b/src/Instrumentation/PDO/composer.json index 58ff8420f..934292abe 100644 --- a/src/Instrumentation/PDO/composer.json +++ b/src/Instrumentation/PDO/composer.json @@ -25,10 +25,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/PDO/src/PDOInstrumentation.php b/src/Instrumentation/PDO/src/PDOInstrumentation.php index b0676a0ad..c27a338a5 100644 --- a/src/Instrumentation/PDO/src/PDOInstrumentation.php +++ b/src/Instrumentation/PDO/src/PDOInstrumentation.php @@ -10,8 +10,8 @@ use OpenTelemetry\API\Trace\SpanKind; use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\Context; -use OpenTelemetry\SDK\Common\Configuration\Configuration; use function OpenTelemetry\Instrumentation\hook; +use OpenTelemetry\SDK\Common\Configuration\Configuration; use OpenTelemetry\SemConv\TraceAttributes; use OpenTelemetry\SemConv\Version; use PDO; @@ -203,7 +203,8 @@ public static function register(): void pre: static function (PDOStatement $statement, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($pdoTracker, $instrumentation) { $attributes = $pdoTracker->trackedAttributesForStatement($statement); if (self::isDistributeStatementToLinkedSpansEnabled()) { - $attributes[TraceAttributes::DB_STATEMENT] = $statement->queryString; + /** @psalm-suppress InvalidArrayAssignment */ + $attributes[TraceAttributes::DB_QUERY_TEXT] = $statement->queryString; } /** @psalm-suppress ArgumentTypeCoercion */ $builder = self::makeBuilder($instrumentation, 'PDOStatement::fetchAll', $function, $class, $filename, $lineno) @@ -228,9 +229,10 @@ public static function register(): void $attributes = $pdoTracker->trackedAttributesForStatement($statement); if (self::isDistributeStatementToLinkedSpansEnabled()) { - $attributes[TraceAttributes::DB_STATEMENT] = $statement->queryString; + /** @psalm-suppress InvalidArrayAssignment */ + $attributes[TraceAttributes::DB_QUERY_TEXT] = $statement->queryString; } - + /** @psalm-suppress ArgumentTypeCoercion */ $builder = self::makeBuilder($instrumentation, 'PDOStatement::execute', $function, $class, $filename, $lineno) ->setSpanKind(SpanKind::KIND_CLIENT) @@ -285,6 +287,6 @@ private static function isDistributeStatementToLinkedSpansEnabled(): bool return Configuration::getBoolean('OTEL_PHP_INSTRUMENTATION_PDO_DISTRIBUTE_STATEMENT_TO_LINKED_SPANS', false); } - return get_cfg_var('otel.instrumentation.pdo.distribute_statement_to_linked_spans'); + return filter_var(get_cfg_var('otel.instrumentation.pdo.distribute_statement_to_linked_spans'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) ?? false; } } diff --git a/src/Instrumentation/PDO/src/PDOTracker.php b/src/Instrumentation/PDO/src/PDOTracker.php index 96761f3c4..a7d1d2ed4 100644 --- a/src/Instrumentation/PDO/src/PDOTracker.php +++ b/src/Instrumentation/PDO/src/PDOTracker.php @@ -17,7 +17,7 @@ final class PDOTracker { /** - * @var WeakMap> + * @var WeakMap> */ private WeakMap $pdoToAttributesMap; /** @@ -48,24 +48,24 @@ public function trackStatement(PDOStatement $statement, PDO $pdo, SpanContextInt * Maps a statement back to the connection attributes. * * @param PDOStatement $statement - * @return iterable + * @return array */ - public function trackedAttributesForStatement(PDOStatement $statement): iterable + public function trackedAttributesForStatement(PDOStatement $statement): array { $pdo = ($this->statementMapToPdoMap[$statement] ?? null)?->get(); if ($pdo === null) { return []; } - return $this->pdoToAttributesMap[$pdo] ?? []; + return $this->pdoToAttributesMap[$pdo] ?: []; } /** * @param PDO $pdo * @param string $dsn - * @return iterable + * @return array */ - public function trackPdoAttributes(PDO $pdo, string $dsn): iterable + public function trackPdoAttributes(PDO $pdo, string $dsn): array { $attributes = self::extractAttributesFromDSN($dsn); @@ -87,15 +87,19 @@ public function trackPdoAttributes(PDO $pdo, string $dsn): iterable /** * @param PDO $pdo - * @return iterable + * @return array */ - public function trackedAttributesForPdo(PDO $pdo): iterable + public function trackedAttributesForPdo(PDO $pdo): array { - return $this->pdoToAttributesMap[$pdo] ?? []; + return $this->pdoToAttributesMap[$pdo] ?: []; } public function getSpanForPreparedStatement(PDOStatement $statement): ?SpanContextInterface { + if (!$this->preparedStatementToSpanMap->offsetExists($statement)) { + return null; + } + return ($this->preparedStatementToSpanMap[$statement] ?? null)?->get(); } @@ -123,9 +127,9 @@ private static function mapDriverNameToAttribute(?string $driverName): string * Extracts attributes from a DSN string * * @param string $dsn - * @return iterable + * @return array */ - private static function extractAttributesFromDSN(string $dsn): iterable + private static function extractAttributesFromDSN(string $dsn): array { $attributes = []; if (str_starts_with($dsn, 'sqlite::memory:')) { diff --git a/src/Instrumentation/Psr14/composer.json b/src/Instrumentation/Psr14/composer.json index 84002adbe..42f65335e 100644 --- a/src/Instrumentation/Psr14/composer.json +++ b/src/Instrumentation/Psr14/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -36,10 +36,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "config": { "allow-plugins": { diff --git a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php index e15459942..4db4cc39b 100644 --- a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php +++ b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php @@ -17,6 +17,7 @@ /** * @psalm-suppress ArgumentTypeCoercion + * @psalm-suppress UnusedClass */ class Psr14Instrumentation { @@ -32,6 +33,7 @@ public static function register(): void /** * Create a span for each PSR-14 event that is dispatched. + * @psalm-suppress UnusedFunctionCall */ hook( EventDispatcherInterface::class, diff --git a/src/Instrumentation/Psr14/tests/Fixture/SampleEventClass.php b/src/Instrumentation/Psr14/tests/Fixture/SampleEventClass.php index 974462177..6257b7619 100644 --- a/src/Instrumentation/Psr14/tests/Fixture/SampleEventClass.php +++ b/src/Instrumentation/Psr14/tests/Fixture/SampleEventClass.php @@ -9,11 +9,11 @@ */ final class SampleEventClass { + /** @psalm-suppress PossiblyUnusedProperty */ public string $item; - public function __construct( - string $item = 'test', - ) { + public function __construct(string $item = 'test') + { $this->item = $item; } } diff --git a/src/Instrumentation/Psr15/composer.json b/src/Instrumentation/Psr15/composer.json index b9e8710f2..a3ed9dd8a 100644 --- a/src/Instrumentation/Psr15/composer.json +++ b/src/Instrumentation/Psr15/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -30,9 +30,9 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" } } diff --git a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php index 025966fde..ddad4f4b9 100644 --- a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php +++ b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php @@ -21,6 +21,7 @@ /** * @psalm-suppress ArgumentTypeCoercion + * @psalm-suppress UnusedClass */ class Psr15Instrumentation { @@ -37,6 +38,7 @@ public static function register(): void /** * Create a span for each psr-15 middleware that is executed. */ + /** @psalm-suppress UnusedFunctionCall */ hook( MiddlewareInterface::class, 'process', @@ -69,6 +71,7 @@ public static function register(): void * Create a span to wrap RequestHandlerInterface::handle. The first execution is assumed to be the root span, which * is stored as a request attribute which may be accessed by later hooks. */ + /** @psalm-suppress UnusedFunctionCall */ hook( RequestHandlerInterface::class, 'handle', diff --git a/src/Instrumentation/Psr16/composer.json b/src/Instrumentation/Psr16/composer.json index 5e75650ff..a642260be 100644 --- a/src/Instrumentation/Psr16/composer.json +++ b/src/Instrumentation/Psr16/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -25,7 +25,7 @@ "psalm/plugin-phpunit": "^0", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php index f2f55f3b1..b16baf093 100644 --- a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php +++ b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php @@ -33,7 +33,7 @@ public static function register(): void $pre = static function (CacheInterface $cacheItem, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($instrumentation) { $builder = self::makeSpanBuilder($instrumentation, $function, $function, $class, $filename, $lineno); - + if (isset($params[0]) && is_string($params[0])) { $builder->setAttribute('cache.key', $params[0]); } @@ -53,6 +53,7 @@ public static function register(): void }; foreach (['get', 'set', 'delete', 'clear', 'getMultiple', 'setMultiple', 'deleteMultiple', 'has'] as $f) { + /** @psalm-suppress UnusedFunctionCall */ hook(class: CacheInterface::class, function: $f, pre: $pre, post: $post); } } diff --git a/src/Instrumentation/Psr18/composer.json b/src/Instrumentation/Psr18/composer.json index 31f5940f8..19320cf7b 100644 --- a/src/Instrumentation/Psr18/composer.json +++ b/src/Instrumentation/Psr18/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -30,9 +30,9 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" } } diff --git a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php index 3d085bd5f..e8ba3092f 100644 --- a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php +++ b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php @@ -20,6 +20,7 @@ use function strtolower; use Throwable; +/** @psalm-suppress UnusedClass */ class Psr18Instrumentation { /** @psalm-suppress ArgumentTypeCoercion */ @@ -32,6 +33,7 @@ public static function register(): void 'https://opentelemetry.io/schemas/1.30.0', ); + /** @psalm-suppress UnusedFunctionCall */ hook( ClientInterface::class, 'sendRequest', diff --git a/src/Instrumentation/Psr3/composer.json b/src/Instrumentation/Psr3/composer.json index 971ec8828..54fde7dbc 100644 --- a/src/Instrumentation/Psr3/composer.json +++ b/src/Instrumentation/Psr3/composer.json @@ -41,10 +41,10 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "config": { "allow-plugins": { diff --git a/src/Instrumentation/Psr3/src/Formatter.php b/src/Instrumentation/Psr3/src/Formatter.php index c88acdf8f..38a577815 100644 --- a/src/Instrumentation/Psr3/src/Formatter.php +++ b/src/Instrumentation/Psr3/src/Formatter.php @@ -15,7 +15,7 @@ public static function format(array $context): array if ($key === 'exception' && $value instanceof Throwable) { $formatted[$key] = self::formatThrowable($value); } else { - $formatted[$key] = json_decode(json_encode($value)); + $formatted[$key] = json_decode(json_encode($value) ?: ''); } } diff --git a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php index e39b9e9ba..93258e6eb 100644 --- a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php +++ b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php @@ -115,19 +115,19 @@ private static function class_uses_deep(object $class): array // Get traits of all parent classes do { - $traits = array_merge(class_uses($class, false), $traits); + $traits = array_merge(class_uses($class, false) ?: [], $traits); } while ($class = get_parent_class($class)); // Get traits of all parent traits $traitsToSearch = $traits; while (!empty($traitsToSearch)) { - $newTraits = class_uses(array_pop($traitsToSearch), false); + $newTraits = class_uses(array_pop($traitsToSearch), false) ?: []; $traits = array_merge($newTraits, $traits); $traitsToSearch = array_merge($newTraits, $traitsToSearch); }; foreach ($traits as $trait => $same) { - $traits = array_merge(class_uses($trait, false), $traits); + $traits = array_merge(class_uses($trait, false) ?: [], $traits); } return array_unique($traits); diff --git a/src/Instrumentation/Psr3/tests/phpt/disable_via_config.phpt b/src/Instrumentation/Psr3/tests/phpt/disable_via_config.phpt index 955550e7e..26759b86b 100644 --- a/src/Instrumentation/Psr3/tests/phpt/disable_via_config.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/disable_via_config.phpt @@ -3,6 +3,8 @@ Test disabling the psr3 instrumentation --DESCRIPTION-- No otlp logs should be generated, but logging from the psr-3 logger should still be emitted. No context will be injected into the log message. +--INI-- +error_reporting = E_ALL & ~E_DEPRECATED --FILE-- getShortName(); - if ($name === '{closure}') { - return $name; + if ((PHP_VERSION_ID < 80400 && $name === '{closure}') || (PHP_VERSION_ID >= 80400 && str_contains($name, '{closure:'))) { + return '{closure}'; } $class = $reflection->getClosureScopeClass()?->getName() ?? ''; if ($reflection->getClosureScopeClass()?->isAnonymous()) { diff --git a/src/Instrumentation/Slim/src/PsrResponsePropagationSetter.php b/src/Instrumentation/Slim/src/PsrResponsePropagationSetter.php index bee385ad6..69e115542 100644 --- a/src/Instrumentation/Slim/src/PsrResponsePropagationSetter.php +++ b/src/Instrumentation/Slim/src/PsrResponsePropagationSetter.php @@ -21,6 +21,7 @@ public static function instance(): self return $instance ??= new self(); } + /** @psalm-suppress PossiblyUnusedMethod */ public function keys($carrier): array { assert($carrier instanceof ResponseInterface); diff --git a/src/Instrumentation/Slim/src/SlimInstrumentation.php b/src/Instrumentation/Slim/src/SlimInstrumentation.php index b90a18e70..2d6a5c22c 100644 --- a/src/Instrumentation/Slim/src/SlimInstrumentation.php +++ b/src/Instrumentation/Slim/src/SlimInstrumentation.php @@ -22,6 +22,7 @@ use Slim\Routing\RouteContext; use Throwable; +/** @psalm-suppress UnusedClass */ class SlimInstrumentation { public const NAME = 'slim'; @@ -39,8 +40,10 @@ public static function register(): void * requires extension >= 1.0.2beta2 * @see https://github.com/open-telemetry/opentelemetry-php-instrumentation/pull/136 */ - self::$supportsResponsePropagation = version_compare(phpversion('opentelemetry'), '1.0.2beta2') >= 0; + $otelVersion = phpversion('opentelemetry'); + self::$supportsResponsePropagation = $otelVersion !== false && version_compare($otelVersion, '1.0.2beta2') >= 0; + /** @psalm-suppress UnusedFunctionCall */ hook( App::class, 'handle', @@ -122,6 +125,7 @@ public static function register(): void * If routing fails (eg 404/not found), then the root span name will not be updated. * * @psalm-suppress ArgumentTypeCoercion + * @psalm-suppress UnusedFunctionCall */ hook( RoutingMiddleware::class, @@ -148,6 +152,7 @@ public static function register(): void * Create a span for Slim route's action/controller/callable * * @psalm-suppress ArgumentTypeCoercion + * @psalm-suppress UnusedFunctionCall */ hook( InvocationStrategyInterface::class, diff --git a/src/Instrumentation/Slim/tests/Integration/SlimInstrumentationTest.php b/src/Instrumentation/Slim/tests/Integration/SlimInstrumentationTest.php index 9cacfd3d9..4d7f5c1ee 100644 --- a/src/Instrumentation/Slim/tests/Integration/SlimInstrumentationTest.php +++ b/src/Instrumentation/Slim/tests/Integration/SlimInstrumentationTest.php @@ -136,7 +136,8 @@ public function performRouting(ServerRequestInterface $request): ServerRequestIn public function test_response_propagation(): void { - if (version_compare(phpversion('opentelemetry'), '1.0.2beta2') < 0) { + $otelVersion = phpversion('opentelemetry'); + if ($otelVersion == false || version_compare($otelVersion, '1.0.2beta2') < 0) { $this->markTestSkipped('response propagation requires opentelemetry extension >= 1.0.2beta2'); } $request = (new ServerRequest('GET', 'https://example.com/foo')); diff --git a/src/Instrumentation/Slim/tests/Unit/CallableFormatterTest.php b/src/Instrumentation/Slim/tests/Unit/CallableFormatterTest.php index 11a852ce1..2079c00ca 100644 --- a/src/Instrumentation/Slim/tests/Unit/CallableFormatterTest.php +++ b/src/Instrumentation/Slim/tests/Unit/CallableFormatterTest.php @@ -83,9 +83,11 @@ class TestClass public function __invoke() { } + /** @psalm-suppress PossiblyUnusedMethod */ public function method() { } + /** @psalm-suppress PossiblyUnusedMethod */ public static function staticMethod() { } diff --git a/src/Instrumentation/Symfony/composer.json b/src/Instrumentation/Symfony/composer.json index ee8e8d35a..dcc126c99 100644 --- a/src/Instrumentation/Symfony/composer.json +++ b/src/Instrumentation/Symfony/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -26,10 +26,10 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0", + "vimeo/psalm": "6.4.0", "symfony/http-client": "^5.4||^6.0", "symfony/messenger": "^5.4||^6.0", "open-telemetry/opentelemetry-propagation-traceresponse": "*", diff --git a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php index 53b0b77f0..f9233412c 100644 --- a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php +++ b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php @@ -18,6 +18,7 @@ /** * @phan-file-suppress PhanTypeInvalidCallableArraySize + * @psalm-suppress UnusedClass */ final class HttpClientInstrumentation { @@ -43,6 +44,7 @@ public static function register(): void 'https://opentelemetry.io/schemas/1.30.0', ); + /** @psalm-suppress UnusedFunctionCall */ hook( HttpClientInterface::class, 'request', diff --git a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php index 1a3565ef3..fe8e22347 100644 --- a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php +++ b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php @@ -32,6 +32,7 @@ final class MessengerInstrumentation const ATTRIBUTE_MESSENGER_MESSAGE = 'symfony.messenger.message'; const ATTRIBUTE_MESSENGER_TRANSPORT = 'symfony.messenger.transport'; + /** @psalm-suppress PossiblyUnusedMethod */ public static function register(): void { $instrumentation = new CachedInstrumentation( @@ -42,7 +43,9 @@ public static function register(): void /** * MessageBusInterface dispatches messages to the handlers. - */ + * + * @psalm-suppress UnusedFunctionCall + */ hook( MessageBusInterface::class, 'dispatch', @@ -107,7 +110,9 @@ public static function register(): void /** * SenderInterface sends messages to a transport. - */ + * + * @psalm-suppress UnusedFunctionCall + */ hook( SenderInterface::class, 'send', diff --git a/src/Instrumentation/Symfony/src/ResponsePropagationSetter.php b/src/Instrumentation/Symfony/src/ResponsePropagationSetter.php index 1602b976a..eb441cbf1 100644 --- a/src/Instrumentation/Symfony/src/ResponsePropagationSetter.php +++ b/src/Instrumentation/Symfony/src/ResponsePropagationSetter.php @@ -20,7 +20,9 @@ public static function instance(): self return $instance ??= new self(); } - /** @psalm-suppress InvalidReturnType */ + /** @psalm-suppress InvalidReturnType + * @psalm-suppress PossiblyUnusedMethod + */ public function keys($carrier): array { assert($carrier instanceof Response); diff --git a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php index 934e6632f..73478f7bc 100644 --- a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php +++ b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; +/** @psalm-suppress UnusedClass */ final class SymfonyInstrumentation { public const NAME = 'symfony'; @@ -30,6 +31,7 @@ public static function register(): void 'https://opentelemetry.io/schemas/1.30.0', ); + /** @psalm-suppress UnusedFunctionCall */ hook( HttpKernel::class, 'handle', @@ -146,16 +148,17 @@ public static function register(): void } ); + /** @psalm-suppress UnusedFunctionCall */ hook( HttpKernel::class, 'handleThrowable', pre: static function ( - HttpKernel $kernel, + HttpKernel $_kernel, array $params, - string $class, - string $function, - ?string $filename, - ?int $lineno, + string $_class, + string $_function, + ?string $_filename, + ?int $_lineno, ): array { /** @var \Throwable $throwable */ $throwable = $params[0]; diff --git a/src/Instrumentation/Symfony/tests/Integration/HttpClientInstrumentationTest.php b/src/Instrumentation/Symfony/tests/Integration/HttpClientInstrumentationTest.php index 2221b977c..be9a18f9e 100644 --- a/src/Instrumentation/Symfony/tests/Integration/HttpClientInstrumentationTest.php +++ b/src/Instrumentation/Symfony/tests/Integration/HttpClientInstrumentationTest.php @@ -5,8 +5,6 @@ namespace OpenTelemetry\Tests\Instrumentation\Symfony\tests\Integration; use OpenTelemetry\API\Trace\StatusCode; -use OpenTelemetry\SDK\Trace\EventInterface; -use OpenTelemetry\SDK\Trace\ImmutableSpan; use OpenTelemetry\SemConv\TraceAttributes; use Symfony\Component\HttpClient\CurlHttpClient; use Symfony\Component\HttpClient\Exception\InvalidArgumentException; @@ -21,7 +19,7 @@ public static function setUpBeforeClass(): void TestHttpServer::start(); } - protected function getHttpClient(string $testCase): HttpClientInterface + protected function getHttpClient(string $_testCase): HttpClientInterface { return new CurlHttpClient(['verify_peer' => false, 'verify_host' => false]); } @@ -38,7 +36,6 @@ public function test_send_request(string $method, string $uri, int $statusCode, $response->getStatusCode(); $this->assertCount(1, $this->storage); - /** @var ImmutableSpan $span */ $span = $this->storage[0]; $this->assertStringContainsString($method, $span->getName()); @@ -65,7 +62,7 @@ public function test_throw_exception(): void $this->assertCount(0, $this->storage); try { - $response = $client->request('GET', 'http://localhost:8057', [ + $client->request('GET', 'http://localhost:8057', [ 'bindto' => '127.0.0.1:9876', 'auth_ntlm' => [], ]); @@ -74,9 +71,7 @@ public function test_throw_exception(): void $this->assertCount(1, $this->storage); - /** @var ImmutableSpan $span */ $span = $this->storage[0]; - /** @var EventInterface $event */ $event = $span->getEvents()[0]; $this->assertTrue($span->getAttributes()->has(TraceAttributes::URL_FULL)); diff --git a/src/Instrumentation/Symfony/tests/Integration/MessengerInstrumentationTest.php b/src/Instrumentation/Symfony/tests/Integration/MessengerInstrumentationTest.php index 63d38849c..c2fa139b2 100644 --- a/src/Instrumentation/Symfony/tests/Integration/MessengerInstrumentationTest.php +++ b/src/Instrumentation/Symfony/tests/Integration/MessengerInstrumentationTest.php @@ -6,7 +6,6 @@ use OpenTelemetry\API\Trace\SpanKind; use OpenTelemetry\Contrib\Instrumentation\Symfony\MessengerInstrumentation; -use OpenTelemetry\SDK\Trace\ImmutableSpan; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; @@ -23,6 +22,7 @@ public function __construct(string $message) $this->message = $message; } + /** @psalm-suppress PossiblyUnusedMethod */ public function getMessage(): string { return $this->message; @@ -61,7 +61,6 @@ public function test_dispatch_message($message, string $spanName, int $kind, arr $this->assertCount(1, $this->storage); - /** @var ImmutableSpan $span */ $span = $this->storage[0]; $this->assertEquals($spanName, $span->getName()); @@ -87,7 +86,6 @@ public function test_send_message($message, string $spanName, int $kind, array $ $this->assertCount(1, $this->storage); - /** @var ImmutableSpan $span */ $span = $this->storage[0]; $this->assertEquals($spanName, $span->getName()); @@ -112,9 +110,7 @@ public function dispatch(object $message, array $stamps = []): Envelope $bus->dispatch(new SendEmailMessage('Hello Again')); } catch (\Throwable $e) { $this->assertCount(1, $this->storage); - - /** @var ImmutableSpan $span */ - $span = $this->storage[0]; + $this->assertArrayHasKey(0, $this->storage); } } @@ -146,8 +142,7 @@ public function send(Envelope $envelope): Envelope $transport->send(new Envelope(new SendEmailMessage('Hello Again'))); } catch (\Throwable $e) { $this->assertCount(1, $this->storage); - - $span = $this->storage[0]; + $this->assertArrayHasKey(0, $this->storage); } } diff --git a/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php b/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php index 7bbe0a608..b9b6401a4 100644 --- a/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php +++ b/src/Instrumentation/Symfony/tests/Integration/SymfonyInstrumentationTest.php @@ -8,7 +8,6 @@ use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Contrib\Propagation\ServerTiming\ServerTimingPropagator; use OpenTelemetry\Contrib\Propagation\TraceResponse\TraceResponsePropagator; -use OpenTelemetry\SDK\Trace\ImmutableSpan; use OpenTelemetry\SemConv\TraceAttributes; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -200,13 +199,12 @@ public function test_http_kernel_handle_subrequest(): void $kernel->handle($request, HttpKernelInterface::SUB_REQUEST); $this->assertCount(1, $this->storage); - /** @var ImmutableSpan $span */ $span = $this->storage[0]; $this->assertSame('GET ErrorController', $span->getName()); $this->assertSame(SpanKind::KIND_INTERNAL, $span->getKind()); } - private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = []): HttpKernel + private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, ?RequestStack $requestStack = null, array $arguments = []): HttpKernel { $controller ??= fn () => new Response('Hello'); diff --git a/src/Instrumentation/Wordpress/composer.json b/src/Instrumentation/Wordpress/composer.json index 30ef2e74d..350de2343 100644 --- a/src/Instrumentation/Wordpress/composer.json +++ b/src/Instrumentation/Wordpress/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", "open-telemetry/sem-conv": "^1.30", @@ -22,9 +22,9 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Instrumentation/Yii/composer.json b/src/Instrumentation/Yii/composer.json index 1d0c58e75..8a43835b8 100644 --- a/src/Instrumentation/Yii/composer.json +++ b/src/Instrumentation/Yii/composer.json @@ -7,7 +7,7 @@ "readme": "./README.md", "license": "Apache-2.0", "require": { - "php": "^8.0", + "php": "^8.1", "ext-opentelemetry": "*", "yiisoft/yii2": "^2.0.13", "open-telemetry/api": "^1", @@ -20,9 +20,9 @@ "php-http/mock-client": "*", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "repositories": [ { diff --git a/src/Instrumentation/Yii/src/YiiInstrumentation.php b/src/Instrumentation/Yii/src/YiiInstrumentation.php index bc2795822..96494a34d 100644 --- a/src/Instrumentation/Yii/src/YiiInstrumentation.php +++ b/src/Instrumentation/Yii/src/YiiInstrumentation.php @@ -166,7 +166,7 @@ protected static function getResponseLength(Response $response): ?string protected static function normalizeRouteName(string $controllerClassName, string $actionName): string { $lastSegment = strrchr($controllerClassName, '\\'); - + if ($lastSegment === false) { return $controllerClassName . '.' . $actionName; } diff --git a/src/Logs/Monolog/composer.json b/src/Logs/Monolog/composer.json index f9d87cc5d..43daefa6b 100644 --- a/src/Logs/Monolog/composer.json +++ b/src/Logs/Monolog/composer.json @@ -29,9 +29,9 @@ "phpbench/phpbench": "^1.2", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "config": { "allow-plugins": { diff --git a/src/Logs/Monolog/tests/Benchmark/LoggingBench.php b/src/Logs/Monolog/tests/Benchmark/LoggingBench.php index b1e7940fc..3c7d28f8a 100644 --- a/src/Logs/Monolog/tests/Benchmark/LoggingBench.php +++ b/src/Logs/Monolog/tests/Benchmark/LoggingBench.php @@ -5,6 +5,7 @@ use Monolog\Logger; use OpenTelemetry\Contrib\Logs\Monolog\Handler; +/** @psalm-suppress UnusedClass */ class LoggingBench { private array $loggers = []; diff --git a/src/Propagation/ServerTiming/composer.json b/src/Propagation/ServerTiming/composer.json index 681e906d1..194f8b904 100644 --- a/src/Propagation/ServerTiming/composer.json +++ b/src/Propagation/ServerTiming/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "open-telemetry/context": "^1.0" }, "autoload": { @@ -22,12 +22,12 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4|^5", + "vimeo/psalm": "^4|^5|^6", "symfony/http-client": "^5.4|^6.0", - "guzzlehttp/promises": "^1.5", + "guzzlehttp/promises": "^1.5|^2", "php-http/message-factory": "^1.0", "nyholm/psr7": "^1.5" }, diff --git a/src/Propagation/TraceResponse/composer.json b/src/Propagation/TraceResponse/composer.json index acb16f4c8..0fd063948 100644 --- a/src/Propagation/TraceResponse/composer.json +++ b/src/Propagation/TraceResponse/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^7.0|^8.0", + "php": "^8.1", "open-telemetry/context": "^1.0" }, "autoload": { @@ -22,10 +22,10 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "open-telemetry/sdk": "^1.0", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0", + "vimeo/psalm": "6.4.0", "symfony/http-client": "^5.4|^6.0", "guzzlehttp/promises": "^2", "php-http/message-factory": "^1.0", diff --git a/src/ResourceDetectors/Azure/composer.json b/src/ResourceDetectors/Azure/composer.json index dda9a0e38..b83009e9f 100644 --- a/src/ResourceDetectors/Azure/composer.json +++ b/src/ResourceDetectors/Azure/composer.json @@ -13,7 +13,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "open-telemetry/api": "^1.0", "open-telemetry/sdk": "^1.0", "open-telemetry/sem-conv": "^1.30" @@ -30,8 +30,8 @@ "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "~9", - "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.0" + "psalm/plugin-phpunit": "^0.19.2", + "vimeo/psalm": "6.4.0" }, "autoload": { "psr-4": { diff --git a/src/ResourceDetectors/Container/composer.json b/src/ResourceDetectors/Container/composer.json index 1144a0355..898106de2 100644 --- a/src/ResourceDetectors/Container/composer.json +++ b/src/ResourceDetectors/Container/composer.json @@ -9,7 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": "^8.0", + "php": "^8.1", "open-telemetry/sdk": "^1.0" }, "autoload": { @@ -26,11 +26,11 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0", + "vimeo/psalm": "6.4.0", "symfony/http-client": "^5.4|^6.0", - "guzzlehttp/promises": "^1.5", + "guzzlehttp/promises": "^1.5|^2", "php-http/message-factory": "^1.0", "nyholm/psr7": "^1.5" }, diff --git a/src/Sampler/RuleBased/composer.json b/src/Sampler/RuleBased/composer.json index 60b4a8d59..7094aad40 100644 --- a/src/Sampler/RuleBased/composer.json +++ b/src/Sampler/RuleBased/composer.json @@ -16,9 +16,9 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^10 || ^11", - "vimeo/psalm": "^4|^5" + "vimeo/psalm": "^4|^5|6.4.0" }, "autoload": { "psr-4": { diff --git a/src/Sampler/RuleBased/psalm.xml.dist b/src/Sampler/RuleBased/psalm.xml.dist index 995b2a653..c9650afeb 100644 --- a/src/Sampler/RuleBased/psalm.xml.dist +++ b/src/Sampler/RuleBased/psalm.xml.dist @@ -20,11 +20,6 @@ - - - - - diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php index 0a714940a..aa01e64d9 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplerRuleBased.php @@ -52,6 +52,8 @@ public function createPlugin(array $properties, Context $context): SamplerInterf public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { $node = new ArrayNodeDefinition('contrib_rule_based'); + + /** @psalm-suppress PossiblyNullReference */ $node ->children() ->arrayNode('rule_sets') diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php index 6c67736b3..c409e7df4 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleAttribute.php @@ -36,6 +36,8 @@ public function createPlugin(array $properties, Context $context): SamplingRule public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { $node = new ArrayNodeDefinition('attribute'); + + /** @psalm-suppress PossiblyNullReference */ $node ->children() ->scalarNode('key') diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php index 17cc55114..dec9bc70e 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleLink.php @@ -34,6 +34,8 @@ public function createPlugin(array $properties, Context $context): SamplingRule public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { $node = new ArrayNodeDefinition('link'); + + /** @psalm-suppress PossiblyNullReference */ $node ->children() ->booleanNode('sampled')->isRequired()->end() diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php index af8185203..40dbcc74b 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleParent.php @@ -34,6 +34,8 @@ public function createPlugin(array $properties, Context $context): SamplingRule public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { $node = new ArrayNodeDefinition('parent'); + + /** @psalm-suppress PossiblyNullReference */ $node ->children() ->booleanNode('sampled')->isRequired()->end() diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php index 429bcc216..b7dfa61d2 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanKind.php @@ -39,6 +39,8 @@ public function createPlugin(array $properties, Context $context): SamplingRule public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { $node = new ArrayNodeDefinition('span_kind'); + + /** @psalm-suppress PossiblyNullReference */ $node ->children() ->enumNode('kind') diff --git a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php index 10c49633d..49f5e605c 100644 --- a/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php +++ b/src/Sampler/RuleBased/src/ComponentProvider/SamplingRuleSpanName.php @@ -34,6 +34,8 @@ public function createPlugin(array $properties, Context $context): SamplingRule public function getConfig(ComponentProviderRegistry $registry): ArrayNodeDefinition { $node = new ArrayNodeDefinition('span_name'); + + /** @psalm-suppress PossiblyNullReference */ $node ->children() ->scalarNode('pattern') diff --git a/src/Shims/OpenTracing/composer.json b/src/Shims/OpenTracing/composer.json index e488accce..5b981f13e 100644 --- a/src/Shims/OpenTracing/composer.json +++ b/src/Shims/OpenTracing/composer.json @@ -27,9 +27,9 @@ "phan/phan": "^5.0", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "config": { "allow-plugins": { diff --git a/src/Shims/OpenTracing/src/SpanContext.php b/src/Shims/OpenTracing/src/SpanContext.php index 89498b0a3..3e74368ba 100644 --- a/src/Shims/OpenTracing/src/SpanContext.php +++ b/src/Shims/OpenTracing/src/SpanContext.php @@ -43,6 +43,7 @@ public function withBaggageItem(string $key, string $value): API\SpanContext return new self($this->context, [$key => $value] + $this->baggageItems); } + /** @psalm-suppress PossiblyUnusedMethod */ public function getContext(): ContextInterface { return $this->context; diff --git a/src/Symfony/composer.json b/src/Symfony/composer.json index 20b056a75..7705d845f 100644 --- a/src/Symfony/composer.json +++ b/src/Symfony/composer.json @@ -48,14 +48,14 @@ "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-symfony": "^1.1", "phpunit/phpunit": "^9.5", - "psalm/plugin-phpunit": "^0.18.4", + "psalm/plugin-phpunit": "^0.19.2", "symfony/config": "^4.4|^5.0|^6.0", "symfony/http-client": "^5.3", "symfony/http-kernel": "^4.4|^5.3|^6.0", "symfony/options-resolver": "^4.4|^5.3|^6.0", "symfony/proxy-manager-bridge": "^4.4|^5.3|^6.0", "symfony/yaml": "^4.4|^5.3|^6.0", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "6.4.0" }, "suggest": { "symfony/config": "Needed to use otel-sdk-bundle", diff --git a/src/Symfony/psalm.xml.dist b/src/Symfony/psalm.xml.dist index 2c9d165c4..ab6ba8fca 100644 --- a/src/Symfony/psalm.xml.dist +++ b/src/Symfony/psalm.xml.dist @@ -18,12 +18,4 @@ - - - - - - - - diff --git a/src/Symfony/src/OtelBundle/composer.json b/src/Symfony/src/OtelBundle/composer.json index ade2d770c..d061d6cbc 100644 --- a/src/Symfony/src/OtelBundle/composer.json +++ b/src/Symfony/src/OtelBundle/composer.json @@ -5,7 +5,7 @@ "type": "symfony-bundle", "license": "Apache-2.0", "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "composer-runtime-api": "^2.0", "open-telemetry/api": "^1", "open-telemetry/context": "^1", diff --git a/src/Symfony/src/OtelSdkBundle/Factory/GenericFactoryTrait.php b/src/Symfony/src/OtelSdkBundle/Factory/GenericFactoryTrait.php index 48906a747..7d28a1248 100644 --- a/src/Symfony/src/OtelSdkBundle/Factory/GenericFactoryTrait.php +++ b/src/Symfony/src/OtelSdkBundle/Factory/GenericFactoryTrait.php @@ -228,6 +228,7 @@ private function parameterCallback(ReflectionParameter $parameter, string $optio private static function camelToSnakeCase(string $value): string { + /** @psalm-suppress PossiblyNullArgument */ return strtolower( ltrim( preg_replace( diff --git a/src/Symfony/src/OtelSdkBundle/Util/ServiceHelper.php b/src/Symfony/src/OtelSdkBundle/Util/ServiceHelper.php index 9c17f7b6f..4c5d92660 100644 --- a/src/Symfony/src/OtelSdkBundle/Util/ServiceHelper.php +++ b/src/Symfony/src/OtelSdkBundle/Util/ServiceHelper.php @@ -12,6 +12,7 @@ class ServiceHelper */ public static function classToId(string $class): string { + /** @psalm-suppress PossiblyNullArgument */ return str_replace( '\_', '.', diff --git a/src/Symfony/tests/Unit/OtelSdkBundle/Util/ServiceHelperTest.php b/src/Symfony/tests/Unit/OtelSdkBundle/Util/ServiceHelperTest.php index fc317a7ec..3ed1a53bd 100644 --- a/src/Symfony/tests/Unit/OtelSdkBundle/Util/ServiceHelperTest.php +++ b/src/Symfony/tests/Unit/OtelSdkBundle/Util/ServiceHelperTest.php @@ -28,7 +28,7 @@ public function testFloatToString() ServiceHelper::floatToString(0.5) ); $this->assertSame( - '2.1234567890124', + PHP_VERSION_ID < 80400 ? '2.1234567890124' : '2.1234567890123', ServiceHelper::floatToString(2.12345678901234567890) ); }