From 673f2f9aed197fb12193d52a6136959ed0718e1a Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Thu, 24 Apr 2025 12:12:58 -0700 Subject: [PATCH 01/12] [aws-sdk]Added Initial auto-instrumentation library for aws-sdk --- src/Instrumentation/AwsSdk/.gitignore | 2 + src/Instrumentation/AwsSdk/.php-cs-fixer.php | 45 ++++++++++ src/Instrumentation/AwsSdk/README.md | 25 ++++++ src/Instrumentation/AwsSdk/_register.php | 20 +++++ src/Instrumentation/AwsSdk/composer.json | 47 ++++++++++ src/Instrumentation/AwsSdk/phpstan.neon.dist | 12 +++ src/Instrumentation/AwsSdk/phpunit.xml.dist | 47 ++++++++++ src/Instrumentation/AwsSdk/psalm.xml.dist | 15 ++++ .../AwsSdk/src/AwsSdkInstrumentation.php | 89 +++++++++++++++++++ .../Integration/AwsSdkInstrumentationTest.php | 83 +++++++++++++++++ .../AwsSdk/tests/Unit/.gitkeep | 0 11 files changed, 385 insertions(+) create mode 100644 src/Instrumentation/AwsSdk/.gitignore create mode 100644 src/Instrumentation/AwsSdk/.php-cs-fixer.php create mode 100644 src/Instrumentation/AwsSdk/README.md create mode 100644 src/Instrumentation/AwsSdk/_register.php create mode 100644 src/Instrumentation/AwsSdk/composer.json create mode 100644 src/Instrumentation/AwsSdk/phpstan.neon.dist create mode 100644 src/Instrumentation/AwsSdk/phpunit.xml.dist create mode 100644 src/Instrumentation/AwsSdk/psalm.xml.dist create mode 100644 src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php create mode 100644 src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php create mode 100644 src/Instrumentation/AwsSdk/tests/Unit/.gitkeep diff --git a/src/Instrumentation/AwsSdk/.gitignore b/src/Instrumentation/AwsSdk/.gitignore new file mode 100644 index 000000000..3a9875b46 --- /dev/null +++ b/src/Instrumentation/AwsSdk/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/src/Instrumentation/AwsSdk/.php-cs-fixer.php b/src/Instrumentation/AwsSdk/.php-cs-fixer.php new file mode 100644 index 000000000..73e33d1ef --- /dev/null +++ b/src/Instrumentation/AwsSdk/.php-cs-fixer.php @@ -0,0 +1,45 @@ +exclude('vendor') + ->exclude('tests/Unit81') //contains php8.1 syntax + ->exclude('var/cache') + ->exclude('tests/coverage') + ->in(__DIR__); + +$config = new PhpCsFixer\Config(); +return $config->setRules([ + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => ['space' => 'none'], + 'is_null' => true, + 'modernize_types_casting' => true, + 'ordered_imports' => true, + 'php_unit_construct' => true, + 'single_line_comment_style' => true, + 'yoda_style' => false, + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => true, + 'cast_spaces' => true, + 'declare_strict_types' => true, + 'type_declaration_spaces' => true, + 'include' => true, + 'lowercase_cast' => true, + 'new_with_parentheses' => true, + 'no_extra_blank_lines' => true, + 'no_leading_import_slash' => true, + 'echo_tag_syntax' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_types' => true, + 'short_scalar_cast' => true, + 'blank_lines_before_namespace' => true, + 'single_quote' => true, + 'trailing_comma_in_multiline' => true, + ]) + ->setRiskyAllowed(true) + ->setFinder($finder); + diff --git a/src/Instrumentation/AwsSdk/README.md b/src/Instrumentation/AwsSdk/README.md new file mode 100644 index 000000000..78646ed18 --- /dev/null +++ b/src/Instrumentation/AwsSdk/README.md @@ -0,0 +1,25 @@ +[![Releases](https://img.shields.io/badge/releases-purple)](https://github.com/opentelemetry-php/contrib-auto-aws-sdk/releases) +[![Issues](https://img.shields.io/badge/issues-pink)](https://github.com/open-telemetry/opentelemetry-php/issues) +[![Source](https://img.shields.io/badge/source-contrib-green)](https://github.com/open-telemetry/opentelemetry-php-contrib/tree/main/src/Instrumentation/AwsSdk) +[![Mirror](https://img.shields.io/badge/mirror-opentelemetry--php--contrib-blue)](https://github.com/opentelemetry-php/contrib-auto-aws-sdk) +[![Latest Version](http://poser.pugx.org/open-telemetry/opentelemetry-auto-guzzle/v/unstable)](https://packagist.org/packages/open-telemetry/opentelemetry-auto-aws-sdk/) +[![Stable](http://poser.pugx.org/open-telemetry/opentelemetry-auto-aws-sdk/v/stable)](https://packagist.org/packages/open-telemetry/opentelemetry-auto-aws-sdk/) + +This is a read-only subtree split of https://github.com/open-telemetry/opentelemetry-php-contrib. + +# OpenTelemetry AWS SDK auto-instrumentation +Please read https://opentelemetry.io/docs/instrumentation/php/automatic/ for instructions on how to +install and configure the extension and SDK. + +## Overview +Auto-instrumentation hooks are registered via composer. + +* create spans automatically for each AWS SDK request that is sent + +## Configuration + +The extension can be disabled via [runtime configuration](https://opentelemetry.io/docs/instrumentation/php/sdk/#configuration): + +```shell +OTEL_PHP_DISABLED_INSTRUMENTATIONS=aws-sdk +``` diff --git a/src/Instrumentation/AwsSdk/_register.php b/src/Instrumentation/AwsSdk/_register.php new file mode 100644 index 000000000..b701f8a0c --- /dev/null +++ b/src/Instrumentation/AwsSdk/_register.php @@ -0,0 +1,20 @@ + + + + + + + src + + + + + + + + + + + + + tests/Unit + + + tests/Integration + + + + diff --git a/src/Instrumentation/AwsSdk/psalm.xml.dist b/src/Instrumentation/AwsSdk/psalm.xml.dist new file mode 100644 index 000000000..155711712 --- /dev/null +++ b/src/Instrumentation/AwsSdk/psalm.xml.dist @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php new file mode 100644 index 000000000..09b245cc2 --- /dev/null +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -0,0 +1,89 @@ +tracer() + ->spanBuilder("{$c->getApi()->getServiceName()}.{$cmd->getName()}") + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setAttribute('rpc.system', 'aws-api') + ->setAttribute('rpc.method', $cmd->getName()) + ->setAttribute('rpc.service', $c->getApi()->getServiceName()) + ->setAttribute('aws.region', $c->getRegion()) + ->setAttribute('code.function', $func) + ->setAttribute('code.namespace', $class) + ->setAttribute('code.filepath', $file) + ->setAttribute('code.line_number', $line); + + $span = $builder->startSpan(); + Context::storage()->attach($span->storeInContext(Context::getCurrent())); + }, + post: static function ( + AwsClient $c, + array $params, + mixed $result, + ?\Throwable $ex + ) { + $scope = Context::storage()->scope(); + if (!$scope) { + return; + } + $span = Span::fromContext($scope->context()); + $scope->detach(); + + if ($result instanceof ResultInterface && isset($result['@metadata'])) { + $span->setAttribute('http.status_code', $result['@metadata']['statusCode']); + $span->setAttribute('aws.requestId', $result['@metadata']['headers']['x-amz-request-id']); + } + if ($ex) { + if ($ex instanceof AwsException && $ex->getAwsRequestId() !== null) { + $span->setAttribute('aws.requestId', $ex->getAwsRequestId()); + } + $span->recordException($ex); + $span->setStatus(StatusCode::STATUS_ERROR, $ex->getMessage()); + } + $span->end(); + } + ); + } +} diff --git a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php new file mode 100644 index 000000000..13612df16 --- /dev/null +++ b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php @@ -0,0 +1,83 @@ +spans = new ArrayObject(); + $tracerProvider = new TracerProvider( + new SimpleSpanProcessor(new InMemoryExporter($this->spans)) + ); + $this->scope = Configurator::create() + ->withTracerProvider($tracerProvider) + ->withPropagator(TraceContextPropagator::getInstance()) + ->activate(); + + $this->mock = new MockHandler(); + $this->mock->append(new Result([ + '@metadata' => [ + 'statusCode' => 200, + 'headers' => [ + 'x-amz-request-id' => 'TEST-REQUEST-ID', + ], + ], + ])); + + $this->client = new S3Client([ + 'region' => 'us-west-2', + 'version' => 'latest', + 'handler' => $this->mock, + ]); + } + + public function tearDown(): void + { + $this->scope->detach(); + } + + public function test_listBuckets_generates_one_aws_span_with_expected_attributes(): void + { + $this->client->listBuckets(); + + $this->assertCount(1, $this->spans); + + $span = $this->spans->offsetGet(0); + + $this->assertInstanceOf(ImmutableSpan::class, $span); + + $this->assertSame('s3.ListBuckets', $span->getName()); + + $attrs = $span->getAttributes(); + $this->assertSame('aws-api', $attrs->get('rpc.system')); + $this->assertSame('s3', $attrs->get('rpc.service')); + $this->assertSame('ListBuckets', $attrs->get('rpc.method')); + $this->assertSame('us-west-2', $attrs->get('aws.region')); + $this->assertSame(200, $attrs->get('http.status_code')); + $this->assertSame('TEST-REQUEST-ID', $attrs->get('aws.requestId')); + } +} diff --git a/src/Instrumentation/AwsSdk/tests/Unit/.gitkeep b/src/Instrumentation/AwsSdk/tests/Unit/.gitkeep new file mode 100644 index 000000000..e69de29bb From 28a512eb1705c1d807127a50890e42cc95776868 Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Tue, 29 Apr 2025 12:07:36 -0700 Subject: [PATCH 02/12] Updated to use sem covs instead of hardcoding --- src/Instrumentation/AwsSdk/composer.json | 3 +- .../AwsSdk/src/AwsSdkInstrumentation.php | 29 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Instrumentation/AwsSdk/composer.json b/src/Instrumentation/AwsSdk/composer.json index e5bb1c5e7..ed2221efa 100644 --- a/src/Instrumentation/AwsSdk/composer.json +++ b/src/Instrumentation/AwsSdk/composer.json @@ -12,7 +12,8 @@ "php": "^8.2", "aws/aws-sdk-php": "^3", "ext-opentelemetry": "*", - "open-telemetry/api": "^1.0" + "open-telemetry/api": "^1.0", + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php index 09b245cc2..7a061337e 100644 --- a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -14,6 +14,7 @@ use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; +use OpenTelemetry\SemConv\TraceAttributes; final class AwsSdkInstrumentation { @@ -38,22 +39,22 @@ public static function register(): void AwsClient $c, array $params, string $class, - string $func, - ?string $file, - ?int $line + string $function, + ?string $filename, + ?int $lineno ) use ($inst) { $cmd = $params[0]; $builder = $inst->tracer() ->spanBuilder("{$c->getApi()->getServiceName()}.{$cmd->getName()}") ->setSpanKind(SpanKind::KIND_CLIENT) - ->setAttribute('rpc.system', 'aws-api') - ->setAttribute('rpc.method', $cmd->getName()) - ->setAttribute('rpc.service', $c->getApi()->getServiceName()) - ->setAttribute('aws.region', $c->getRegion()) - ->setAttribute('code.function', $func) - ->setAttribute('code.namespace', $class) - ->setAttribute('code.filepath', $file) - ->setAttribute('code.line_number', $line); + ->setAttribute(TraceAttributes::RPC_SYSTEM, 'aws-api') + ->setAttribute(TraceAttributes::RPC_METHOD, $cmd->getName()) + ->setAttribute(TraceAttributes::RPC_SERVICE, $c->getApi()->getServiceName()) + ->setAttribute(TraceAttributes::CLOUD_REGION, $c->getRegion()) + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) + ->setAttribute(TraceAttributes::CODE_NAMESPACE, $class) + ->setAttribute(TraceAttributes::CODE_FILEPATH, $filename) + ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno); $span = $builder->startSpan(); Context::storage()->attach($span->storeInContext(Context::getCurrent())); @@ -72,12 +73,12 @@ public static function register(): void $scope->detach(); if ($result instanceof ResultInterface && isset($result['@metadata'])) { - $span->setAttribute('http.status_code', $result['@metadata']['statusCode']); - $span->setAttribute('aws.requestId', $result['@metadata']['headers']['x-amz-request-id']); + $span->setAttribute(TraceAttributes::HTTP_RESPONSE_STATUS_CODE, $result['@metadata']['statusCode']); + $span->setAttribute(TraceAttributes::AWS_REQUEST_ID, $result['@metadata']['headers']['x-amz-request-id']); } if ($ex) { if ($ex instanceof AwsException && $ex->getAwsRequestId() !== null) { - $span->setAttribute('aws.requestId', $ex->getAwsRequestId()); + $span->setAttribute(TraceAttributes::AWS_REQUEST_ID, $ex->getAwsRequestId()); } $span->recordException($ex); $span->setStatus(StatusCode::STATUS_ERROR, $ex->getMessage()); From 45224ce124266c40e31ad25eed22e299f8e81a2c Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Tue, 13 May 2025 11:12:33 -0700 Subject: [PATCH 03/12] added to gitsplit --- .gitsplit.yml | 2 ++ src/Instrumentation/AwsSdk/README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitsplit.yml b/.gitsplit.yml index 072982784..330f1c222 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -60,6 +60,8 @@ splits: target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-auto-yii.git" - prefix: "src/Instrumentation/Doctrine" target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-auto-doctrine.git" + - prefix: "src/Instrumentation/AwsSdk" + target: "https://${GH_TOKEN}@github.com/opentelemetry-php/contrib-auto-aws-sdk.git" - prefix: "src/Context/Swoole" target: "https://${GH_TOKEN}@github.com/opentelemetry-php/context-swoole.git" - prefix: "src/AutoInstrumentationInstaller" diff --git a/src/Instrumentation/AwsSdk/README.md b/src/Instrumentation/AwsSdk/README.md index 78646ed18..8ab0a8a70 100644 --- a/src/Instrumentation/AwsSdk/README.md +++ b/src/Instrumentation/AwsSdk/README.md @@ -2,7 +2,7 @@ [![Issues](https://img.shields.io/badge/issues-pink)](https://github.com/open-telemetry/opentelemetry-php/issues) [![Source](https://img.shields.io/badge/source-contrib-green)](https://github.com/open-telemetry/opentelemetry-php-contrib/tree/main/src/Instrumentation/AwsSdk) [![Mirror](https://img.shields.io/badge/mirror-opentelemetry--php--contrib-blue)](https://github.com/opentelemetry-php/contrib-auto-aws-sdk) -[![Latest Version](http://poser.pugx.org/open-telemetry/opentelemetry-auto-guzzle/v/unstable)](https://packagist.org/packages/open-telemetry/opentelemetry-auto-aws-sdk/) +[![Latest Version](http://poser.pugx.org/open-telemetry/opentelemetry-auto-aws-sdk/v/unstable)](https://packagist.org/packages/open-telemetry/opentelemetry-auto-aws-sdk/) [![Stable](http://poser.pugx.org/open-telemetry/opentelemetry-auto-aws-sdk/v/stable)](https://packagist.org/packages/open-telemetry/opentelemetry-auto-aws-sdk/) This is a read-only subtree split of https://github.com/open-telemetry/opentelemetry-php-contrib. From be7848eb62849050a7b5b2dc9109aacaa1903669 Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Tue, 13 May 2025 11:14:42 -0700 Subject: [PATCH 04/12] added gitattributes file --- src/Instrumentation/AwsSdk/.gitattributes | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/Instrumentation/AwsSdk/.gitattributes diff --git a/src/Instrumentation/AwsSdk/.gitattributes b/src/Instrumentation/AwsSdk/.gitattributes new file mode 100644 index 000000000..1676cf825 --- /dev/null +++ b/src/Instrumentation/AwsSdk/.gitattributes @@ -0,0 +1,12 @@ +* text=auto + +*.md diff=markdown +*.php diff=php + +/.gitattributes export-ignore +/.gitignore export-ignore +/.php-cs-fixer.php export-ignore +/phpstan.neon.dist export-ignore +/phpunit.xml.dist export-ignore +/psalm.xml.dist export-ignore +/tests export-ignore From 5f3a9ed65fe30c1b8386d0a2fcce8636075a64fa Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Wed, 14 May 2025 13:28:39 -0700 Subject: [PATCH 05/12] Updated to use the latest semcov 1.32 --- src/Instrumentation/AwsSdk/composer.json | 2 +- src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php | 7 +++---- .../AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php | 7 ++++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Instrumentation/AwsSdk/composer.json b/src/Instrumentation/AwsSdk/composer.json index ed2221efa..92bfaa96f 100644 --- a/src/Instrumentation/AwsSdk/composer.json +++ b/src/Instrumentation/AwsSdk/composer.json @@ -13,7 +13,7 @@ "aws/aws-sdk-php": "^3", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.30" + "open-telemetry/sem-conv": "^1.32" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php index 7a061337e..0a50b63d9 100644 --- a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -25,7 +25,7 @@ public static function register(): void $inst = new CachedInstrumentation( 'io.opentelemetry.contrib.php.aws-sdk', null, - 'https://opentelemetry.io/schemas/1.30.0', + 'https://opentelemetry.io/schemas/1.32.0', ); /** @@ -51,9 +51,8 @@ public static function register(): void ->setAttribute(TraceAttributes::RPC_METHOD, $cmd->getName()) ->setAttribute(TraceAttributes::RPC_SERVICE, $c->getApi()->getServiceName()) ->setAttribute(TraceAttributes::CLOUD_REGION, $c->getRegion()) - ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) - ->setAttribute(TraceAttributes::CODE_NAMESPACE, $class) - ->setAttribute(TraceAttributes::CODE_FILEPATH, $filename) + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function)) + ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename) ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno); $span = $builder->startSpan(); diff --git a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php index 13612df16..95354f51e 100644 --- a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php +++ b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php @@ -73,11 +73,12 @@ public function test_listBuckets_generates_one_aws_span_with_expected_attributes $this->assertSame('s3.ListBuckets', $span->getName()); $attrs = $span->getAttributes(); + $this->assertSame('Aws\AwsClient::execute', $attrs->get('code.function.name')); $this->assertSame('aws-api', $attrs->get('rpc.system')); $this->assertSame('s3', $attrs->get('rpc.service')); $this->assertSame('ListBuckets', $attrs->get('rpc.method')); - $this->assertSame('us-west-2', $attrs->get('aws.region')); - $this->assertSame(200, $attrs->get('http.status_code')); - $this->assertSame('TEST-REQUEST-ID', $attrs->get('aws.requestId')); + $this->assertSame('us-west-2', $attrs->get('cloud.region')); + $this->assertSame(200, $attrs->get('http.response.status_code')); + $this->assertSame('TEST-REQUEST-ID', $attrs->get('aws.request_id')); } } From 500afb63b9bc0b306189063d3922cda79d0b4f72 Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Thu, 15 May 2025 15:21:31 -0700 Subject: [PATCH 06/12] Added aws tests to php.yml --- .github/workflows/php.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 601a3f5d0..99d19925a 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -22,6 +22,7 @@ jobs: project: [ 'Aws', 'Context/Swoole', + 'Instrumentation/AwsSdk', 'Instrumentation/CakePHP', 'Instrumentation/CodeIgniter', 'Instrumentation/Curl', From 9a940088f79f99c15569a39267c40a91a4564511 Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Wed, 21 May 2025 11:32:24 -0700 Subject: [PATCH 07/12] Updated composer for php 8.1 and fixed style issue --- src/Instrumentation/AwsSdk/_register.php | 4 +++- src/Instrumentation/AwsSdk/composer.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Instrumentation/AwsSdk/_register.php b/src/Instrumentation/AwsSdk/_register.php index b701f8a0c..b0a0dec1d 100644 --- a/src/Instrumentation/AwsSdk/_register.php +++ b/src/Instrumentation/AwsSdk/_register.php @@ -1,4 +1,5 @@ Date: Thu, 22 May 2025 10:54:04 -0700 Subject: [PATCH 08/12] Fixed psalm errors --- src/Instrumentation/AwsSdk/.phan/config.php | 371 ++++++++++++++++++ .../AwsSdk/src/AwsSdkInstrumentation.php | 5 +- .../Integration/AwsSdkInstrumentationTest.php | 1 + 3 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 src/Instrumentation/AwsSdk/.phan/config.php diff --git a/src/Instrumentation/AwsSdk/.phan/config.php b/src/Instrumentation/AwsSdk/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/AwsSdk/.phan/config.php @@ -0,0 +1,371 @@ + '8.0', + + // If enabled, missing properties will be created when + // they are first seen. If false, we'll report an + // error message if there is an attempt to write + // to a class property that wasn't explicitly + // defined. + 'allow_missing_properties' => false, + + // If enabled, null can be cast to any type and any + // type can be cast to null. Setting this to true + // will cut down on false positives. + 'null_casts_as_any_type' => false, + + // If enabled, allow null to be cast as any array-like type. + // + // This is an incremental step in migrating away from `null_casts_as_any_type`. + // If `null_casts_as_any_type` is true, this has no effect. + 'null_casts_as_array' => true, + + // If enabled, allow any array-like type to be cast to null. + // This is an incremental step in migrating away from `null_casts_as_any_type`. + // If `null_casts_as_any_type` is true, this has no effect. + 'array_casts_as_null' => true, + + // If enabled, scalars (int, float, bool, string, null) + // are treated as if they can cast to each other. + // This does not affect checks of array keys. See `scalar_array_key_cast`. + 'scalar_implicit_cast' => false, + + // If enabled, any scalar array keys (int, string) + // are treated as if they can cast to each other. + // E.g. `array` can cast to `array` and vice versa. + // Normally, a scalar type such as int could only cast to/from int and mixed. + 'scalar_array_key_cast' => true, + + // If this has entries, scalars (int, float, bool, string, null) + // are allowed to perform the casts listed. + // + // E.g. `['int' => ['float', 'string'], 'float' => ['int'], 'string' => ['int'], 'null' => ['string']]` + // allows casting null to a string, but not vice versa. + // (subset of `scalar_implicit_cast`) + 'scalar_implicit_partial' => [], + + // If enabled, Phan will warn if **any** type in a method invocation's object + // is definitely not an object, + // or if **any** type in an invoked expression is not a callable. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_method_checking' => false, + + // If enabled, Phan will warn if **any** type of the object expression for a property access + // does not contain that property. + 'strict_object_checking' => false, + + // If enabled, Phan will warn if **any** type in the argument's union type + // cannot be cast to a type in the parameter's expected union type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_param_checking' => false, + + // If enabled, Phan will warn if **any** type in a property assignment's union type + // cannot be cast to a type in the property's declared union type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_property_checking' => false, + + // If enabled, Phan will warn if **any** type in a returned value's union type + // cannot be cast to the declared return type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_return_checking' => false, + + // If true, seemingly undeclared variables in the global + // scope will be ignored. + // + // This is useful for projects with complicated cross-file + // globals that you have no hope of fixing. + 'ignore_undeclared_variables_in_global_scope' => true, + + // Set this to false to emit `PhanUndeclaredFunction` issues for internal functions that Phan has signatures for, + // but aren't available in the codebase, or from Reflection. + // (may lead to false positives if an extension isn't loaded) + // + // If this is true(default), then Phan will not warn. + // + // Even when this is false, Phan will still infer return values and check parameters of internal functions + // if Phan has the signatures. + 'ignore_undeclared_functions_with_known_signatures' => true, + + // Backwards Compatibility Checking. This is slow + // and expensive, but you should consider running + // it before upgrading your version of PHP to a + // new version that has backward compatibility + // breaks. + // + // If you are migrating from PHP 5 to PHP 7, + // you should also look into using + // [php7cc (no longer maintained)](https://github.com/sstalle/php7cc) + // and [php7mar](https://github.com/Alexia/php7mar), + // which have different backwards compatibility checks. + 'backward_compatibility_checks' => false, + + // If true, check to make sure the return type declared + // in the doc-block (if any) matches the return type + // declared in the method signature. + 'check_docblock_signature_return_type_match' => false, + + // If true, make narrowed types from phpdoc params override + // the real types from the signature, when real types exist. + // (E.g. allows specifying desired lists of subclasses, + // or to indicate a preference for non-nullable types over nullable types) + // + // Affects analysis of the body of the method and the param types passed in by callers. + // + // (*Requires `check_docblock_signature_param_type_match` to be true*) + 'prefer_narrowed_phpdoc_param_type' => true, + + // (*Requires `check_docblock_signature_return_type_match` to be true*) + // + // If true, make narrowed types from phpdoc returns override + // the real types from the signature, when real types exist. + // + // (E.g. allows specifying desired lists of subclasses, + // or to indicate a preference for non-nullable types over nullable types) + // + // This setting affects the analysis of return statements in the body of the method and the return types passed in by callers. + 'prefer_narrowed_phpdoc_return_type' => true, + + // If enabled, check all methods that override a + // parent method to make sure its signature is + // compatible with the parent's. + // + // This check can add quite a bit of time to the analysis. + // + // This will also check if final methods are overridden, etc. + 'analyze_signature_compatibility' => true, + + // This setting maps case-insensitive strings to union types. + // + // This is useful if a project uses phpdoc that differs from the phpdoc2 standard. + // + // If the corresponding value is the empty string, + // then Phan will ignore that union type (E.g. can ignore 'the' in `@return the value`) + // + // If the corresponding value is not empty, + // then Phan will act as though it saw the corresponding UnionTypes(s) + // when the keys show up in a UnionType of `@param`, `@return`, `@var`, `@property`, etc. + // + // This matches the **entire string**, not parts of the string. + // (E.g. `@return the|null` will still look for a class with the name `the`, but `@return the` will be ignored with the below setting) + // + // (These are not aliases, this setting is ignored outside of doc comments). + // (Phan does not check if classes with these names exist) + // + // Example setting: `['unknown' => '', 'number' => 'int|float', 'char' => 'string', 'long' => 'int', 'the' => '']` + 'phpdoc_type_mapping' => [], + + // Set to true in order to attempt to detect dead + // (unreferenced) code. Keep in mind that the + // results will only be a guess given that classes, + // properties, constants and methods can be referenced + // as variables (like `$class->$property` or + // `$class->$method()`) in ways that we're unable + // to make sense of. + 'dead_code_detection' => false, + + // Set to true in order to attempt to detect unused variables. + // `dead_code_detection` will also enable unused variable detection. + // + // This has a few known false positives, e.g. for loops or branches. + 'unused_variable_detection' => false, + + // Set to true in order to attempt to detect redundant and impossible conditions. + // + // This has some false positives involving loops, + // variables set in branches of loops, and global variables. + 'redundant_condition_detection' => false, + + // If enabled, Phan will act as though it's certain of real return types of a subset of internal functions, + // even if those return types aren't available in reflection (real types were taken from php 7.3 or 8.0-dev, depending on target_php_version). + // + // Note that with php 7 and earlier, php would return null or false for many internal functions if the argument types or counts were incorrect. + // As a result, enabling this setting with target_php_version 8.0 may result in false positives for `--redundant-condition-detection` when codebases also support php 7.x. + 'assume_real_types_for_internal_functions' => false, + + // If true, this runs a quick version of checks that takes less + // time at the cost of not running as thorough + // of an analysis. You should consider setting this + // to true only when you wish you had more **undiagnosed** issues + // to fix in your code base. + // + // In quick-mode the scanner doesn't rescan a function + // or a method's code block every time a call is seen. + // This means that the problem here won't be detected: + // + // ```php + // false, + + // Enable or disable support for generic templated + // class types. + 'generic_types_enabled' => true, + + // Override to hardcode existence and types of (non-builtin) globals in the global scope. + // Class names should be prefixed with `\`. + // + // (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`) + 'globals_type_map' => [], + + // The minimum severity level to report on. This can be + // set to `Issue::SEVERITY_LOW`, `Issue::SEVERITY_NORMAL` or + // `Issue::SEVERITY_CRITICAL`. Setting it to only + // critical issues is a good place to start on a big + // sloppy mature code base. + 'minimum_severity' => Issue::SEVERITY_LOW, + + // Add any issue types (such as `'PhanUndeclaredMethod'`) + // to this deny-list to inhibit them from being reported. + 'suppress_issue_types' => [], + + // A regular expression to match files to be excluded + // from parsing and analysis and will not be read at all. + // + // This is useful for excluding groups of test or example + // directories/files, unanalyzable files, or files that + // can't be removed for whatever reason. + // (e.g. `'@Test\.php$@'`, or `'@vendor/.*/(tests|Tests)/@'`) + 'exclude_file_regex' => '@^vendor/.*/(tests?|Tests?)/@', + + // A list of files that will be excluded from parsing and analysis + // and will not be read at all. + // + // This is useful for excluding hopelessly unanalyzable + // files that can't be removed for whatever reason. + 'exclude_file_list' => [ + 'vendor/composer/composer/src/Composer/InstalledVersions.php' + ], + + // A directory list that defines files that will be excluded + // from static analysis, but whose class and method + // information should be included. + // + // Generally, you'll want to include the directories for + // third-party code (such as "vendor/") in this list. + // + // n.b.: If you'd like to parse but not analyze 3rd + // party code, directories containing that code + // should be added to the `directory_list` as well as + // to `exclude_analysis_directory_list`. + 'exclude_analysis_directory_list' => [ + 'vendor/', + 'proto/', + 'thrift/' + ], + + // Enable this to enable checks of require/include statements referring to valid paths. + 'enable_include_path_checks' => true, + + // The number of processes to fork off during the analysis + // phase. + 'processes' => 1, + + // List of case-insensitive file extensions supported by Phan. + // (e.g. `['php', 'html', 'htm']`) + 'analyzed_file_extensions' => [ + 'php', + ], + + // You can put paths to stubs of internal extensions in this config option. + // If the corresponding extension is **not** loaded, then Phan will use the stubs instead. + // Phan will continue using its detailed type annotations, + // but load the constants, classes, functions, and classes (and their Reflection types) + // from these stub files (doubling as valid php files). + // Use a different extension from php to avoid accidentally loading these. + // The `tools/make_stubs` script can be used to generate your own stubs (compatible with php 7.0+ right now) + // + // (e.g. `['xdebug' => '.phan/internal_stubs/xdebug.phan_php']`) + 'autoload_internal_extension_signatures' => [], + + // A list of plugin files to execute. + // + // Plugins which are bundled with Phan can be added here by providing their name (e.g. `'AlwaysReturnPlugin'`) + // + // Documentation about available bundled plugins can be found [here](https://github.com/phan/phan/tree/master/.phan/plugins). + // + // Alternately, you can pass in the full path to a PHP file with the plugin's implementation (e.g. `'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'`) + 'plugins' => [ + 'AlwaysReturnPlugin', + 'PregRegexCheckerPlugin', + 'UnreachableCodePlugin', + ], + + // A list of directories that should be parsed for class and + // method information. After excluding the directories + // defined in `exclude_analysis_directory_list`, the remaining + // files will be statically analyzed for errors. + // + // Thus, both first-party and third-party code being used by + // your application should be included in this list. + 'directory_list' => [ + 'src', + 'vendor' + ], + + // A list of individual files to include in analysis + // with a path relative to the root directory of the + // project. + 'file_list' => [], +]; diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php index 0a50b63d9..3ceae8637 100644 --- a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -16,8 +16,10 @@ use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +/** @psalm-suppress UnusedClass */ final class AwsSdkInstrumentation { + /** @psalm-suppress ArgumentTypeCoercion */ public const NAME = 'aws-sdk'; public static function register(): void @@ -32,7 +34,8 @@ public static function register(): void * ② Intercept the low‑level `execute` call that actually * performs the HTTP request and has the Command object. */ - hook( + /** @psalm-suppress UnusedFunctionCall */ + hook( AwsClient::class, 'execute', pre: static function ( diff --git a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php index 95354f51e..6ce033e57 100644 --- a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php +++ b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php @@ -20,6 +20,7 @@ /** * @covers \OpenTelemetry\Contrib\Instrumentation\AwsSdk\AwsSdkInstrumentation */ +/** @psalm-suppress TooManyArguments */ class AwsSdkInstrumentationTest extends TestCase { private S3Client $client; From c24bd829f2bc88dc3f0e9d1d2084495ba72c1e4c Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Thu, 22 May 2025 16:48:31 -0700 Subject: [PATCH 09/12] fixed styling again --- src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php index 3ceae8637..36da24021 100644 --- a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -34,8 +34,8 @@ public static function register(): void * ② Intercept the low‑level `execute` call that actually * performs the HTTP request and has the Command object. */ - /** @psalm-suppress UnusedFunctionCall */ - hook( + /** @psalm-suppress UnusedFunctionCall */ + hook( AwsClient::class, 'execute', pre: static function ( From bfc0335672ab68ba29df1c2d7bfabf08e60709cb Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Thu, 22 May 2025 19:28:23 -0700 Subject: [PATCH 10/12] supress phan errors --- src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php index 36da24021..08e250011 100644 --- a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -75,8 +75,8 @@ public static function register(): void $scope->detach(); if ($result instanceof ResultInterface && isset($result['@metadata'])) { - $span->setAttribute(TraceAttributes::HTTP_RESPONSE_STATUS_CODE, $result['@metadata']['statusCode']); - $span->setAttribute(TraceAttributes::AWS_REQUEST_ID, $result['@metadata']['headers']['x-amz-request-id']); + $span->setAttribute(TraceAttributes::HTTP_RESPONSE_STATUS_CODE, $result['@metadata']['statusCode']); // @phan-suppress-current-line PhanTypeMismatchDimFetch + $span->setAttribute(TraceAttributes::AWS_REQUEST_ID, $result['@metadata']['headers']['x-amz-request-id']); // @phan-suppress-current-line PhanTypeMismatchDimFetch } if ($ex) { if ($ex instanceof AwsException && $ex->getAwsRequestId() !== null) { From 3f94160964c9d6a8912f58029b8458d19dc3f1f8 Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Fri, 23 May 2025 00:17:00 -0700 Subject: [PATCH 11/12] updated unit test to not require credentials --- .../AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php index 6ce033e57..3db769275 100644 --- a/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php +++ b/src/Instrumentation/AwsSdk/tests/Integration/AwsSdkInstrumentationTest.php @@ -53,6 +53,7 @@ public function setUp(): void 'region' => 'us-west-2', 'version' => 'latest', 'handler' => $this->mock, + 'credentials' => false, ]); } From 75e50337b401bf03fe15bac90fbd1066a4547647 Mon Sep 17 00:00:00 2001 From: Mohamed Asaker Date: Fri, 23 May 2025 01:35:03 -0700 Subject: [PATCH 12/12] updated comment messages --- src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php index 08e250011..a1997088d 100644 --- a/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php +++ b/src/Instrumentation/AwsSdk/src/AwsSdkInstrumentation.php @@ -1,6 +1,5 @@