From 2c9e38b5ffc2335d7334509e9c1f5d3d6eed97e4 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 12:24:42 +1100 Subject: [PATCH 01/35] update auto-instrumentation packages to SemConv 1.30.0 --- src/Instrumentation/CakePHP/composer.json | 2 +- .../CakePHP/src/CakePHPInstrumentation.php | 3 ++- .../CakePHP/src/Hooks/Cake/Command/Command.php | 8 +++----- .../CakePHP/src/Hooks/Cake/Controller/Controller.php | 2 +- .../CakePHP/src/Hooks/Cake/Http/Server.php | 2 +- src/Instrumentation/CakePHP/src/Hooks/CakeHookTrait.php | 4 ++-- .../tests/Integration/CakePHPInstrumentationTest.php | 4 ++-- src/Instrumentation/CodeIgniter/composer.json | 2 +- .../CodeIgniter/src/CodeIgniterInstrumentation.php | 9 +++++---- .../tests/Integration/CodeIgniterInstrumentationTest.php | 1 - 10 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Instrumentation/CakePHP/composer.json b/src/Instrumentation/CakePHP/composer.json index 5debc7a5f..e559c368c 100644 --- a/src/Instrumentation/CakePHP/composer.json +++ b/src/Instrumentation/CakePHP/composer.json @@ -13,7 +13,7 @@ "ext-opentelemetry": "*", "cakephp/cakephp": "^4 || ^5", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php b/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php index 9ad4c68c2..347cc5d01 100644 --- a/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php +++ b/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php @@ -8,6 +8,7 @@ use OpenTelemetry\Contrib\Instrumentation\CakePHP\Hooks\Cake\Command\Command; use OpenTelemetry\Contrib\Instrumentation\CakePHP\Hooks\Cake\Controller\Controller; use OpenTelemetry\Contrib\Instrumentation\CakePHP\Hooks\Cake\Http\Server; +use OpenTelemetry\SemConv\Version; class CakePHPInstrumentation { @@ -18,7 +19,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.cakephp', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); Server::hook($instrumentation); Controller::hook($instrumentation); diff --git a/src/Instrumentation/CakePHP/src/Hooks/Cake/Command/Command.php b/src/Instrumentation/CakePHP/src/Hooks/Cake/Command/Command.php index 9838963b1..138cf84eb 100644 --- a/src/Instrumentation/CakePHP/src/Hooks/Cake/Command/Command.php +++ b/src/Instrumentation/CakePHP/src/Hooks/Cake/Command/Command.php @@ -26,10 +26,10 @@ public function instrument(): void $builder = $this->instrumentation ->tracer() ->spanBuilder(sprintf('Command %s', $command->getName() ?: 'unknown')) - ->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); $parent = Context::getCurrent(); $span = $builder->startSpan(); @@ -52,9 +52,7 @@ public function instrument(): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/CakePHP/src/Hooks/Cake/Controller/Controller.php b/src/Instrumentation/CakePHP/src/Hooks/Cake/Controller/Controller.php index 090f53f40..e41acd06d 100644 --- a/src/Instrumentation/CakePHP/src/Hooks/Cake/Controller/Controller.php +++ b/src/Instrumentation/CakePHP/src/Hooks/Cake/Controller/Controller.php @@ -35,7 +35,7 @@ public function instrument(): void $scope->detach(); $span = \OpenTelemetry\API\Trace\Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } $response = $app->getResponse(); diff --git a/src/Instrumentation/CakePHP/src/Hooks/Cake/Http/Server.php b/src/Instrumentation/CakePHP/src/Hooks/Cake/Http/Server.php index c7f05ad87..a90fd38c5 100644 --- a/src/Instrumentation/CakePHP/src/Hooks/Cake/Http/Server.php +++ b/src/Instrumentation/CakePHP/src/Hooks/Cake/Http/Server.php @@ -49,7 +49,7 @@ public function instrument(): void $span->setAttribute(TraceAttributes::HTTP_ROUTE, $route); } if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } if ($response) { diff --git a/src/Instrumentation/CakePHP/src/Hooks/CakeHookTrait.php b/src/Instrumentation/CakePHP/src/Hooks/CakeHookTrait.php index 110efc6f4..cbbb9eb44 100644 --- a/src/Instrumentation/CakePHP/src/Hooks/CakeHookTrait.php +++ b/src/Instrumentation/CakePHP/src/Hooks/CakeHookTrait.php @@ -57,10 +57,10 @@ protected function buildSpan(?ServerRequestInterface $request, string $class, st : sprintf('%s', $request?->getMethod() ?? 'unknown') ) ->setSpanKind(SpanKind::KIND_SERVER) - ->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); $parent = Context::getCurrent(); if (!$root && $request) { $this->isRoot = true; diff --git a/src/Instrumentation/CakePHP/tests/Integration/CakePHPInstrumentationTest.php b/src/Instrumentation/CakePHP/tests/Integration/CakePHPInstrumentationTest.php index bf7468eeb..c64f39fb8 100644 --- a/src/Instrumentation/CakePHP/tests/Integration/CakePHPInstrumentationTest.php +++ b/src/Instrumentation/CakePHP/tests/Integration/CakePHPInstrumentationTest.php @@ -45,7 +45,7 @@ public function test_index(): void $this->assertSame(SpanKind::KIND_SERVER, $serverSpan->getKind()); $this->assertGreaterThan(0, $serverSpan->getAttributes()->count()); $attributes = $serverSpan->getAttributes()->toArray(); - $this->assertSame('run', $attributes['code.function']); + $this->assertSame('run', $attributes['code.function.name']); $this->assertSame('GET', $attributes['http.request.method']); $this->assertSame(200, $attributes['http.response.status_code']); $this->assertSame(self::TRACE_ID, $serverSpan->getParentContext()->getTraceId()); @@ -58,7 +58,7 @@ public function test_index(): void $this->assertSame(SpanKind::KIND_INTERNAL, $controllerSpan->getKind()); $this->assertGreaterThan(0, $controllerSpan->getAttributes()->count()); $attributes = $controllerSpan->getAttributes()->toArray(); - $this->assertSame('invokeAction', $attributes['code.function']); + $this->assertSame('invokeAction', $attributes['code.function.name']); $this->assertSame($serverSpan->getTraceId(), $controllerSpan->getParentContext()->getTraceId()); $this->assertSame($serverSpan->getSpanId(), $controllerSpan->getParentContext()->getSpanId()); } diff --git a/src/Instrumentation/CodeIgniter/composer.json b/src/Instrumentation/CodeIgniter/composer.json index 2e8664707..8053360b6 100644 --- a/src/Instrumentation/CodeIgniter/composer.json +++ b/src/Instrumentation/CodeIgniter/composer.json @@ -13,7 +13,7 @@ "ext-opentelemetry": "*", "codeigniter4/framework": "^4.3", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.50", diff --git a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php index ba8c183d0..3438fc1c8 100644 --- a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php +++ b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php @@ -16,6 +16,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; class CodeIgniterInstrumentation { @@ -26,7 +27,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.codeigniter', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); // The method that creates request/response/controller objects is in the same class as the method @@ -60,10 +61,10 @@ public static function register(): void /** @phan-suppress-next-line PhanDeprecatedFunction */ ->spanBuilder(\sprintf('%s', $request?->getMethod() ?? 'unknown')) ->setSpanKind(SpanKind::KIND_SERVER) - ->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); $parent = Context::getCurrent(); @@ -146,7 +147,7 @@ public static function register(): void } if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/CodeIgniter/tests/Integration/CodeIgniterInstrumentationTest.php b/src/Instrumentation/CodeIgniter/tests/Integration/CodeIgniterInstrumentationTest.php index 9b6692036..5512397f8 100644 --- a/src/Instrumentation/CodeIgniter/tests/Integration/CodeIgniterInstrumentationTest.php +++ b/src/Instrumentation/CodeIgniter/tests/Integration/CodeIgniterInstrumentationTest.php @@ -76,6 +76,5 @@ public function test_exception() $this->assertEquals('Exception', $eventAttributes->get('exception.type')); $this->assertEquals('Threw', $eventAttributes->get('exception.message')); $this->assertNotNull($eventAttributes->get('exception.stacktrace')); - $this->assertTrue($eventAttributes->get('exception.escaped')); } } From 378015d0a144076be26ba3533e2299bcb0bbe0df Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 12:34:45 +1100 Subject: [PATCH 02/35] Curl semconv 1.30 --- src/Instrumentation/Curl/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/Curl/composer.json | 2 +- src/Instrumentation/Curl/phpstan.neon.dist | 5 + src/Instrumentation/Curl/psalm.xml.dist | 7 + .../Curl/src/CurlInstrumentation.php | 14 +- 5 files changed, 391 insertions(+), 8 deletions(-) create mode 100644 src/Instrumentation/Curl/.phan/config.php diff --git a/src/Instrumentation/Curl/.phan/config.php b/src/Instrumentation/Curl/.phan/config.php new file mode 100644 index 000000000..6bf6f35c4 --- /dev/null +++ b/src/Instrumentation/Curl/.phan/config.php @@ -0,0 +1,371 @@ + '8.2', + + // 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/Curl/composer.json b/src/Instrumentation/Curl/composer.json index 3021c7543..441f9f794 100644 --- a/src/Instrumentation/Curl/composer.json +++ b/src/Instrumentation/Curl/composer.json @@ -20,7 +20,7 @@ "ext-curl": "*", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/Curl/phpstan.neon.dist b/src/Instrumentation/Curl/phpstan.neon.dist index ed94c13da..3ecab5902 100644 --- a/src/Instrumentation/Curl/phpstan.neon.dist +++ b/src/Instrumentation/Curl/phpstan.neon.dist @@ -7,3 +7,8 @@ parameters: paths: - src - tests + ignoreErrors: + - + message: "#Right side of .* is always false.#" + paths: + - src/CurlInstrumentation.php diff --git a/src/Instrumentation/Curl/psalm.xml.dist b/src/Instrumentation/Curl/psalm.xml.dist index 5a04b34d7..1a83afc1a 100644 --- a/src/Instrumentation/Curl/psalm.xml.dist +++ b/src/Instrumentation/Curl/psalm.xml.dist @@ -14,4 +14,11 @@ + + + + + + + diff --git a/src/Instrumentation/Curl/src/CurlInstrumentation.php b/src/Instrumentation/Curl/src/CurlInstrumentation.php index 27bef1272..f18475355 100644 --- a/src/Instrumentation/Curl/src/CurlInstrumentation.php +++ b/src/Instrumentation/Curl/src/CurlInstrumentation.php @@ -16,6 +16,7 @@ use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SDK\Common\Configuration\Configuration; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use WeakMap; use WeakReference; @@ -28,7 +29,7 @@ public static function register(): void /** @var WeakMap */ $curlHandleToAttributes = new WeakMap(); - /** @var WeakMap > + /** @var WeakMap $curlMultiToHandle * * curlMultiToHandle -> array('started'=>bool, * 'handles'=> @@ -40,13 +41,12 @@ public static function register(): void */ $curlMultiToHandle = new WeakMap(); - /** @var bool */ $curlSetOptInstrumentationSuppressed = false; $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.curl', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); hook( @@ -149,9 +149,9 @@ public static function register(): void ->spanBuilder($spanName) ->setParent($parent) ->setSpanKind(SpanKind::KIND_CLIENT) - ->setAttribute(TraceAttributes::CODE_FUNCTION, $function) + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) ->setAttribute(TraceAttributes::CODE_FILEPATH, $filename) - ->setAttribute(TraceAttributes::CODE_LINENO, $lineno) + ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno) ->setAttributes($curlHandleToAttributes[$params[0]]->getAttributes()); $span = $builder->startSpan(); @@ -283,7 +283,7 @@ public static function register(): void ->spanBuilder($spanName) ->setParent($parent) ->setSpanKind(SpanKind::KIND_CLIENT) - ->setAttribute(TraceAttributes::CODE_FUNCTION, 'curl_multi_exec') + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, 'curl_multi_exec') ->setAttributes($curlHandleToAttributes[$cHandle]->getAttributes()); $span = $builder->startSpan(); @@ -417,7 +417,7 @@ private static function setAttributesFromCurlGetInfo(CurlHandle $handle, SpanInt $span->setAttribute(TraceAttributes::HTTP_RESPONSE_STATUS_CODE, $value); } if (($value = $info['download_content_length']) > -1) { - $span->setAttribute(TraceAttributes::HTTP_RESPONSE_CONTENT_LENGTH, $value); + $span->setAttribute(TraceAttributes::HTTP_RESPONSE_HEADER . '.content_length', $value); } if (($value = $info['upload_content_length']) > -1) { $span->setAttribute(TraceAttributes::HTTP_REQUEST_BODY_SIZE, $value); From d431d527d100f1efba95d00fdab0aaabe5143945 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 13:38:03 +1100 Subject: [PATCH 03/35] amqp noting semconv recommendations, try to stick to semconv 1.24. Where attributes have been removed, replace with a string --- src/Instrumentation/ExtAmqp/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/ExtAmqp/composer.json | 2 +- .../ExtAmqp/src/ExtAmqpInstrumentation.php | 23 +- .../ExtAmqpInstrumentationTest.php | 7 +- 4 files changed, 391 insertions(+), 12 deletions(-) create mode 100644 src/Instrumentation/ExtAmqp/.phan/config.php diff --git a/src/Instrumentation/ExtAmqp/.phan/config.php b/src/Instrumentation/ExtAmqp/.phan/config.php new file mode 100644 index 000000000..6bf6f35c4 --- /dev/null +++ b/src/Instrumentation/ExtAmqp/.phan/config.php @@ -0,0 +1,371 @@ + '8.2', + + // 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/ExtAmqp/composer.json b/src/Instrumentation/ExtAmqp/composer.json index 3c2918ce2..e1e20dd24 100644 --- a/src/Instrumentation/ExtAmqp/composer.json +++ b/src/Instrumentation/ExtAmqp/composer.json @@ -13,7 +13,7 @@ "ext-amqp": "*", "ext-opentelemetry": "*", "open-telemetry/api": "^1", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php b/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php index 2802163a5..d6fd972ad 100644 --- a/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php +++ b/src/Instrumentation/ExtAmqp/src/ExtAmqpInstrumentation.php @@ -18,6 +18,11 @@ use OpenTelemetry\SemConv\TraceAttributes; use Throwable; +/** + * This uses SemConv 1.24, until messaging SemConv becomes stable. + * @see https://opentelemetry.io/docs/specs/semconv/messaging/rabbitmq/ + * @phan-file-suppress PhanDeprecatedClassConstant + */ final class ExtAmqpInstrumentation { public const NAME = 'ext_amqp'; @@ -57,14 +62,14 @@ public static function register(): void ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, 'amqp') ->setAttribute(TraceAttributes::MESSAGING_OPERATION, 'publish') - ->setAttribute(TraceAttributes::MESSAGING_DESTINATION, $routingKey) + ->setAttribute('messaging.destination', $routingKey) ->setAttribute(TraceAttributes::MESSAGING_DESTINATION_NAME, $routingKey) - ->setAttribute(TraceAttributes::MESSAGING_DESTINATION_PUBLISH_NAME, sprintf('%s%s', $exchange->getName() != '' ? $exchange->getName() . ' ': '', $routingKey)) + ->setAttribute('messaging.destination_publish.name', sprintf('%s%s', $exchange->getName() != '' ? $exchange->getName() . ' ': '', $routingKey)) - ->setAttribute(TraceAttributes::MESSAGING_DESTINATION_KIND, $exchange->getType() !== '' ? $exchange->getType() : 'unknown') + ->setAttribute('messaging.destination.kind', $exchange->getType() !== '' ? $exchange->getType() : 'unknown') - ->setAttribute(TraceAttributes::MESSAGING_RABBITMQ_ROUTING_KEY, $routingKey) - ->setAttribute(TraceAttributes::MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY, $routingKey) + ->setAttribute('messaging.rabbitmq.routing.key', $routingKey) + ->setAttribute('messaging.rabbitmq.destination.routing.key', $routingKey) // network ->setAttribute(TraceAttributes::NET_PROTOCOL_NAME, 'amqp') @@ -170,11 +175,11 @@ protected static function createInteractionWithQueueSpan(CachedInstrumentation $ ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, 'amqp') ->setAttribute(TraceAttributes::MESSAGING_OPERATION, $method) - ->setAttribute(TraceAttributes::MESSAGING_DESTINATION_KIND, 'queue') + ->setAttribute('messaging.destination.kind', 'queue') - ->setAttribute(TraceAttributes::MESSAGING_RABBITMQ_ROUTING_KEY, $queueName) - ->setAttribute(TraceAttributes::MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY, $queueName) - ->setAttribute(TraceAttributes::MESSAGING_DESTINATION_PUBLISH_NAME, $queueName) + ->setAttribute('messaging.rabbitmq.routing.key', $queueName) + ->setAttribute('messaging.rabbitmq.destination.routing_key', $queueName) + ->setAttribute('messaging.destination_publish.name', $queueName) ->setAttribute(TraceAttributes::MESSAGING_CLIENT_ID, $queue->getConsumerTag()) diff --git a/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php b/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php index 02d85c4fa..f92b70f14 100644 --- a/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php +++ b/src/Instrumentation/ExtAmqp/tests/Integration/ExtAmqpInstrumentationTest.php @@ -59,7 +59,7 @@ public function test_rabbit_basic_publish_without_args_works(): void $this->assertEquals('amqp', $span->getAttributes()->get(TraceAttributes::MESSAGING_SYSTEM)); $this->assertEquals(SpanKind::KIND_PRODUCER, $span->getKind()); $this->assertEquals('test_exchange ' . $routing_key, $span->getAttributes()->get(TraceAttributes::MESSAGING_DESTINATION_PUBLISH_NAME)); - $this->assertEquals('topic', $span->getAttributes()->get(TraceAttributes::MESSAGING_DESTINATION_KIND)); + $this->assertEquals('topic', $span->getAttributes()->get('messaging.destination.kind')); /** * Our message should be the first one in the queue @@ -93,7 +93,7 @@ public function test_rabbit_basic_publish(string $messageInteraction): void $this->assertEquals('amqp', $publishSpan->getAttributes()->get(TraceAttributes::MESSAGING_SYSTEM)); $this->assertEquals(SpanKind::KIND_PRODUCER, $publishSpan->getKind()); $this->assertEquals('test_exchange ' . $routing_key, $publishSpan->getAttributes()->get(TraceAttributes::MESSAGING_DESTINATION_PUBLISH_NAME)); - $this->assertEquals('topic', $publishSpan->getAttributes()->get(TraceAttributes::MESSAGING_DESTINATION_KIND)); + $this->assertEquals('topic', $publishSpan->getAttributes()->get('messaging.destination.kind')); /** * Our message should be the first one in the queue @@ -125,6 +125,9 @@ public function getRabbitMessageInteractions(): array ]; } + /** + * @psalm-suppress PossiblyNullArgument + */ protected function setUpQueue() { $routing_key = uniqid('test_queue_', true); From 85c1a2dfd671c17418dd2f2751940dfa710efba2 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 13:59:07 +1100 Subject: [PATCH 04/35] rdkafka --- .../ExtRdKafka/.phan/config.php | 2 +- src/Instrumentation/ExtRdKafka/composer.json | 2 +- .../src/ExtRdKafkaInstrumentation.php | 19 ++++++++++--------- .../ExtRdKafkaInstrumentationTest.php | 6 +++--- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/Instrumentation/ExtRdKafka/.phan/config.php b/src/Instrumentation/ExtRdKafka/.phan/config.php index da2ac2d99..6bf6f35c4 100644 --- a/src/Instrumentation/ExtRdKafka/.phan/config.php +++ b/src/Instrumentation/ExtRdKafka/.phan/config.php @@ -42,7 +42,7 @@ // // Note that the **only** effect of choosing `'5.6'` is to infer that functions removed in php 7.0 exist. // (See `backward_compatibility_checks` for additional options) - 'target_php_version' => '8.0', + 'target_php_version' => '8.2', // If enabled, missing properties will be created when // they are first seen. If false, we'll report an diff --git a/src/Instrumentation/ExtRdKafka/composer.json b/src/Instrumentation/ExtRdKafka/composer.json index 0c23c0450..152f79261 100644 --- a/src/Instrumentation/ExtRdKafka/composer.json +++ b/src/Instrumentation/ExtRdKafka/composer.json @@ -13,7 +13,7 @@ "ext-rdkafka": "*", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "composer-runtime-api": "^2.0" }, "require-dev": { diff --git a/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php b/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php index 72104d5da..98afb317d 100644 --- a/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php +++ b/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php @@ -12,9 +12,10 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; - use OpenTelemetry\SemConv\TraceAttributeValues; +use OpenTelemetry\SemConv\Version; + use RdKafka\KafkaConsumer; use RdKafka\Message; use RdKafka\ProducerTopic; @@ -29,7 +30,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.ext_rdkafka', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-ext-rdkafka'), - 'https://opentelemetry.io/schemas/1.25.0', + Version::VERSION_1_30_0->url(), ); // Start root span and propagate parent if it exists in headers, for each message consumed @@ -74,14 +75,14 @@ private static function addProductionHooks($instrumentation) /** @var CachedInstrumentation $instrumentation */ $builder = $instrumentation ->tracer() - ->spanBuilder(sprintf('%s %s', $exchange->getName(), TraceAttributeValues::MESSAGING_OPERATION_PUBLISH)) + ->spanBuilder(sprintf('%s %s', $exchange->getName(), TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND)) ->setSpanKind(SpanKind::KIND_PRODUCER) - ->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) ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, TraceAttributeValues::MESSAGING_SYSTEM_KAFKA) - ->setAttribute(TraceAttributes::MESSAGING_OPERATION, TraceAttributeValues::MESSAGING_OPERATION_PUBLISH) + ->setAttribute(TraceAttributes::MESSAGING_OPERATION_TYPE, TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND) ; $parent = Context::getCurrent(); @@ -147,12 +148,12 @@ private static function addConsumeHooks($instrumentation) $builder = $instrumentation ->tracer() // @phan-suppress-next-line PhanTypeMismatchArgumentInternal - Doesn't seem to know this has to be a string - ->spanBuilder(sprintf('%s %s', $message->topic_name, TraceAttributeValues::MESSAGING_OPERATION_DELIVER)) + ->spanBuilder(sprintf('%s %s', $message->topic_name, TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND)) ->setSpanKind(SpanKind::KIND_CONSUMER) ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, TraceAttributeValues::MESSAGING_SYSTEM_KAFKA) - ->setAttribute(TraceAttributes::MESSAGING_OPERATION, TraceAttributeValues::MESSAGING_OPERATION_DELIVER) + ->setAttribute(TraceAttributes::MESSAGING_OPERATION_TYPE, TraceAttributeValues::MESSAGING_OPERATION_TYPE_PROCESS) ->setAttribute(TraceAttributes::MESSAGING_KAFKA_MESSAGE_KEY, $message->key) - ->setAttribute(TraceAttributes::MESSAGING_KAFKA_MESSAGE_OFFSET, $message->offset) + ->setAttribute(TraceAttributes::MESSAGING_KAFKA_OFFSET, $message->offset) ; if (is_array($message->headers)) { diff --git a/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php b/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php index 55e0bac25..8de199d79 100644 --- a/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php +++ b/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php @@ -62,7 +62,7 @@ public function test_consume_creates_new_span(): void $this->assertCount(1, $this->storage); /** @var ImmutableSpan $span */ $span = $this->storage->offsetGet(0); - $this->assertEquals('test process', $span->getName()); + $this->assertEquals('test send', $span->getName()); } public function test_context_propagated_on_consumption(): void @@ -91,7 +91,7 @@ public function test_context_propagated_on_consumption(): void $this->assertCount(3, $this->storage); /** @var ImmutableSpan $span */ $span = $this->storage->offsetGet(2); - $this->assertEquals('test process', $span->getName()); + $this->assertEquals('test send', $span->getName()); $this->assertEquals($expectedTraceId, $span->getContext()->getTraceId()); } @@ -130,7 +130,7 @@ public function test_produce_creates_new_span() $this->assertCount(1, $this->storage); $span = $this->storage->offsetGet(0); - $this->assertEquals('test publish', $span->getName()); + $this->assertEquals('test send', $span->getName()); } private function produceMessage( From 9380eabf2500996cec20b30b9abf910964abfc50 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 14:02:26 +1100 Subject: [PATCH 05/35] guzzle --- src/Instrumentation/Guzzle/composer.json | 2 +- .../Guzzle/src/GuzzleInstrumentation.php | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Instrumentation/Guzzle/composer.json b/src/Instrumentation/Guzzle/composer.json index f6db43b41..a9edb66c9 100644 --- a/src/Instrumentation/Guzzle/composer.json +++ b/src/Instrumentation/Guzzle/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "guzzlehttp/guzzle": "^7" }, "require-dev": { diff --git a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php index e258153c6..44b6f6232 100644 --- a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php +++ b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php @@ -15,6 +15,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use function sprintf; @@ -31,7 +32,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.guzzle', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); hook( @@ -58,10 +59,10 @@ public static function register(): void ->setAttribute(TraceAttributes::SERVER_ADDRESS, $request->getUri()->getHost()) ->setAttribute(TraceAttributes::SERVER_PORT, $request->getUri()->getPort()) ->setAttribute(TraceAttributes::URL_PATH, $request->getUri()->getPath()) - ->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) ; foreach ($propagator->fields() as $field) { @@ -94,7 +95,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); $span->end(); } @@ -119,7 +120,7 @@ public static function register(): void return $response; }, onRejected: function (\Throwable $t) use ($span) { - $span->recordException($t, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($t); $span->setStatus(StatusCode::STATUS_ERROR, $t->getMessage()); $span->end(); From f47fdf0fc91c9d204e75ecd57c4dc7f1a4f35e6c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 14:05:51 +1100 Subject: [PATCH 06/35] HttpAsyncClient --- src/Instrumentation/HttpAsyncClient/composer.json | 2 +- .../src/HttpAsyncClientInstrumentation.php | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Instrumentation/HttpAsyncClient/composer.json b/src/Instrumentation/HttpAsyncClient/composer.json index eaab6a1cc..4635cf403 100644 --- a/src/Instrumentation/HttpAsyncClient/composer.json +++ b/src/Instrumentation/HttpAsyncClient/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "php-http/httplug": "^2" }, "autoload": { diff --git a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php index 33939f656..10363dac3 100644 --- a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php +++ b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php @@ -14,6 +14,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Throwable; @@ -24,7 +25,10 @@ class HttpAsyncClientInstrumentation public static function register(): void { - $instrumentation = new CachedInstrumentation('io.opentelemetry.contrib.php.http-async-client', schemaUrl: TraceAttributes::SCHEMA_URL); + $instrumentation = new CachedInstrumentation( + 'io.opentelemetry.contrib.php.http-async-client', + schemaUrl: Version::VERSION_1_30_0->url() + ); hook( HttpAsyncClient::class, @@ -53,10 +57,10 @@ public static function register(): void ->setAttribute(TraceAttributes::HTTP_REQUEST_BODY_SIZE, $request->getHeaderLine('Content-Length')) ->setAttribute(TraceAttributes::SERVER_ADDRESS, $request->getUri()->getHost()) ->setAttribute(TraceAttributes::SERVER_PORT, $request->getUri()->getPort()) - ->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) ; foreach ($propagator->fields() as $field) { @@ -89,7 +93,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); $span->end(); } @@ -114,7 +118,7 @@ public static function register(): void return $response; }, onRejected: function (\Throwable $t) use ($span) { - $span->recordException($t, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($t); $span->setStatus(StatusCode::STATUS_ERROR, $t->getMessage()); $span->end(); From 5a290225d8a940d1ca65c265a16aae4760cd0c6c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 14:09:22 +1100 Subject: [PATCH 07/35] io --- src/Instrumentation/IO/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/IO/composer.json | 3 +- .../IO/src/IOInstrumentation.php | 9 +- 3 files changed, 378 insertions(+), 5 deletions(-) create mode 100644 src/Instrumentation/IO/.phan/config.php diff --git a/src/Instrumentation/IO/.phan/config.php b/src/Instrumentation/IO/.phan/config.php new file mode 100644 index 000000000..6bf6f35c4 --- /dev/null +++ b/src/Instrumentation/IO/.phan/config.php @@ -0,0 +1,371 @@ + '8.2', + + // 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/IO/composer.json b/src/Instrumentation/IO/composer.json index 344d5825e..54182a66a 100644 --- a/src/Instrumentation/IO/composer.json +++ b/src/Instrumentation/IO/composer.json @@ -7,11 +7,12 @@ "readme": "./README.md", "license": "Apache-2.0", "minimum-stability": "dev", + "prefer-stable": true, "require": { "php": "^8.2", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/IO/src/IOInstrumentation.php b/src/Instrumentation/IO/src/IOInstrumentation.php index 44496c38c..106ae7f9e 100644 --- a/src/Instrumentation/IO/src/IOInstrumentation.php +++ b/src/Instrumentation/IO/src/IOInstrumentation.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Throwable; class IOInstrumentation @@ -22,7 +23,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.io', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); self::_hook($instrumentation, null, 'fopen', 'fopen'); @@ -67,9 +68,9 @@ private static function makeBuilder( /** @psalm-suppress ArgumentTypeCoercion */ return $instrumentation->tracer() ->spanBuilder($name) - ->setAttribute(TraceAttributes::CODE_FUNCTION, $function) + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) ->setAttribute(TraceAttributes::CODE_FILEPATH, $filename) - ->setAttribute(TraceAttributes::CODE_LINENO, $lineno); + ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno); } private static function end(?Throwable $exception): void { @@ -80,7 +81,7 @@ private static function end(?Throwable $exception): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From f99a06fa4d5fbf9c81339b123619d9d39f544d35 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 14:33:31 +1100 Subject: [PATCH 08/35] laravel --- src/Instrumentation/Laravel/composer.json | 2 +- .../Laravel/src/Hooks/Illuminate/Console/Command.php | 4 ++-- .../Hooks/Illuminate/Contracts/Console/Kernel.php | 4 ++-- .../src/Hooks/Illuminate/Contracts/Http/Kernel.php | 4 ++-- .../src/Hooks/Illuminate/Contracts/Queue/Queue.php | 12 ++++++------ .../Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php | 4 ++-- .../Laravel/src/Hooks/Illuminate/Queue/Worker.php | 2 +- .../Laravel/src/Hooks/PostHookTrait.php | 5 +---- .../Laravel/src/LaravelInstrumentation.php | 3 ++- .../Laravel/src/Watchers/ExceptionWatcher.php | 3 +-- .../Laravel/src/Watchers/LogWatcher.php | 4 ++-- .../Laravel/src/Watchers/QueryWatcher.php | 10 +++++----- .../Watchers/RedisCommand/RedisCommandWatcher.php | 8 ++++---- .../Laravel/src/Watchers/RedisCommand/Serializer.php | 2 +- .../tests/Integration/LaravelInstrumentationTest.php | 8 ++++---- .../Laravel/tests/Integration/Queue/QueueTest.php | 4 ++-- 16 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/Instrumentation/Laravel/composer.json b/src/Instrumentation/Laravel/composer.json index 65372b3b1..bc5ba619f 100644 --- a/src/Instrumentation/Laravel/composer.json +++ b/src/Instrumentation/Laravel/composer.json @@ -14,7 +14,7 @@ "ext-opentelemetry": "*", "laravel/framework": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.50", diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php index d45153904..171626c24 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Console/Command.php @@ -34,10 +34,10 @@ protected function hookExecute(): bool $builder = $this->instrumentation ->tracer() ->spanBuilder(sprintf('Command %s', $command->getName() ?: 'unknown')) - ->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); $parent = Context::getCurrent(); $span = $builder->startSpan(); 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 edf961f91..70f23ef05 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php @@ -43,10 +43,10 @@ private function hookHandle(): bool ->tracer() ->spanBuilder('Artisan handler') ->setSpanKind(SpanKind::KIND_PRODUCER) - ->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); $parent = Context::getCurrent(); $span = $builder->startSpan(); 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 b5415cc23..0a0bc54ed 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php @@ -45,10 +45,10 @@ protected function hookHandle(): bool ->tracer() ->spanBuilder(sprintf('%s', $request?->method() ?? 'unknown')) ->setSpanKind(SpanKind::KIND_SERVER) - ->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); $parent = Context::getCurrent(); if ($request) { /** @phan-suppress-next-line PhanAccessMethodInternal */ 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 c58800db9..531099b0a 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php @@ -38,10 +38,10 @@ protected function hookBulk(): bool 'bulk', pre: function (QueueContract $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) { $attributes = array_merge([ - TraceAttributes::CODE_FUNCTION => $function, + TraceAttributes::CODE_FUNCTION_NAME => $function, TraceAttributes::CODE_NAMESPACE => $class, TraceAttributes::CODE_FILEPATH => $filename, - TraceAttributes::CODE_LINENO => $lineno, + TraceAttributes::CODE_LINE_NUMBER => $lineno, TraceAttributes::MESSAGING_BATCH_MESSAGE_COUNT => count($params[0] ?? []), ], $this->contextualMessageSystemAttributes($queue, [])); @@ -51,7 +51,7 @@ protected function hookBulk(): bool ->spanBuilder(vsprintf('%s %s', [ /** @phan-suppress-next-line PhanUndeclaredMethod */ method_exists($queue, 'getQueue') ? $queue->getQueue($params[2] ?? null) : $queue->getConnectionName(), - TraceAttributeValues::MESSAGING_OPERATION_PUBLISH, + TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND, ])) ->setSpanKind(SpanKind::KIND_PRODUCER) ->setAttributes($attributes) @@ -81,10 +81,10 @@ protected function hookLater(): bool }; $attributes = [ - TraceAttributes::CODE_FUNCTION => $function, + TraceAttributes::CODE_FUNCTION_NAME => $function, TraceAttributes::CODE_NAMESPACE => $class, TraceAttributes::CODE_FILEPATH => $filename, - TraceAttributes::CODE_LINENO => $lineno, + TraceAttributes::CODE_LINE_NUMBER => $lineno, 'messaging.message.delivery_timestamp' => $estimateDeliveryTimestamp, ]; @@ -125,7 +125,7 @@ protected function hookPushRaw(): bool ->tracer() ->spanBuilder(vsprintf('%s %s', [ $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], - TraceAttributeValues::MESSAGING_OPERATION_CREATE, + TraceAttributeValues::MESSAGING_OPERATION_TYPE_CREATE, ])) ->setSpanKind(SpanKind::KIND_PRODUCER) ->setAttributes($attributes) diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php index 19d85cc2e..ed21dadba 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php @@ -40,10 +40,10 @@ protected function hookPush(): bool ])) ->setSpanKind(SpanKind::KIND_INTERNAL) ->setAttributes([ - TraceAttributes::CODE_FUNCTION => $function, + TraceAttributes::CODE_FUNCTION_NAME => $function, TraceAttributes::CODE_NAMESPACE => $class, TraceAttributes::CODE_FILEPATH => $filename, - TraceAttributes::CODE_LINENO => $lineno, + TraceAttributes::CODE_LINE_NUMBER => $lineno, ]) ->startSpan(); diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php index 0e295a690..2e7ef69a4 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php @@ -99,7 +99,7 @@ private function hookWorkerGetNextJob(): bool ->tracer() ->spanBuilder(vsprintf('%s %s', [ $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], - TraceAttributeValues::MESSAGING_OPERATION_RECEIVE, + TraceAttributeValues::MESSAGING_OPERATION_TYPE_RECEIVE, ])) ->setSpanKind(SpanKind::KIND_CONSUMER) ->setAttributes($attributes) diff --git a/src/Instrumentation/Laravel/src/Hooks/PostHookTrait.php b/src/Instrumentation/Laravel/src/Hooks/PostHookTrait.php index bd1e5a367..fa9c06ca7 100644 --- a/src/Instrumentation/Laravel/src/Hooks/PostHookTrait.php +++ b/src/Instrumentation/Laravel/src/Hooks/PostHookTrait.php @@ -7,7 +7,6 @@ use OpenTelemetry\API\Trace\Span; use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\Context; -use OpenTelemetry\SemConv\TraceAttributes; use Throwable; trait PostHookTrait @@ -23,9 +22,7 @@ private function endSpan(?Throwable $exception = null): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php index c49dcde3e..3e2d52154 100644 --- a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php +++ b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php @@ -6,6 +6,7 @@ use OpenTelemetry\API\Instrumentation\CachedInstrumentation; use OpenTelemetry\SDK\Common\Configuration\Configuration; +use OpenTelemetry\SemConv\Version; class LaravelInstrumentation { @@ -16,7 +17,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.laravel', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); Hooks\Illuminate\Console\Command::hook($instrumentation); diff --git a/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php b/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php index 7bbb2bdd4..176575a26 100644 --- a/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/ExceptionWatcher.php @@ -9,7 +9,6 @@ use OpenTelemetry\API\Trace\Span; use OpenTelemetry\API\Trace\StatusCode; use OpenTelemetry\Context\Context; -use OpenTelemetry\SemConv\TraceAttributes; use Throwable; class ExceptionWatcher extends Watcher @@ -37,7 +36,7 @@ public function recordException(MessageLogged $log): void return; } $span = Span::fromContext($scope->context()); - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } } diff --git a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php index 7adcddd92..4b6e9eb9a 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 @@ -58,7 +58,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 ff1c82d50..cfd438096 100644 --- a/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php @@ -44,13 +44,13 @@ public function recordQuery(QueryExecuted $query): void ->startSpan(); $attributes = [ - TraceAttributes::DB_SYSTEM => $query->connection->getDriverName(), - TraceAttributes::DB_NAME => $query->connection->getDatabaseName(), - TraceAttributes::DB_OPERATION => $operationName, - TraceAttributes::DB_USER => $query->connection->getConfig('username'), + TraceAttributes::DB_SYSTEM_NAME => $query->connection->getDriverName(), + TraceAttributes::DB_NAMESPACE => $query->connection->getDatabaseName(), + TraceAttributes::DB_OPERATION_NAME => $operationName, + //TraceAttributes::DB_USER => $query->connection->getConfig('username'), ]; - $attributes[TraceAttributes::DB_STATEMENT] = $query->sql; + $attributes[TraceAttributes::DB_QUERY_TEXT] = $query->sql; /** @psalm-suppress PossiblyInvalidArgument */ $span->setAttributes($attributes); $span->end($nowInNs); diff --git a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php index 6e798d4e5..31de0a2b5 100644 --- a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php @@ -54,10 +54,10 @@ public function recordRedisCommand(CommandExecuted $event): void // See https://opentelemetry.io/docs/specs/semconv/database/redis/ $attributes = [ - TraceAttributes::DB_SYSTEM => TraceAttributeValues::DB_SYSTEM_REDIS, - TraceAttributes::DB_NAME => $this->fetchDbIndex($event->connection), - TraceAttributes::DB_OPERATION => $operationName, - TraceAttributes::DB_STATEMENT => Serializer::serializeCommand($event->command, $event->parameters), + TraceAttributes::DB_SYSTEM_NAME => TraceAttributeValues::DB_SYSTEM_REDIS, + TraceAttributes::DB_NAMESPACE => $this->fetchDbIndex($event->connection), + TraceAttributes::DB_OPERATION_NAME => $operationName, + TraceAttributes::DB_QUERY_TEXT => Serializer::serializeCommand($event->command, $event->parameters), TraceAttributes::SERVER_ADDRESS => $this->fetchDbHost($event->connection), ]; diff --git a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/Serializer.php b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/Serializer.php index a64c40813..e15b4db6f 100644 --- a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/Serializer.php +++ b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/Serializer.php @@ -70,7 +70,7 @@ public static function serializeCommand(string $command, array $params): string } // In some cases (for example when using LUA scripts) arrays are valid parameters - $paramsToSerialize = array_map(function($param) { return is_array($param) ? json_encode($param) : $param; }, $paramsToSerialize); + $paramsToSerialize = array_map(function ($param) { return is_array($param) ? json_encode($param) : $param; }, $paramsToSerialize); return $command . ' ' . implode(' ', $paramsToSerialize); } diff --git a/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php b/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php index c5096ff3e..8f9bd1355 100644 --- a/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/LaravelInstrumentationTest.php @@ -58,10 +58,10 @@ public function test_cache_log_db(): void $span = $this->storage[1]; $this->assertSame('sql SELECT', $span->getName()); - $this->assertSame('SELECT', $span->getAttributes()->get('db.operation')); - $this->assertSame(':memory:', $span->getAttributes()->get('db.name')); - $this->assertSame('select 1', $span->getAttributes()->get('db.statement')); - $this->assertSame('sqlite', $span->getAttributes()->get('db.system')); + $this->assertSame('SELECT', $span->getAttributes()->get('db.operation.name')); + $this->assertSame(':memory:', $span->getAttributes()->get('db.namespace')); + $this->assertSame('select 1', $span->getAttributes()->get('db.query.text')); + $this->assertSame('sqlite', $span->getAttributes()->get('db.system.name')); /** @var \OpenTelemetry\SDK\Logs\ReadWriteLogRecord $logRecord */ $logRecord = $this->storage[0]; diff --git a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php index 1d902e0b7..c4584a071 100644 --- a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php @@ -86,7 +86,7 @@ public function test_it_can_publish_in_bulk(): void /** @psalm-suppress PossiblyUndefinedMethod */ $mockQueue->bulk($jobs); - $this->assertEquals('dummy-queue publish', $this->storage[0]->getName()); + $this->assertEquals('dummy-queue send', $this->storage[0]->getName()); $this->assertEquals(10, $this->storage[0]->getAttributes()->get(TraceAttributes::MESSAGING_BATCH_MESSAGE_COUNT)); } @@ -107,7 +107,7 @@ public function test_it_can_create_with_redis(): void new DummyJob('B'), ]); - $this->assertEquals('queues:default publish', $this->storage[0]->getName()); + $this->assertEquals('queues:default send', $this->storage[0]->getName()); $this->assertEquals(2, $this->storage[0]->getAttributes()->get(TraceAttributes::MESSAGING_BATCH_MESSAGE_COUNT)); $this->assertEquals('redis', $this->storage[0]->getAttributes()->get(TraceAttributes::MESSAGING_SYSTEM)); } From 9d29682a4ee36d4738b1a467af744708a717952b Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 15:00:04 +1100 Subject: [PATCH 09/35] mongodb --- src/Instrumentation/MongoDB/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/MongoDB/composer.json | 4 +- .../MongoDB/src/MongoDBInstrumentation.php | 9 +- .../src/MongoDBInstrumentationSubscriber.php | 26 +- .../MongoDBInstrumentationTest.php | 8 +- 5 files changed, 396 insertions(+), 22 deletions(-) create mode 100644 src/Instrumentation/MongoDB/.phan/config.php diff --git a/src/Instrumentation/MongoDB/.phan/config.php b/src/Instrumentation/MongoDB/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/MongoDB/.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/MongoDB/composer.json b/src/Instrumentation/MongoDB/composer.json index df7c245b8..24810b7ce 100644 --- a/src/Instrumentation/MongoDB/composer.json +++ b/src/Instrumentation/MongoDB/composer.json @@ -7,12 +7,12 @@ "readme": "./README.md", "license": "Apache-2.0", "require": { - "php": ">=7.4", + "php": ">=8.0", "ext-mongodb": "^1.13", "ext-json": "*", "mongodb/mongodb": "^1.15", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php b/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php index 7400da50e..a8dc4ec5c 100644 --- a/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php +++ b/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php @@ -6,20 +6,21 @@ use function MongoDB\Driver\Monitoring\addSubscriber; use OpenTelemetry\API\Instrumentation\CachedInstrumentation; +use OpenTelemetry\SemConv\Version; final class MongoDBInstrumentation { public const NAME = 'mongodb'; /** - * @param callable(object):?string $commandSerializer + * @param ?callable(object):string $commandSerializer */ - public static function register(callable $commandSerializer = null): void + public static function register(?callable $commandSerializer = null): void { $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.mongodb', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); $commandSerializer ??= self::defaultCommandSerializer(); /** @psalm-suppress UnusedFunctionCall */ @@ -27,7 +28,7 @@ public static function register(callable $commandSerializer = null): void } /** - * @return callable(object):?string + * @return callable(object): string */ private static function defaultCommandSerializer(): callable { diff --git a/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php b/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php index b94f6cddd..8add3f2c0 100644 --- a/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php +++ b/src/Instrumentation/MongoDB/src/MongoDBInstrumentationSubscriber.php @@ -28,11 +28,14 @@ use OpenTelemetry\SemConv\TraceAttributes; use Throwable; +/** + * @phan-file-suppress PhanTypeMismatchDeclaredParamNullable + */ final class MongoDBInstrumentationSubscriber implements CommandSubscriber, SDAMSubscriber { private CachedInstrumentation $instrumentation; /** - * @var Closure(object):?string + * @var Closure(object): string */ private Closure $commandSerializer; /** @@ -41,22 +44,23 @@ final class MongoDBInstrumentationSubscriber implements CommandSubscriber, SDAMS private array $serverAttributes = []; /** - * @param (callable(object):?string) $commandSerializer + * @param callable(object):string $commandSerializer */ public function __construct(CachedInstrumentation $instrumentation, callable $commandSerializer) { $this->instrumentation = $instrumentation; - $this->commandSerializer = static function (object $command) use ($commandSerializer): ?string { + $this->commandSerializer = static function (object $command) use ($commandSerializer): string { try { return $commandSerializer($command); } catch (Throwable $exception) { - return null; + return ''; } }; } /** * @psalm-suppress MixedAssignment,MixedArrayTypeCoercion,MixedArrayOffset,MixedArgument + * @phan-suppress PhanDeprecatedFunctionInternal */ public function commandStarted(CommandStartedEvent $event): void { @@ -81,14 +85,14 @@ public function commandStarted(CommandStartedEvent $event): void $builder = self::startSpan($this->instrumentation, 'MongoDB ' . $scopedCommand) ->setSpanKind(SpanKind::KIND_CLIENT) - ->setAttribute(TraceAttributes::DB_SYSTEM, 'mongodb') - ->setAttribute(TraceAttributes::DB_NAME, $databaseName) - ->setAttribute(TraceAttributes::DB_OPERATION, $commandName) + ->setAttribute(TraceAttributes::DB_SYSTEM_NAME, 'mongodb') + ->setAttribute(TraceAttributes::DB_NAMESPACE, $databaseName) + ->setAttribute(TraceAttributes::DB_OPERATION_NAME, $commandName) ->setAttribute(TraceAttributes::SERVER_ADDRESS, $isSocket ? null : $host) ->setAttribute(TraceAttributes::SERVER_PORT, $isSocket ? null : $port) ->setAttribute(TraceAttributes::NETWORK_TRANSPORT, $isSocket ? 'unix' : 'tcp') - ->setAttribute(TraceAttributes::DB_STATEMENT, ($this->commandSerializer)($command)) - ->setAttribute(TraceAttributes::DB_MONGODB_COLLECTION, $collectionName) + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, ($this->commandSerializer)($command)) + ->setAttribute(TraceAttributes::DB_COLLECTION_NAME, $collectionName) ->setAttribute(MongoDBTraceAttributes::DB_MONGODB_REQUEST_ID, $event->getRequestId()) ->setAttribute(MongoDBTraceAttributes::DB_MONGODB_OPERATION_ID, $event->getOperationId()) ->setAttributes($attributes) @@ -127,9 +131,7 @@ private static function endSpan(?Throwable $exception = null): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/MongoDB/tests/Integration/MongoDBInstrumentationTest.php b/src/Instrumentation/MongoDB/tests/Integration/MongoDBInstrumentationTest.php index 6675495a7..692191e51 100644 --- a/src/Instrumentation/MongoDB/tests/Integration/MongoDBInstrumentationTest.php +++ b/src/Instrumentation/MongoDB/tests/Integration/MongoDBInstrumentationTest.php @@ -69,10 +69,10 @@ public function test_mongodb_find_one(): void self::assertSame('MongoDB coll.find', $this->span->getName()); self::assertSame(SpanKind::KIND_CLIENT, $this->span->getKind()); $attributes = $this->span->getAttributes(); - self::assertSame('mongodb', $attributes->get(TraceAttributes::DB_SYSTEM)); - self::assertSame(self::DATABASE_NAME, $attributes->get(TraceAttributes::DB_NAME)); - self::assertSame('find', $attributes->get(TraceAttributes::DB_OPERATION)); - self::assertSame(self::COLLECTION_NAME, $attributes->get(TraceAttributes::DB_MONGODB_COLLECTION)); + self::assertSame('mongodb', $attributes->get(TraceAttributes::DB_SYSTEM_NAME)); + self::assertSame(self::DATABASE_NAME, $attributes->get(TraceAttributes::DB_NAMESPACE)); + self::assertSame('find', $attributes->get(TraceAttributes::DB_OPERATION_NAME)); + self::assertSame(self::COLLECTION_NAME, $attributes->get(TraceAttributes::DB_COLLECTION_NAME)); self::assertSame($this->host, $attributes->get(TraceAttributes::SERVER_ADDRESS)); self::assertSame($this->port, $attributes->get(TraceAttributes::SERVER_PORT)); self::assertSame('tcp', $attributes->get(TraceAttributes::NETWORK_TRANSPORT)); From 8353a5bddb433a1bddc4a07caca8d11e8ea525ed Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 15:26:59 +1100 Subject: [PATCH 10/35] mysqli --- src/Instrumentation/MySqli/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/MySqli/composer.json | 2 +- .../MySqli/src/MySqliInstrumentation.php | 56 ++- .../MySqli/src/MySqliTracker.php | 8 +- .../Integration/MySqliInstrumentationTest.php | 182 ++++----- 5 files changed, 494 insertions(+), 125 deletions(-) create mode 100644 src/Instrumentation/MySqli/.phan/config.php diff --git a/src/Instrumentation/MySqli/.phan/config.php b/src/Instrumentation/MySqli/.phan/config.php new file mode 100644 index 000000000..6bf6f35c4 --- /dev/null +++ b/src/Instrumentation/MySqli/.phan/config.php @@ -0,0 +1,371 @@ + '8.2', + + // 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/MySqli/composer.json b/src/Instrumentation/MySqli/composer.json index a038ead32..e55f750ab 100644 --- a/src/Instrumentation/MySqli/composer.json +++ b/src/Instrumentation/MySqli/composer.json @@ -21,7 +21,7 @@ "ext-mysqli": "*", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.27.1", + "open-telemetry/sem-conv": "^1.30", "symfony/polyfill-mbstring": "^1.31" }, "suggest": { diff --git a/src/Instrumentation/MySqli/src/MySqliInstrumentation.php b/src/Instrumentation/MySqli/src/MySqliInstrumentation.php index 4ee60abc3..30bc32352 100644 --- a/src/Instrumentation/MySqli/src/MySqliInstrumentation.php +++ b/src/Instrumentation/MySqli/src/MySqliInstrumentation.php @@ -16,7 +16,11 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; +/** + * @phan-file-suppress PhanParamTooFewUnpack + */ class MySqliInstrumentation { use LogsMessagesTrait; @@ -33,7 +37,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.mysqli', null, - 'https://opentelemetry.io/schemas/1.27.1' + Version::VERSION_1_30_0->url(), ); $tracker = new MySqliTracker(); @@ -409,9 +413,9 @@ private static function constructPreHook(string $spanName, int $paramsOffset, Ca $attributes = []; $attributes[TraceAttributes::SERVER_ADDRESS] = $params[$paramsOffset + 0] ?? get_cfg_var('mysqli.default_host'); $attributes[TraceAttributes::SERVER_PORT] = $params[$paramsOffset + 4] ?? get_cfg_var('mysqli.default_port'); - $attributes[TraceAttributes::DB_USER] = $params[$paramsOffset + 1] ?? get_cfg_var('mysqli.default_user'); + //$attributes[TraceAttributes::DB_USER] = $params[$paramsOffset + 1] ?? get_cfg_var('mysqli.default_user'); $attributes[TraceAttributes::DB_NAMESPACE] = $params[$paramsOffset + 3] ?? null; - $attributes[TraceAttributes::DB_SYSTEM] = 'mysql'; + $attributes[TraceAttributes::DB_SYSTEM_NAME] = 'mysql'; self::startSpan($spanName, $instrumentation, $class, $function, $filename, $lineno, $attributes); } @@ -450,12 +454,11 @@ private static function queryPostHook(CachedInstrumentation $instrumentation, My $attributes = $tracker->getMySqliAttributes($mysqli); - $attributes[TraceAttributes::DB_STATEMENT] = mb_convert_encoding($query, 'UTF-8'); + $attributes[TraceAttributes::DB_QUERY_TEXT] = mb_convert_encoding($query, 'UTF-8'); $attributes[TraceAttributes::DB_OPERATION_NAME] = self::extractQueryCommand($query); if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $mysqli->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $mysqli->errno; } $errorStatus = ($retVal === false && !$exception) ? $mysqli->error : null; @@ -473,13 +476,12 @@ private static function multiQueryPostHook(CachedInstrumentation $instrumentatio $tracker->storeMySqliMultiQuery($mysqli, $query); if ($currentQuery = $tracker->getNextMySqliMultiQuery($mysqli)) { - $attributes[TraceAttributes::DB_STATEMENT] = mb_convert_encoding($currentQuery, 'UTF-8'); + $attributes[TraceAttributes::DB_QUERY_TEXT] = mb_convert_encoding($currentQuery, 'UTF-8'); $attributes[TraceAttributes::DB_OPERATION_NAME] = self::extractQueryCommand($currentQuery); } if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $mysqli->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $mysqli->errno; } else { $tracker->trackMySqliSpan($mysqli, Span::getCurrent()->getContext()); } @@ -521,13 +523,12 @@ private static function nextResultPostHook(CachedInstrumentation $instrumentatio } if ($currentQuery) { - $attributes[TraceAttributes::DB_STATEMENT] = mb_convert_encoding($currentQuery, 'UTF-8'); + $attributes[TraceAttributes::DB_QUERY_TEXT] = mb_convert_encoding($currentQuery, 'UTF-8'); $attributes[TraceAttributes::DB_OPERATION_NAME] = self::extractQueryCommand($currentQuery); } if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $mysqli->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $mysqli->errno; } self::endSpan($attributes, $exception, $errorStatus); @@ -541,7 +542,7 @@ private static function changeUserPostHook(CachedInstrumentation $instrumentatio $mysqli = $obj ? $obj : $params[0]; - $tracker->addMySqliAttribute($mysqli, TraceAttributes::DB_USER, $params[$obj ? 0 : 1]); + //$tracker->addMySqliAttribute($mysqli, TraceAttributes::DB_USER, $params[$obj ? 0 : 1]); //deprecated, no replacment at this time if (($database = $params[$obj ? 2 : 3] ?? null) !== null) { $tracker->addMySqliAttribute($mysqli, TraceAttributes::DB_NAMESPACE, $database); } @@ -575,17 +576,16 @@ private static function preparePostHook(CachedInstrumentation $instrumentation, $operation = self::extractQueryCommand($query); $attributes = $tracker->getMySqliAttributes($mysqli); - $attributes[TraceAttributes::DB_STATEMENT] = $query; + $attributes[TraceAttributes::DB_QUERY_TEXT] = $query; $attributes[TraceAttributes::DB_OPERATION_NAME] = $operation; if (!$exception && $stmtRetVal instanceof mysqli_stmt) { $tracker->trackMySqliFromStatement($mysqli, $stmtRetVal); - $tracker->addStatementAttribute($stmtRetVal, TraceAttributes::DB_STATEMENT, $query); + $tracker->addStatementAttribute($stmtRetVal, TraceAttributes::DB_QUERY_TEXT, $query); $tracker->addStatementAttribute($stmtRetVal, TraceAttributes::DB_OPERATION_NAME, $operation); } else { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $mysqli->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $mysqli->errno; $errorStatus = !$exception ? $mysqli->error : null; } @@ -610,8 +610,7 @@ private static function beginTransactionPostHook(CachedInstrumentation $instrume } if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $mysqli->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $mysqli->errno; } else { $tracker->trackMySqliTransaction($mysqli, Span::getCurrent()->getContext()); } @@ -640,8 +639,7 @@ private static function transactionPostHook(CachedInstrumentation $instrumentati } if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $mysqli->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $mysqli->errno; } $tracker->untrackMySqliTransaction($mysqli); @@ -667,7 +665,7 @@ private static function stmtPreparePostHook(CachedInstrumentation $instrumentati } $query = $obj ? $params[0] : $params[1]; - $tracker->addStatementAttribute($obj ? $obj : $params[0], TraceAttributes::DB_STATEMENT, mb_convert_encoding($query, 'UTF-8')); + $tracker->addStatementAttribute($obj ? $obj : $params[0], TraceAttributes::DB_QUERY_TEXT, mb_convert_encoding($query, 'UTF-8')); $tracker->addStatementAttribute($obj ? $obj : $params[0], TraceAttributes::DB_OPERATION_NAME, self::extractQueryCommand($query)); } @@ -683,7 +681,7 @@ private static function stmtConstructPostHook(CachedInstrumentation $instrumenta $tracker->trackMySqliFromStatement($params[0], $stmt); if ($params[1] ?? null) { - $tracker->addStatementAttribute($stmt, TraceAttributes::DB_STATEMENT, mb_convert_encoding($params[1], 'UTF-8')); + $tracker->addStatementAttribute($stmt, TraceAttributes::DB_QUERY_TEXT, mb_convert_encoding($params[1], 'UTF-8')); $tracker->addStatementAttribute($stmt, TraceAttributes::DB_OPERATION_NAME, self::extractQueryCommand($params[1])); } } @@ -701,8 +699,7 @@ private static function stmtExecutePostHook(CachedInstrumentation $instrumentati $attributes = array_merge($tracker->getMySqliAttributesFromStatement($stmt), $tracker->getStatementAttributes($stmt)); if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $stmt->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $stmt->errno; } $errorStatus = ($retVal === false && !$exception) ? $stmt->error : null; @@ -740,8 +737,7 @@ private static function stmtNextResultPostHook(CachedInstrumentation $instrument } if ($retVal === false || $exception) { - //TODO use constant from comment after sem-conv update - $attributes[/*TraceAttributes::DB_RESPONSE_STATUS_CODE*/ 'db.response.status_code'] = $stmt->errno; + $attributes[TraceAttributes::DB_RESPONSE_STATUS_CODE] = $stmt->errno; } $errorStatus = ($retVal === false && !$exception) ? $stmt->error : null; @@ -757,10 +753,10 @@ private static function startSpan(string $spanName, CachedInstrumentation $instr ->spanBuilder($spanName) ->setParent($parent) ->setSpanKind(SpanKind::KIND_CLIENT) - ->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) ->setAttributes($attributes); $span = $builder->startSpan(); @@ -788,7 +784,7 @@ private static function endSpan(iterable $attributes, ?\Throwable $exception, ?s } if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setAttribute(TraceAttributes::EXCEPTION_TYPE, $exception::class); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/MySqli/src/MySqliTracker.php b/src/Instrumentation/MySqli/src/MySqliTracker.php index ae2d9067e..5e67162a9 100644 --- a/src/Instrumentation/MySqli/src/MySqliTracker.php +++ b/src/Instrumentation/MySqli/src/MySqliTracker.php @@ -11,6 +11,9 @@ use WeakMap; use WeakReference; +/** + * @phan-file-suppress PhanNonClassMethodCall + */ final class MySqliTracker { @@ -51,10 +54,10 @@ public function getNextMySqliMultiQuery(mysqli $mysqli) : ?string public function storeMySqliAttributes(mysqli $mysqli, ?string $hostname = null, ?string $username = null, ?string $database = null, ?int $port = null, ?string $socket = null) { $attributes = []; - $attributes[TraceAttributes::DB_SYSTEM] = 'mysql'; + $attributes[TraceAttributes::DB_SYSTEM_NAME] = 'mysql'; $attributes[TraceAttributes::SERVER_ADDRESS] = $hostname ?? get_cfg_var('mysqli.default_host'); $attributes[TraceAttributes::SERVER_PORT] = $port ?? get_cfg_var('mysqli.default_port'); - $attributes[TraceAttributes::DB_USER] = $username ?? get_cfg_var('mysqli.default_user'); + //$attributes[TraceAttributes::DB_USER] = $username ?? get_cfg_var('mysqli.default_user'); //deprecated, no replacment at this time if ($database) { $attributes[TraceAttributes::DB_NAMESPACE] = $database; } @@ -82,7 +85,6 @@ public function trackMySqliFromStatement(mysqli $mysqli, mysqli_stmt $mysqli_stm public function getMySqliFromStatement(mysqli_stmt $mysqli_stmt) : ?mysqli { return ($this->statementToMySqli[$mysqli_stmt] ?? null)?->get(); - ; } public function getMySqliAttributesFromStatement(mysqli_stmt $stmt) : array diff --git a/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php b/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php index c187df3b0..7cf024ca2 100644 --- a/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php +++ b/src/Instrumentation/MySqli/tests/Integration/MySqliInstrumentationTest.php @@ -63,9 +63,9 @@ private function assertDatabaseAttributes(int $offset) { $span = $this->storage->offsetGet($offset); $this->assertEquals($this->mysqlHost, $span->getAttributes()->get(TraceAttributes::SERVER_ADDRESS)); - $this->assertEquals($this->user, $span->getAttributes()->get(TraceAttributes::DB_USER)); + //$this->assertEquals($this->user, $span->getAttributes()->get(TraceAttributes::DB_USER)); $this->assertEquals($this->database, $span->getAttributes()->get(TraceAttributes::DB_NAMESPACE)); - $this->assertEquals('mysql', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('mysql', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); } private function assertDatabaseAttributesForAllSpans(int $offsets) @@ -121,7 +121,7 @@ public function test_mysqli_query_objective(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -131,7 +131,7 @@ public function test_mysqli_query_objective(): void } $this->assertSame('mysqli::real_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -145,7 +145,7 @@ public function test_mysqli_query_objective(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -162,7 +162,7 @@ public function test_mysqli_query_objective(): void $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -180,7 +180,7 @@ public function test_mysqli_query_objective(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -195,7 +195,7 @@ public function test_mysqli_query_objective(): void $this->assertSame('mysqli::real_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -225,7 +225,7 @@ public function test_mysqli_query_procedural(): void $this->assertSame('mysqli_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -235,7 +235,7 @@ public function test_mysqli_query_procedural(): void } $this->assertSame('mysqli_real_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -249,7 +249,7 @@ public function test_mysqli_query_procedural(): void $this->assertSame('mysqli_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -266,7 +266,7 @@ public function test_mysqli_query_procedural(): void $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -284,7 +284,7 @@ public function test_mysqli_query_procedural(): void $this->assertSame('mysqli_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -299,7 +299,7 @@ public function test_mysqli_query_procedural(): void $this->assertSame('mysqli_real_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -327,7 +327,7 @@ public function test_mysqli_execute_query_objective(): void $this->assertSame('mysqli::execute_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -341,7 +341,7 @@ public function test_mysqli_execute_query_objective(): void $this->assertSame('mysqli::execute_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -358,7 +358,7 @@ public function test_mysqli_execute_query_objective(): void $this->assertSame('mysqli::execute_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -385,7 +385,7 @@ public function test_mysqli_execute_query_procedural(): void $this->assertSame('mysqli_execute_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -399,7 +399,7 @@ public function test_mysqli_execute_query_procedural(): void $this->assertSame('mysqli_execute_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -416,7 +416,7 @@ public function test_mysqli_execute_query_procedural(): void $this->assertSame('mysqli_execute_query', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString('Unknown database', $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -458,21 +458,21 @@ public function test_mysqli_multi_query_objective(): void $offset++; $this->assertSame('mysqli::multi_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT email FROM users ORDER BY id;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT email FROM users ORDER BY id;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT name FROM products ORDER BY stock;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT name FROM products ORDER BY stock;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -480,7 +480,7 @@ public function test_mysqli_multi_query_objective(): void $this->assertSame('mysqli::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString("Table 'otel_db.unknown' doesn't exist", $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT test FROM unknown ORDER BY nothing;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT test FROM unknown ORDER BY nothing;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -505,21 +505,21 @@ public function test_mysqli_multi_query_objective(): void $offset++; $this->assertSame('mysqli::multi_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT email FROM users ORDER BY id;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT email FROM users ORDER BY id;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT name FROM products ORDER BY stock;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT name FROM products ORDER BY stock;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -527,7 +527,7 @@ public function test_mysqli_multi_query_objective(): void $this->assertSame('mysqli::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString("Table 'otel_db.unknown' doesn't exist", $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT test FROM unknown ORDER BY nothing;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT test FROM unknown ORDER BY nothing;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -569,21 +569,21 @@ public function test_mysqli_multi_query_procedural(): void $offset++; $this->assertSame('mysqli_multi_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT email FROM users ORDER BY id;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT email FROM users ORDER BY id;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT name FROM products ORDER BY stock;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT name FROM products ORDER BY stock;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -591,7 +591,7 @@ public function test_mysqli_multi_query_procedural(): void $this->assertSame('mysqli_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString("Table 'otel_db.unknown' doesn't exist", $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT test FROM unknown ORDER BY nothing;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT test FROM unknown ORDER BY nothing;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -616,21 +616,21 @@ public function test_mysqli_multi_query_procedural(): void $offset++; $this->assertSame('mysqli_multi_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT email FROM users ORDER BY id;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT email FROM users ORDER BY id;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); $offset++; $this->assertSame('mysqli_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT name FROM products ORDER BY stock;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT name FROM products ORDER BY stock;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -638,7 +638,7 @@ public function test_mysqli_multi_query_procedural(): void $this->assertSame('mysqli_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertStringContainsString("Table 'otel_db.unknown' doesn't exist", $this->storage->offsetGet($offset)->getStatus()->getDescription()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT test FROM unknown ORDER BY nothing;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT test FROM unknown ORDER BY nothing;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -663,7 +663,7 @@ public function test_mysqli_prepare_objective(): void $offset++; $this->assertSame('mysqli::prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -672,7 +672,7 @@ public function test_mysqli_prepare_objective(): void $this->assertSame('mysqli_stmt::execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -692,7 +692,7 @@ public function test_mysqli_prepare_objective(): void $this->assertSame('mysqli::prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -719,7 +719,7 @@ public function test_mysqli_prepare_procedural(): void $offset++; $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -728,7 +728,7 @@ public function test_mysqli_prepare_procedural(): void $this->assertSame('mysqli_stmt_execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM otel_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM otel_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -747,7 +747,7 @@ public function test_mysqli_prepare_procedural(): void $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM unknown_db.users', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM unknown_db.users', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::EXCEPTION_TYPE => \PHPUnit\Framework\Error\Warning::class, ]); @@ -787,7 +787,7 @@ public function test_mysqli_transaction_rollback_objective(): void $offset++; $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 42000123)", + TraceAttributes::DB_QUERY_TEXT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 42000123)", TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -798,7 +798,7 @@ public function test_mysqli_transaction_rollback_objective(): void $offset++; $this->assertSame('mysqli::prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -810,7 +810,7 @@ public function test_mysqli_transaction_rollback_objective(): void $offset++; $this->assertSame('mysqli_stmt::execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -857,7 +857,7 @@ public function test_mysqli_transaction_rollback_procedural(): void $offset++; $this->assertSame('mysqli_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 76000001)", + TraceAttributes::DB_QUERY_TEXT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 76000001)", TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -868,7 +868,7 @@ public function test_mysqli_transaction_rollback_procedural(): void $offset++; $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -880,7 +880,7 @@ public function test_mysqli_transaction_rollback_procedural(): void $offset++; $this->assertSame('mysqli_stmt_execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -929,7 +929,7 @@ public function test_mysqli_transaction_commit_objective(): void $offset++; $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 76000001)", + TraceAttributes::DB_QUERY_TEXT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 76000001)", TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -941,7 +941,7 @@ public function test_mysqli_transaction_commit_objective(): void $offset++; $this->assertSame('mysqli::prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -951,7 +951,7 @@ public function test_mysqli_transaction_commit_objective(): void $offset++; $this->assertSame('mysqli_stmt::execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -1000,7 +1000,7 @@ public function test_mysqli_transaction_commit_procedural(): void $offset++; $this->assertSame('mysqli_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 76000001)", + TraceAttributes::DB_QUERY_TEXT => "INSERT INTO language(Code, Speakers) VALUES ('DE', 76000001)", TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -1011,7 +1011,7 @@ public function test_mysqli_transaction_commit_procedural(): void $offset++; $this->assertSame('mysqli_prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -1021,7 +1021,7 @@ public function test_mysqli_transaction_commit_procedural(): void $offset++; $this->assertSame('mysqli_stmt_execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', + TraceAttributes::DB_QUERY_TEXT => 'INSERT INTO language(Code, Speakers) VALUES (?,?)', TraceAttributes::DB_OPERATION_NAME => 'INSERT', ]); @@ -1058,7 +1058,7 @@ public function test_mysqli_stmt_execute_objective(): void $offset++; $this->assertSame('mysqli_stmt::execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "SELECT email FROM users WHERE name='John Doe'", + TraceAttributes::DB_QUERY_TEXT => "SELECT email FROM users WHERE name='John Doe'", TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -1072,7 +1072,7 @@ public function test_mysqli_stmt_execute_objective(): void $offset++; $this->assertSame('mysqli_stmt::execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "SELECT email FROM users WHERE name='John Doe'", + TraceAttributes::DB_QUERY_TEXT => "SELECT email FROM users WHERE name='John Doe'", TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -1099,7 +1099,7 @@ public function test_mysqli_stmt_execute_procedural(): void $offset++; $this->assertSame('mysqli_stmt_execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => "SELECT email FROM users WHERE name='John Doe'", + TraceAttributes::DB_QUERY_TEXT => "SELECT email FROM users WHERE name='John Doe'", TraceAttributes::DB_OPERATION_NAME => 'SELECT', ]); @@ -1133,7 +1133,7 @@ public function test_mysqli_multiquery_with_calls(): void $offset++; $this->assertSame('mysqli::multi_query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'DROP PROCEDURE IF EXISTS get_message;', + TraceAttributes::DB_QUERY_TEXT => 'DROP PROCEDURE IF EXISTS get_message;', TraceAttributes::DB_OPERATION_NAME => 'DROP', ]); @@ -1149,14 +1149,14 @@ public function test_mysqli_multiquery_with_calls(): void TraceAttributes::DB_OPERATION_NAME => 'CREATE', ]); $span = $this->storage->offsetGet($offset); - $this->assertStringStartsWith('CREATE PROCEDURE', $span->getAttributes()->get(TraceAttributes::DB_STATEMENT)); - $this->assertStringEndsWith('END;', $span->getAttributes()->get(TraceAttributes::DB_STATEMENT)); + $this->assertStringStartsWith('CREATE PROCEDURE', $span->getAttributes()->get(TraceAttributes::DB_QUERY_TEXT)); + $this->assertStringEndsWith('END;', $span->getAttributes()->get(TraceAttributes::DB_QUERY_TEXT)); $stmt = $mysqli->prepare('CALL get_message();'); $offset++; $this->assertSame('mysqli::prepare', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); @@ -1165,7 +1165,7 @@ public function test_mysqli_multiquery_with_calls(): void $offset++; $this->assertSame('mysqli_stmt::execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); @@ -1182,14 +1182,14 @@ public function test_mysqli_multiquery_with_calls(): void $offset++; $this->assertSame('mysqli_stmt::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); $offset++; $this->assertSame('mysqli_stmt::next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); @@ -1200,7 +1200,7 @@ public function test_mysqli_multiquery_with_calls(): void $offset++; $this->assertSame('mysqli_stmt_execute', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); @@ -1217,14 +1217,14 @@ public function test_mysqli_multiquery_with_calls(): void $offset++; $this->assertSame('mysqli_stmt_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); $offset++; $this->assertSame('mysqli_stmt_next_result', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'CALL get_message();', + TraceAttributes::DB_QUERY_TEXT => 'CALL get_message();', TraceAttributes::DB_OPERATION_NAME => 'CALL', ]); @@ -1251,12 +1251,12 @@ public function test_mysqli_change_user(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => $this->database, - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', ]); $mysqli->change_user('otel_user2', $this->passwd, 'otel_db2'); @@ -1270,12 +1270,12 @@ public function test_mysqli_change_user(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => 'otel_user2', + //TraceAttributes::DB_USER => 'otel_user2', TraceAttributes::DB_NAMESPACE => 'otel_db2', - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', ]); mysqli_change_user($mysqli, $this->user, $this->passwd, $this->database); @@ -1289,12 +1289,12 @@ public function test_mysqli_change_user(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => $this->database, - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', ]); try { @@ -1315,12 +1315,12 @@ public function test_mysqli_change_user(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT CURRENT_USER();', + TraceAttributes::DB_QUERY_TEXT => 'SELECT CURRENT_USER();', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => $this->database, - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); @@ -1346,12 +1346,12 @@ public function test_mysqli_select_db(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM users;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM users;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => $this->database, - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', ]); $mysqli->select_db('otel_db2'); @@ -1364,12 +1364,12 @@ public function test_mysqli_select_db(): void $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM users;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM users;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => 'otel_db2', - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', TraceAttributes::EXCEPTION_TYPE => mysqli_sql_exception::class, ]); } @@ -1385,12 +1385,12 @@ public function test_mysqli_select_db(): void $offset++; $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM users;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM users;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => $this->database, - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', ]); try { @@ -1408,12 +1408,12 @@ public function test_mysqli_select_db(): void $offset++; $this->assertSame('mysqli::query', $this->storage->offsetGet($offset)->getName()); $this->assertAttributes($offset, [ - TraceAttributes::DB_STATEMENT => 'SELECT * FROM users;', + TraceAttributes::DB_QUERY_TEXT => 'SELECT * FROM users;', TraceAttributes::DB_OPERATION_NAME => 'SELECT', TraceAttributes::SERVER_ADDRESS => $this->mysqlHost, - TraceAttributes::DB_USER => $this->user, + //TraceAttributes::DB_USER => $this->user, TraceAttributes::DB_NAMESPACE => $this->database, - TraceAttributes::DB_SYSTEM => 'mysql', + TraceAttributes::DB_SYSTEM_NAME => 'mysql', ]); $offset++; From e090bcbd7721dd0d63ce5d2affc732a621d0b639 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 15:30:34 +1100 Subject: [PATCH 11/35] openaiphp --- .../OpenAIPHP/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/OpenAIPHP/composer.json | 3 +- .../src/OpenAIPHPInstrumentation.php | 7 +- 3 files changed, 377 insertions(+), 4 deletions(-) create mode 100644 src/Instrumentation/OpenAIPHP/.phan/config.php diff --git a/src/Instrumentation/OpenAIPHP/.phan/config.php b/src/Instrumentation/OpenAIPHP/.phan/config.php new file mode 100644 index 000000000..6473a9aa8 --- /dev/null +++ b/src/Instrumentation/OpenAIPHP/.phan/config.php @@ -0,0 +1,371 @@ + '8.1', + + // 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/OpenAIPHP/composer.json b/src/Instrumentation/OpenAIPHP/composer.json index e850e1a3a..00c03b2f4 100644 --- a/src/Instrumentation/OpenAIPHP/composer.json +++ b/src/Instrumentation/OpenAIPHP/composer.json @@ -7,13 +7,14 @@ "readme": "./README.md", "license": "Apache-2.0", "minimum-stability": "dev", + "prefer-stable": true, "require": { "php": "^8.1", "composer-runtime-api": "^2.0", "ext-opentelemetry": "*", "openai-php/client": "*", "open-telemetry/api": "^1", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php b/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php index c08979bac..0379d92df 100644 --- a/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php +++ b/src/Instrumentation/OpenAIPHP/src/OpenAIPHPInstrumentation.php @@ -23,6 +23,7 @@ use OpenTelemetry\Context\ContextInterface; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Throwable; final class OpenAIPHPInstrumentation @@ -39,7 +40,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.openaiphp', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-openai-php'), - 'https://opentelemetry.io/schemas/1.24.0', + Version::VERSION_1_30_0->url(), ); self::$totalTokensCounter = $instrumentation->meter()->createCounter( @@ -91,10 +92,10 @@ private static function hookApi(CachedInstrumentation $instrumentation, $class, ->spanBuilder(sprintf('openai %s', $resource . '/' . $operation)) ->setSpanKind(SpanKind::KIND_INTERNAL) // 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) // openai ->setAttribute(OpenAIAttributes::OPENAI_RESOURCE, $resource . '/' . $operation) ; From a36267c3dca74439a328c728ec203070c433798a Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 15:58:33 +1100 Subject: [PATCH 12/35] pdo --- src/Instrumentation/PDO/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/PDO/composer.json | 2 +- .../PDO/src/PDOInstrumentation.php | 19 +- src/Instrumentation/PDO/src/PDOTracker.php | 29 +- .../Integration/PDOInstrumentationTest.php | 24 +- .../tests/Unit/PDOAttributeTrackerTest.php | 10 +- 6 files changed, 415 insertions(+), 40 deletions(-) create mode 100644 src/Instrumentation/PDO/.phan/config.php diff --git a/src/Instrumentation/PDO/.phan/config.php b/src/Instrumentation/PDO/.phan/config.php new file mode 100644 index 000000000..6bf6f35c4 --- /dev/null +++ b/src/Instrumentation/PDO/.phan/config.php @@ -0,0 +1,371 @@ + '8.2', + + // 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/PDO/composer.json b/src/Instrumentation/PDO/composer.json index 501947f2b..58ff8420f 100644 --- a/src/Instrumentation/PDO/composer.json +++ b/src/Instrumentation/PDO/composer.json @@ -13,7 +13,7 @@ "ext-pdo": "*", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "symfony/polyfill-mbstring": "^1.31" }, "suggest": { diff --git a/src/Instrumentation/PDO/src/PDOInstrumentation.php b/src/Instrumentation/PDO/src/PDOInstrumentation.php index 312c3104f..8ddc6b6f6 100644 --- a/src/Instrumentation/PDO/src/PDOInstrumentation.php +++ b/src/Instrumentation/PDO/src/PDOInstrumentation.php @@ -12,6 +12,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use PDO; use PDOStatement; use Throwable; @@ -25,7 +26,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.pdo', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); $pdoTracker = new PDOTracker(); @@ -39,8 +40,8 @@ public static function register(): void if ($class === PDO::class) { //@todo split params[0] into host + port, replace deprecated trace attribute $builder - ->setAttribute(TraceAttributes::DB_CONNECTION_STRING, $params[0] ?? 'unknown') - ->setAttribute(TraceAttributes::DB_USER, $params[1] ?? 'unknown'); + ->setAttribute(TraceAttributes::SERVER_ADDRESS, $params[0] ?? 'unknown') + ->setAttribute(TraceAttributes::SERVER_PORT, $params[0] ?? null); } $parent = Context::getCurrent(); $span = $builder->startSpan(); @@ -70,7 +71,7 @@ public static function register(): void $builder = self::makeBuilder($instrumentation, 'PDO::query', $function, $class, $filename, $lineno) ->setSpanKind(SpanKind::KIND_CLIENT); if ($class === PDO::class) { - $builder->setAttribute(TraceAttributes::DB_STATEMENT, mb_convert_encoding($params[0] ?? 'undefined', 'UTF-8')); + $builder->setAttribute(TraceAttributes::DB_QUERY_TEXT, mb_convert_encoding($params[0] ?? 'undefined', 'UTF-8')); } $parent = Context::getCurrent(); $span = $builder->startSpan(); @@ -93,7 +94,7 @@ public static function register(): void $builder = self::makeBuilder($instrumentation, 'PDO::exec', $function, $class, $filename, $lineno) ->setSpanKind(SpanKind::KIND_CLIENT); if ($class === PDO::class) { - $builder->setAttribute(TraceAttributes::DB_STATEMENT, mb_convert_encoding($params[0] ?? 'undefined', 'UTF-8')); + $builder->setAttribute(TraceAttributes::DB_QUERY_TEXT, mb_convert_encoding($params[0] ?? 'undefined', 'UTF-8')); } $parent = Context::getCurrent(); $span = $builder->startSpan(); @@ -116,7 +117,7 @@ public static function register(): void $builder = self::makeBuilder($instrumentation, 'PDO::prepare', $function, $class, $filename, $lineno) ->setSpanKind(SpanKind::KIND_CLIENT); if ($class === PDO::class) { - $builder->setAttribute(TraceAttributes::DB_STATEMENT, mb_convert_encoding($params[0] ?? 'undefined', 'UTF-8')); + $builder->setAttribute(TraceAttributes::DB_QUERY_TEXT, mb_convert_encoding($params[0] ?? 'undefined', 'UTF-8')); } $parent = Context::getCurrent(); $span = $builder->startSpan(); @@ -248,10 +249,10 @@ private static function makeBuilder( /** @psalm-suppress ArgumentTypeCoercion */ return $instrumentation->tracer() ->spanBuilder($name) - ->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); } private static function end(?Throwable $exception): void { @@ -262,7 +263,7 @@ private static function end(?Throwable $exception): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/PDO/src/PDOTracker.php b/src/Instrumentation/PDO/src/PDOTracker.php index ecf78bdef..96761f3c4 100644 --- a/src/Instrumentation/PDO/src/PDOTracker.php +++ b/src/Instrumentation/PDO/src/PDOTracker.php @@ -11,6 +11,9 @@ use WeakMap; use WeakReference; +/** + * @phan-file-suppress PhanNonClassMethodCall,PhanTypeArraySuspicious + */ final class PDOTracker { /** @@ -70,11 +73,11 @@ public function trackPdoAttributes(PDO $pdo, string $dsn): iterable /** @var string $dbSystem */ $dbSystem = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); /** @psalm-suppress InvalidArrayAssignment */ - $attributes[TraceAttributes::DB_SYSTEM] = self::mapDriverNameToAttribute($dbSystem); + $attributes[TraceAttributes::DB_SYSTEM_NAME] = self::mapDriverNameToAttribute($dbSystem); } catch (\Error) { - // if we catched an exception, the driver is likely not supporting the operation, default to "other" + // if we caught an exception, the driver is likely not supporting the operation, default to "other" /** @psalm-suppress PossiblyInvalidArrayAssignment */ - $attributes[TraceAttributes::DB_SYSTEM] = 'other_sql'; + $attributes[TraceAttributes::DB_SYSTEM_NAME] = 'other_sql'; } $this->pdoToAttributesMap[$pdo] = $attributes; @@ -126,39 +129,39 @@ private static function extractAttributesFromDSN(string $dsn): iterable { $attributes = []; if (str_starts_with($dsn, 'sqlite::memory:')) { - $attributes[TraceAttributes::DB_SYSTEM] = 'sqlite'; - $attributes[TraceAttributes::DB_NAME] = 'memory'; + $attributes[TraceAttributes::DB_SYSTEM_NAME] = 'sqlite'; + $attributes[TraceAttributes::DB_NAMESPACE] = 'memory'; return $attributes; } elseif (str_starts_with($dsn, 'sqlite:')) { - $attributes[TraceAttributes::DB_SYSTEM] = 'sqlite'; - $attributes[TraceAttributes::DB_NAME] = substr($dsn, 7); + $attributes[TraceAttributes::DB_SYSTEM_NAME] = 'sqlite'; + $attributes[TraceAttributes::DB_NAMESPACE] = substr($dsn, 7); return $attributes; } elseif (str_starts_with($dsn, 'sqlite')) { - $attributes[TraceAttributes::DB_SYSTEM] = 'sqlite'; - $attributes[TraceAttributes::DB_NAME] = $dsn; + $attributes[TraceAttributes::DB_SYSTEM_NAME] = 'sqlite'; + $attributes[TraceAttributes::DB_NAMESPACE] = $dsn; return $attributes; } - if (preg_match('/user=([^;]*)/', $dsn, $matches)) { + //deprecated, no replacement at this time + /*if (preg_match('/user=([^;]*)/', $dsn, $matches)) { $user = $matches[1]; if ($user !== '') { $attributes[TraceAttributes::DB_USER] = $user; } - } + }*/ if (preg_match('/host=([^;]*)/', $dsn, $matches)) { $host = $matches[1]; if ($host !== '') { - $attributes[TraceAttributes::NET_PEER_NAME] = $host; $attributes[TraceAttributes::SERVER_ADDRESS] = $host; } } if (preg_match('/dbname=([^;]*)/', $dsn, $matches)) { $dbname = $matches[1]; if ($dbname !== '') { - $attributes[TraceAttributes::DB_NAME] = $dbname; + $attributes[TraceAttributes::DB_NAMESPACE] = $dbname; } } diff --git a/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php b/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php index 3fcd1b3c4..ba43e304a 100644 --- a/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php +++ b/src/Instrumentation/PDO/tests/Integration/PDOInstrumentationTest.php @@ -69,7 +69,7 @@ public function test_pdo_construct(): void $this->assertCount(1, $this->storage); $span = $this->storage->offsetGet(0); $this->assertSame('PDO::__construct', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); } public function test_constructor_exception(): void @@ -87,32 +87,32 @@ public function test_statement_execution(): void $db->exec($statement); $span = $this->storage->offsetGet(1); $this->assertSame('PDO::exec', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertFalse($db->inTransaction()); $this->assertCount(2, $this->storage); $sth = $db->prepare('SELECT * FROM `technology`'); $span = $this->storage->offsetGet(2); $this->assertSame('PDO::prepare', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(3, $this->storage); $sth->execute(); $span = $this->storage->offsetGet(3); $this->assertSame('PDOStatement::execute', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(4, $this->storage); $sth->fetchAll(); $span = $this->storage->offsetGet(4); $this->assertSame('PDOStatement::fetchAll', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(5, $this->storage); $db->query('SELECT * FROM `technology`'); $span = $this->storage->offsetGet(5); $this->assertSame('PDO::query', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(6, $this->storage); } @@ -122,7 +122,7 @@ public function test_transaction(): void $result = $db->beginTransaction(); $span = $this->storage->offsetGet(1); $this->assertSame('PDO::beginTransaction', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(2, $this->storage); $this->assertSame($result, true); @@ -131,7 +131,7 @@ public function test_transaction(): void $result = $db->commit(); $span = $this->storage->offsetGet(3); $this->assertSame('PDO::commit', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(4, $this->storage); $this->assertTrue($result); @@ -143,7 +143,7 @@ public function test_transaction(): void $result = $db->rollback(); $span = $this->storage->offsetGet(6); $this->assertSame('PDO::rollBack', $span->getName()); - $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM)); + $this->assertEquals('sqlite', $span->getAttributes()->get(TraceAttributes::DB_SYSTEM_NAME)); $this->assertCount(7, $this->storage); $this->assertTrue($result); $this->assertFalse($db->inTransaction()); @@ -201,17 +201,17 @@ public function test_encode_db_statement_as_utf8(): void $db->prepare("SELECT id FROM technology WHERE id = '{$non_utf8_id}'"); $span_db_prepare = $this->storage->offsetGet(2); - $this->assertTrue(mb_check_encoding($span_db_prepare->getAttributes()->get(TraceAttributes::DB_STATEMENT), 'UTF-8')); + $this->assertTrue(mb_check_encoding($span_db_prepare->getAttributes()->get(TraceAttributes::DB_QUERY_TEXT), 'UTF-8')); $this->assertCount(3, $this->storage); $db->query("SELECT id FROM technology WHERE id = '{$non_utf8_id}'"); $span_db_query = $this->storage->offsetGet(3); - $this->assertTrue(mb_check_encoding($span_db_query->getAttributes()->get(TraceAttributes::DB_STATEMENT), 'UTF-8')); + $this->assertTrue(mb_check_encoding($span_db_query->getAttributes()->get(TraceAttributes::DB_QUERY_TEXT), 'UTF-8')); $this->assertCount(4, $this->storage); $db->exec("SELECT id FROM technology WHERE id = '{$non_utf8_id}'"); $span_db_exec = $this->storage->offsetGet(4); - $this->assertTrue(mb_check_encoding($span_db_exec->getAttributes()->get(TraceAttributes::DB_STATEMENT), 'UTF-8')); + $this->assertTrue(mb_check_encoding($span_db_exec->getAttributes()->get(TraceAttributes::DB_QUERY_TEXT), 'UTF-8')); $this->assertCount(5, $this->storage); } } diff --git a/src/Instrumentation/PDO/tests/Unit/PDOAttributeTrackerTest.php b/src/Instrumentation/PDO/tests/Unit/PDOAttributeTrackerTest.php index 7031b333a..44937122e 100644 --- a/src/Instrumentation/PDO/tests/Unit/PDOAttributeTrackerTest.php +++ b/src/Instrumentation/PDO/tests/Unit/PDOAttributeTrackerTest.php @@ -22,20 +22,20 @@ public function testPdoCanBeTracked(): void $span = Span::getInvalid(); /** @psalm-suppress InvalidArgument */ - $this->assertContains(TraceAttributes::DB_SYSTEM, array_keys($attributes)); + $this->assertContains(TraceAttributes::DB_SYSTEM_NAME, array_keys($attributes)); /** @psalm-suppress InvalidArgument */ - $this->assertContains(TraceAttributes::DB_NAME, array_keys($attributes)); + $this->assertContains(TraceAttributes::DB_NAMESPACE, array_keys($attributes)); /** @psalm-suppress InvalidArrayAccess */ - $this->assertSame('memory', $attributes[TraceAttributes::DB_NAME]); + $this->assertSame('memory', $attributes[TraceAttributes::DB_NAMESPACE]); $stmt = $pdo->prepare('SELECT NULL LIMIT 0;'); $objectMap->trackStatement($stmt, $pdo, $span->getContext()); $attributes = $objectMap->trackedAttributesForStatement($stmt); /** @psalm-suppress InvalidArgument */ - $this->assertContains(TraceAttributes::DB_SYSTEM, array_keys($attributes)); + $this->assertContains(TraceAttributes::DB_SYSTEM_NAME, array_keys($attributes)); /** @psalm-suppress InvalidArrayAccess */ - $this->assertEquals('sqlite', $attributes[TraceAttributes::DB_SYSTEM]); + $this->assertEquals('sqlite', $attributes[TraceAttributes::DB_SYSTEM_NAME]); $this->assertSame($span->getContext(), $objectMap->getSpanForPreparedStatement($stmt)); } } From a83ff6184e68815c64d126f083a6b7ffbf0e00f7 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:04:49 +1100 Subject: [PATCH 13/35] psr3 --- src/Instrumentation/Psr3/composer.json | 2 +- src/Instrumentation/Psr3/src/Psr3Instrumentation.php | 5 +++-- src/Instrumentation/Psr3/tests/phpt/export_apix.phpt | 2 +- src/Instrumentation/Psr3/tests/phpt/export_cake.phpt | 2 +- src/Instrumentation/Psr3/tests/phpt/export_monolog.phpt | 2 +- src/Instrumentation/Psr3/tests/phpt/export_multi.phpt | 2 +- src/Instrumentation/Psr3/tests/phpt/export_symfony.phpt | 2 +- src/Instrumentation/Psr3/tests/phpt/export_yii.phpt | 2 +- 8 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Instrumentation/Psr3/composer.json b/src/Instrumentation/Psr3/composer.json index 019b1c00d..942700d98 100644 --- a/src/Instrumentation/Psr3/composer.json +++ b/src/Instrumentation/Psr3/composer.json @@ -19,7 +19,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "psr/log": "^1 || ^2 || ^3" }, "autoload": { diff --git a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php index 2cca4e8e6..faf0f5643 100644 --- a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php +++ b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php @@ -10,6 +10,7 @@ use OpenTelemetry\API\Trace\Span; use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; +use OpenTelemetry\SemConv\Version; use Psr\Log\LoggerInterface; use Psr\Log\LoggerTrait; @@ -63,7 +64,7 @@ public static function register(): void $instrumentation ??= new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr3', null, - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); if ($function === 'log') { $level = $params[0]; @@ -76,7 +77,7 @@ public static function register(): void } $record = (new API\LogRecord($body)) - ->setSeverityNumber(API\Map\Psr3::severityNumber($level)); + ->setSeverityNumber(API\Severity::fromPsr3($level)); foreach (Formatter::format($context) as $key => $value) { $record->setAttribute((string) $key, $value); } diff --git a/src/Instrumentation/Psr3/tests/phpt/export_apix.phpt b/src/Instrumentation/Psr3/tests/phpt/export_apix.phpt index c506f205f..147c31354 100644 --- a/src/Instrumentation/Psr3/tests/phpt/export_apix.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/export_apix.phpt @@ -42,7 +42,7 @@ $span->end(); "version": null, "attributes": [], "dropped_attributes_count": 0, - "schema_url": "https:\/\/opentelemetry.io\/schemas\/1.24.0", + "schema_url": "https:\/\/opentelemetry.io\/schemas\/%s", "logs": [ { "timestamp": null, diff --git a/src/Instrumentation/Psr3/tests/phpt/export_cake.phpt b/src/Instrumentation/Psr3/tests/phpt/export_cake.phpt index 1c190b1ec..73c3cdc3a 100644 --- a/src/Instrumentation/Psr3/tests/phpt/export_cake.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/export_cake.phpt @@ -45,7 +45,7 @@ $span->end(); "version": null, "attributes": [], "dropped_attributes_count": 0, - "schema_url": "https:\/\/opentelemetry.io\/schemas\/1.24.0", + "schema_url": "https:\/\/opentelemetry.io\/schemas\/%s", "logs": [ { "timestamp": null, diff --git a/src/Instrumentation/Psr3/tests/phpt/export_monolog.phpt b/src/Instrumentation/Psr3/tests/phpt/export_monolog.phpt index 0ac95f040..9506318e1 100644 --- a/src/Instrumentation/Psr3/tests/phpt/export_monolog.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/export_monolog.phpt @@ -39,7 +39,7 @@ $span->end(); "version": null, "attributes": [], "dropped_attributes_count": 0, - "schema_url": "https:\/\/opentelemetry.io\/schemas\/1.24.0", + "schema_url": "https:\/\/opentelemetry.io\/schemas\/%s", "logs": [ { "timestamp": null, diff --git a/src/Instrumentation/Psr3/tests/phpt/export_multi.phpt b/src/Instrumentation/Psr3/tests/phpt/export_multi.phpt index 8680d8eda..2d5dfa709 100644 --- a/src/Instrumentation/Psr3/tests/phpt/export_multi.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/export_multi.phpt @@ -54,7 +54,7 @@ Message context: "version": null, "attributes": [], "dropped_attributes_count": 0, - "schema_url": "https:\/\/opentelemetry.io\/schemas\/1.24.0", + "schema_url": "https:\/\/opentelemetry.io\/schemas\/%s", "logs": [ { "timestamp": null, diff --git a/src/Instrumentation/Psr3/tests/phpt/export_symfony.phpt b/src/Instrumentation/Psr3/tests/phpt/export_symfony.phpt index d43517ffe..34205fca4 100644 --- a/src/Instrumentation/Psr3/tests/phpt/export_symfony.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/export_symfony.phpt @@ -41,7 +41,7 @@ $span->end(); "version": null, "attributes": [], "dropped_attributes_count": 0, - "schema_url": "https:\/\/opentelemetry.io\/schemas\/1.24.0", + "schema_url": "https:\/\/opentelemetry.io\/schemas\/%s", "logs": [ { "timestamp": null, diff --git a/src/Instrumentation/Psr3/tests/phpt/export_yii.phpt b/src/Instrumentation/Psr3/tests/phpt/export_yii.phpt index e483d67e8..73618662a 100644 --- a/src/Instrumentation/Psr3/tests/phpt/export_yii.phpt +++ b/src/Instrumentation/Psr3/tests/phpt/export_yii.phpt @@ -59,7 +59,7 @@ Stack trace: "version": null, "attributes": [], "dropped_attributes_count": 0, - "schema_url": "https:\/\/opentelemetry.io\/schemas\/1.24.0", + "schema_url": "https:\/\/opentelemetry.io\/schemas\/%s", "logs": [ { "timestamp": null, From 9b014a26104b6da4ed42863fbaab4d245f2945eb Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:07:21 +1100 Subject: [PATCH 14/35] psr6 --- src/Instrumentation/Psr6/composer.json | 2 +- src/Instrumentation/Psr6/src/Psr6Instrumentation.php | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Instrumentation/Psr6/composer.json b/src/Instrumentation/Psr6/composer.json index 64894c45b..52c5ed9d6 100644 --- a/src/Instrumentation/Psr6/composer.json +++ b/src/Instrumentation/Psr6/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "psr/cache": "^1 || ^2 || ^3", "composer-runtime-api": "^2.0" }, diff --git a/src/Instrumentation/Psr6/src/Psr6Instrumentation.php b/src/Instrumentation/Psr6/src/Psr6Instrumentation.php index 10ac01ca6..944fed2c0 100644 --- a/src/Instrumentation/Psr6/src/Psr6Instrumentation.php +++ b/src/Instrumentation/Psr6/src/Psr6Instrumentation.php @@ -13,6 +13,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\Cache\CacheItemInterface; use Psr\Cache\CacheItemPoolInterface; use Throwable; @@ -29,7 +30,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr6', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-psr6'), - 'https://opentelemetry.io/schemas/1.24.0', + Version::VERSION_1_30_0->url(), ); $pre = static function (CacheItemPoolInterface $pool, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($instrumentation) { @@ -73,10 +74,10 @@ private static function makeSpanBuilder( return $instrumentation->tracer() ->spanBuilder($function) ->setSpanKind(SpanKind::KIND_INTERNAL) - ->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) ->setAttribute('cache.operation', $name); } @@ -91,7 +92,7 @@ private static function end(?Throwable $exception): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From d77b8cd841f6e3c61344e6a231ac26800bf00e74 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:10:58 +1100 Subject: [PATCH 15/35] psr14 --- src/Instrumentation/Psr14/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/Psr14/composer.json | 2 +- .../Psr14/src/Psr14Instrumentation.php | 9 +- 3 files changed, 377 insertions(+), 5 deletions(-) create mode 100644 src/Instrumentation/Psr14/.phan/config.php diff --git a/src/Instrumentation/Psr14/.phan/config.php b/src/Instrumentation/Psr14/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/Psr14/.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/Psr14/composer.json b/src/Instrumentation/Psr14/composer.json index 1b3449548..84002adbe 100644 --- a/src/Instrumentation/Psr14/composer.json +++ b/src/Instrumentation/Psr14/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "psr/event-dispatcher": "^1", "composer-runtime-api": "^2.0" }, diff --git a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php index 1d0a239f2..8690cbf95 100644 --- a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php +++ b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\EventDispatcher\EventDispatcherInterface; use Throwable; @@ -27,7 +28,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr14', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-psr14'), - 'https://opentelemetry.io/schemas/1.24.0' + Version::VERSION_1_30_0->url(), ); /** @@ -40,10 +41,10 @@ public static function register(): void $event = is_object($params[0]) ? $params[0] : null; $builder = $instrumentation->tracer() ->spanBuilder(sprintf('event %s', $event ? $event::class : 'unknown')) - ->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); if ($event) { $builder->setAttribute('psr14.event.name', $event::class); @@ -63,7 +64,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From f561a33ff8f1ee1db1f53438425326eb3a75770f Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:19:41 +1100 Subject: [PATCH 16/35] psr15 --- src/Instrumentation/Psr15/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/Psr15/composer.json | 2 +- .../Psr15/src/Psr15Instrumentation.php | 19 +- 3 files changed, 384 insertions(+), 8 deletions(-) create mode 100644 src/Instrumentation/Psr15/.phan/config.php diff --git a/src/Instrumentation/Psr15/.phan/config.php b/src/Instrumentation/Psr15/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/Psr15/.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/Psr15/composer.json b/src/Instrumentation/Psr15/composer.json index 0489d10ee..b9e8710f2 100644 --- a/src/Instrumentation/Psr15/composer.json +++ b/src/Instrumentation/Psr15/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "psr/http-server-middleware": "^1" }, "autoload": { diff --git a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php index de59e64aa..6d263c962 100644 --- a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php +++ b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php @@ -13,6 +13,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -28,7 +29,11 @@ class Psr15Instrumentation public static function register(): void { - $instrumentation = new CachedInstrumentation('io.opentelemetry.contrib.php.psr15'); + $instrumentation = new CachedInstrumentation( + 'io.opentelemetry.contrib.php.psr15', + null, + Version::VERSION_1_30_0->url(), + ); /** * Create a span for each psr-15 middleware that is executed. @@ -38,10 +43,10 @@ public static function register(): void 'process', pre: static function (MiddlewareInterface $middleware, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($instrumentation) { $span = $instrumentation->tracer()->spanBuilder(sprintf('%s::%s', $class, $function)) - ->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) ->startSpan(); Context::storage()->attach($span->storeInContext(Context::getCurrent())); @@ -54,7 +59,7 @@ public static function register(): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } $span->end(); @@ -79,10 +84,10 @@ public static function register(): void : sprintf('%s', $request?->getMethod() ?? 'unknown') ) ->setSpanKind(SpanKind::KIND_SERVER) - ->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); $parent = Context::getCurrent(); if (!$root && $request) { //create http root span @@ -114,7 +119,7 @@ public static function register(): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } if ($response) { From df0e60d46717aa46268896c622d2bda9f70f339f Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:22:20 +1100 Subject: [PATCH 17/35] psr16 --- src/Instrumentation/Psr16/composer.json | 2 +- src/Instrumentation/Psr16/src/Psr16Instrumentation.php | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Instrumentation/Psr16/composer.json b/src/Instrumentation/Psr16/composer.json index d11250ca3..5e75650ff 100644 --- a/src/Instrumentation/Psr16/composer.json +++ b/src/Instrumentation/Psr16/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "psr/simple-cache": "^1 || ^2 || ^3", "composer-runtime-api": "^2.0" }, diff --git a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php index 4f598a9cd..ffeecea60 100644 --- a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php +++ b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php @@ -13,6 +13,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\SimpleCache\CacheInterface; use Throwable; @@ -28,7 +29,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr16', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-psr16'), - 'https://opentelemetry.io/schemas/1.24.0', + Version::VERSION_1_30_0->url(), ); $pre = static function (CacheInterface $cacheItem, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($instrumentation) { @@ -68,10 +69,10 @@ private static function makeSpanBuilder( return $instrumentation->tracer() ->spanBuilder($name) ->setSpanKind(SpanKind::KIND_INTERNAL) - ->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) ->setAttribute('cache.operation', $name); } @@ -86,7 +87,7 @@ private static function end(?Throwable $exception): void $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From 8345f3a1092bb30c934978db22a9e8017c965a43 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:25:38 +1100 Subject: [PATCH 18/35] psr18 --- src/Instrumentation/Psr18/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/Psr18/composer.json | 2 +- .../Psr18/src/Psr18Instrumentation.php | 12 +- 3 files changed, 380 insertions(+), 5 deletions(-) create mode 100644 src/Instrumentation/Psr18/.phan/config.php diff --git a/src/Instrumentation/Psr18/.phan/config.php b/src/Instrumentation/Psr18/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/Psr18/.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/Psr18/composer.json b/src/Instrumentation/Psr18/composer.json index 273e0d836..31f5940f8 100644 --- a/src/Instrumentation/Psr18/composer.json +++ b/src/Instrumentation/Psr18/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "psr/http-client": "^1" }, "autoload": { diff --git a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php index 0be3127aa..2ea0ecefb 100644 --- a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php +++ b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php @@ -13,6 +13,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -27,7 +28,10 @@ class Psr18Instrumentation public static function register(): void { - $instrumentation = new CachedInstrumentation('io.opentelemetry.contrib.php.psr18', schemaUrl: TraceAttributes::SCHEMA_URL); + $instrumentation = new CachedInstrumentation( + 'io.opentelemetry.contrib.php.psr18', + schemaUrl: Version::VERSION_1_30_0->url(), + ); hook( ClientInterface::class, @@ -56,10 +60,10 @@ public static function register(): void ->setAttribute(TraceAttributes::HTTP_REQUEST_BODY_SIZE, $request->getHeaderLine('Content-Length')) ->setAttribute(TraceAttributes::SERVER_ADDRESS, $request->getUri()->getHost()) ->setAttribute(TraceAttributes::SERVER_PORT, $request->getUri()->getPort()) - ->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) ; foreach ($propagator->fields() as $field) { @@ -110,7 +114,7 @@ public static function register(): void } } if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From 104cf0b6d4d84b1ded49c29dbdebc88dfb0a0acf Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:29:45 +1100 Subject: [PATCH 19/35] slim --- src/Instrumentation/Slim/composer.json | 2 +- .../Slim/src/SlimInstrumentation.php | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Instrumentation/Slim/composer.json b/src/Instrumentation/Slim/composer.json index 4fa380ee3..f2e9cc2b6 100644 --- a/src/Instrumentation/Slim/composer.json +++ b/src/Instrumentation/Slim/composer.json @@ -13,7 +13,7 @@ "ext-opentelemetry": "*", "ext-reflection": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "slim/slim": "^4" }, "require-dev": { diff --git a/src/Instrumentation/Slim/src/SlimInstrumentation.php b/src/Instrumentation/Slim/src/SlimInstrumentation.php index ca860178e..561fe8033 100644 --- a/src/Instrumentation/Slim/src/SlimInstrumentation.php +++ b/src/Instrumentation/Slim/src/SlimInstrumentation.php @@ -13,6 +13,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\App; @@ -32,8 +33,9 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.slim', null, - 'https://opentelemetry.io/schemas/1.25.0' + Version::VERSION_1_30_0->url(), ); + /** * requires extension >= 1.0.2beta2 * @see https://github.com/open-telemetry/opentelemetry-php-instrumentation/pull/136 @@ -49,10 +51,10 @@ public static function register(): void $builder = $instrumentation->tracer() ->spanBuilder(sprintf('%s', $request?->getMethod() ?? 'unknown')) ->setSpanKind(SpanKind::KIND_SERVER) - ->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); $parent = Context::getCurrent(); if ($request) { $parent = Globals::propagator()->extract($request->getHeaders()); @@ -83,7 +85,7 @@ public static function register(): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } if ($response) { @@ -155,10 +157,10 @@ public static function register(): void $callable = $params[0]; $name = CallableFormatter::format($callable); $builder = $instrumentation->tracer()->spanBuilder($name) - ->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); $span = $builder->startSpan(); Context::storage()->attach($span->storeInContext(Context::getCurrent())); }, @@ -170,7 +172,7 @@ public static function register(): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } $span->end(); From d7891e7254da7060bf141e46de7ddd1da534b635 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:36:35 +1100 Subject: [PATCH 20/35] symfony --- src/Instrumentation/Symfony/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/Symfony/composer.json | 2 +- .../Symfony/src/HttpClientInstrumentation.php | 18 +- .../Symfony/src/MessengerInstrumentation.php | 23 +- .../Symfony/src/SymfonyInstrumentation.php | 19 +- 5 files changed, 406 insertions(+), 27 deletions(-) create mode 100644 src/Instrumentation/Symfony/.phan/config.php diff --git a/src/Instrumentation/Symfony/.phan/config.php b/src/Instrumentation/Symfony/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/Symfony/.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/Symfony/composer.json b/src/Instrumentation/Symfony/composer.json index 63acee77d..ee8e8d35a 100644 --- a/src/Instrumentation/Symfony/composer.json +++ b/src/Instrumentation/Symfony/composer.json @@ -12,7 +12,7 @@ "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "symfony/http-kernel": "*", "symfony/http-client-contracts": "*" }, diff --git a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php index 666ac67a2..d4f6d8ba1 100644 --- a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php +++ b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php @@ -13,9 +13,13 @@ use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; +/** + * @phan-file-suppress PhanTypeInvalidCallableArraySize + */ final class HttpClientInstrumentation { /** @@ -34,7 +38,11 @@ public static function supportsProgress(string $class): bool public static function register(): void { - $instrumentation = new CachedInstrumentation('io.opentelemetry.contrib.php.symfony_http'); + $instrumentation = new CachedInstrumentation( + 'io.opentelemetry.contrib.php.symfony_http', + null, + Version::VERSION_1_30_0->url(), + ); hook( HttpClientInterface::class, @@ -55,10 +63,10 @@ public static function register(): void ->setAttribute(TraceAttributes::PEER_SERVICE, parse_url((string) $params[1])['host'] ?? null) ->setAttribute(TraceAttributes::URL_FULL, (string) $params[1]) ->setAttribute(TraceAttributes::HTTP_REQUEST_METHOD, $params[0]) - ->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); $propagator = Globals::propagator(); $parent = Context::getCurrent(); @@ -129,9 +137,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); if (null !== $exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); $span->end(); diff --git a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php index 9b0b8e606..5fa9f11ba 100644 --- a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php +++ b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php @@ -11,6 +11,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; @@ -34,7 +35,11 @@ final class MessengerInstrumentation public static function register(): void { - $instrumentation = new CachedInstrumentation('io.opentelemetry.contrib.php.symfony_messenger'); + $instrumentation = new CachedInstrumentation( + 'io.opentelemetry.contrib.php.symfony_messenger', + null, + Version::VERSION_1_30_0->url(), + ); /** * MessageBusInterface dispatches messages to the handlers. @@ -59,10 +64,10 @@ public static function register(): void ->tracer() ->spanBuilder(\sprintf('DISPATCH %s', $messageClass)) ->setSpanKind(SpanKind::KIND_PRODUCER) - ->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) ->setAttribute(self::ATTRIBUTE_MESSENGER_BUS, $class) ->setAttribute(self::ATTRIBUTE_MESSENGER_MESSAGE, $messageClass) @@ -93,9 +98,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); if (null !== $exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } @@ -126,10 +129,10 @@ public static function register(): void ->tracer() ->spanBuilder(\sprintf('SEND %s', $messageClass)) ->setSpanKind(SpanKind::KIND_PRODUCER) - ->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) ->setAttribute(self::ATTRIBUTE_MESSENGER_TRANSPORT, $class) ->setAttribute(self::ATTRIBUTE_MESSENGER_MESSAGE, $messageClass) @@ -162,9 +165,7 @@ public static function register(): void $span = Span::fromContext($scope->context()); if (null !== $exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } diff --git a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php index 3b2053551..ff9bb79cb 100644 --- a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php +++ b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php @@ -13,6 +13,7 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; +use OpenTelemetry\SemConv\Version; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernel; @@ -24,7 +25,11 @@ final class SymfonyInstrumentation public static function register(): void { - $instrumentation = new CachedInstrumentation('io.opentelemetry.contrib.php.symfony'); + $instrumentation = new CachedInstrumentation( + 'io.opentelemetry.contrib.php.symfony', + null, + Version::VERSION_1_30_0->url(), + ); hook( HttpKernel::class, @@ -48,10 +53,10 @@ public static function register(): void ->tracer() ->spanBuilder($name) ->setSpanKind(($type === HttpKernelInterface::SUB_REQUEST) ? SpanKind::KIND_INTERNAL : SpanKind::KIND_SERVER) - ->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); $parent = Context::getCurrent(); if ($request) { @@ -101,9 +106,7 @@ public static function register(): void } if (null !== $exception) { - $span->recordException($exception, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + $span->recordException($exception); if (null !== $response && $response->getStatusCode() >= Response::HTTP_INTERNAL_SERVER_ERROR) { $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } @@ -159,9 +162,7 @@ public static function register(): void $throwable = $params[0]; Span::getCurrent() - ->recordException($throwable, [ - TraceAttributes::EXCEPTION_ESCAPED => true, - ]); + ->recordException($throwable); return $params; }, From fbd27b2ff9ae854a5a020a41e221b7316281ab8b Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:45:00 +1100 Subject: [PATCH 21/35] wordpress --- src/Instrumentation/Wordpress/composer.json | 3 ++- src/Instrumentation/Wordpress/psalm.xml.dist | 7 +++++++ .../src/WordpressInstrumentation.php | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Instrumentation/Wordpress/composer.json b/src/Instrumentation/Wordpress/composer.json index ba499d0a8..30ef2e74d 100644 --- a/src/Instrumentation/Wordpress/composer.json +++ b/src/Instrumentation/Wordpress/composer.json @@ -7,11 +7,12 @@ "readme": "./README.md", "license": "Apache-2.0", "minimum-stability": "dev", + "prefer-stable": true, "require": { "php": "^8.0", "ext-opentelemetry": "*", "open-telemetry/api": "^1.0", - "open-telemetry/sem-conv": "^1.24", + "open-telemetry/sem-conv": "^1.30", "nyholm/psr7": "^1", "nyholm/psr7-server": "^1" }, diff --git a/src/Instrumentation/Wordpress/psalm.xml.dist b/src/Instrumentation/Wordpress/psalm.xml.dist index 155711712..c9c51229e 100644 --- a/src/Instrumentation/Wordpress/psalm.xml.dist +++ b/src/Instrumentation/Wordpress/psalm.xml.dist @@ -12,4 +12,11 @@ + + + + + + + diff --git a/src/Instrumentation/Wordpress/src/WordpressInstrumentation.php b/src/Instrumentation/Wordpress/src/WordpressInstrumentation.php index f2677223a..d23198249 100644 --- a/src/Instrumentation/Wordpress/src/WordpressInstrumentation.php +++ b/src/Instrumentation/Wordpress/src/WordpressInstrumentation.php @@ -17,6 +17,9 @@ use OpenTelemetry\SemConv\TraceAttributes; use Throwable; +/** + * @phan-file-suppress PhanUndeclaredFunction + */ class WordpressInstrumentation { public const NAME = 'wordpress'; @@ -26,7 +29,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.wordpress', null, - 'https://opentelemetry.io/schemas/1.24.0' + 'https://opentelemetry.io/schemas/1.30.0' ); self::_hook($instrumentation, 'WP', 'main', 'WP.main'); @@ -48,9 +51,9 @@ class: 'wpdb', function: '__construct', pre: static function ($object, ?array $params, ?string $class, ?string $function, ?string $filename, ?int $lineno) use ($instrumentation) { $span = self::builder($instrumentation, 'wpdb.__connect', $function, $class, $filename, $lineno) - ->setAttribute(TraceAttributes::DB_USER, $params[0] ?? 'unknown') - ->setAttribute(TraceAttributes::DB_NAME, $params[2] ?? 'unknown') - ->setAttribute(TraceAttributes::DB_SYSTEM, 'mysql') + //->setAttribute(TraceAttributes::DB_USER, $params[0] ?? 'unknown') //deprecated, no replacement + ->setAttribute(TraceAttributes::DB_NAMESPACE, $params[2] ?? 'unknown') + ->setAttribute(TraceAttributes::DB_SYSTEM_NAME, 'mysql') ->startSpan(); Context::storage()->attach($span->storeInContext(Context::getCurrent())); }, @@ -68,7 +71,7 @@ function: 'query', pre: static function ($object, ?array $params, ?string $class, ?string $function, ?string $filename, ?int $lineno) use ($instrumentation) { $span = self::builder($instrumentation, 'wpdb.query', $function, $class, $filename, $lineno) ->setSpanKind(SpanKind::KIND_CLIENT) - ->setAttribute(TraceAttributes::DB_STATEMENT, $params[0] ?? 'undefined') + ->setAttribute(TraceAttributes::DB_QUERY_TEXT, $params[0] ?? 'undefined') ->startSpan(); Context::storage()->attach($span->storeInContext(Context::getCurrent())); }, @@ -157,10 +160,10 @@ private static function builder( /** @psalm-suppress ArgumentTypeCoercion */ return $instrumentation->tracer() ->spanBuilder($name) - ->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); } private static function end(?Throwable $exception): void @@ -172,7 +175,7 @@ private static function end(?Throwable $exception): void $scope->detach(); $span = Span::fromContext($scope->context()); if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From f3e7009b0e8753caa4ee5f072855feedc0158eb2 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:48:37 +1100 Subject: [PATCH 22/35] yii --- src/Instrumentation/Yii/.phan/config.php | 371 ++++++++++++++++++ src/Instrumentation/Yii/composer.json | 2 +- src/Instrumentation/Yii/psalm.xml.dist | 2 + .../Yii/src/YiiInstrumentation.php | 8 +- 4 files changed, 378 insertions(+), 5 deletions(-) create mode 100644 src/Instrumentation/Yii/.phan/config.php diff --git a/src/Instrumentation/Yii/.phan/config.php b/src/Instrumentation/Yii/.phan/config.php new file mode 100644 index 000000000..da2ac2d99 --- /dev/null +++ b/src/Instrumentation/Yii/.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/Yii/composer.json b/src/Instrumentation/Yii/composer.json index 28faa314a..1d0c58e75 100644 --- a/src/Instrumentation/Yii/composer.json +++ b/src/Instrumentation/Yii/composer.json @@ -11,7 +11,7 @@ "ext-opentelemetry": "*", "yiisoft/yii2": "^2.0.13", "open-telemetry/api": "^1", - "open-telemetry/sem-conv": "^1.24" + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", diff --git a/src/Instrumentation/Yii/psalm.xml.dist b/src/Instrumentation/Yii/psalm.xml.dist index e74348f05..7fce5be16 100644 --- a/src/Instrumentation/Yii/psalm.xml.dist +++ b/src/Instrumentation/Yii/psalm.xml.dist @@ -1,6 +1,8 @@ spanBuilder(sprintf('%s', $request->getMethod())) ->setParent($parent) ->setSpanKind(SpanKind::KIND_SERVER) - ->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) ->setAttribute(TraceAttributes::URL_FULL, $request->getAbsoluteUrl()) ->setAttribute(TraceAttributes::HTTP_REQUEST_METHOD, $request->getMethod()) ->setAttribute(TraceAttributes::HTTP_REQUEST_BODY_SIZE, $request->getHeaders()->get('Content-Length', null, true)) @@ -113,7 +113,7 @@ public static function register(): void } if ($exception) { - $span->recordException($exception, [TraceAttributes::EXCEPTION_ESCAPED => true]); + $span->recordException($exception); $span->setStatus(StatusCode::STATUS_ERROR, $exception->getMessage()); } From d8de072011653e1dc89b3c89cb1dcdda671df080 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:54:07 +1100 Subject: [PATCH 23/35] symfony --- src/Symfony/composer.json | 2 +- src/Symfony/src/OtelBundle/Console/ConsoleListener.php | 4 ++-- src/Symfony/src/OtelBundle/HttpKernel/RequestListener.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/composer.json b/src/Symfony/composer.json index 80081eeb5..20b056a75 100644 --- a/src/Symfony/composer.json +++ b/src/Symfony/composer.json @@ -13,7 +13,7 @@ "open-telemetry/context": "^1", "open-telemetry/exporter-otlp": "^1", "open-telemetry/exporter-zipkin": "^1", - "open-telemetry/sem-conv": "^1.23", + "open-telemetry/sem-conv": "^1.30", "php-http/discovery": "^1.14", "php-http/message": "^1.12" }, diff --git a/src/Symfony/src/OtelBundle/Console/ConsoleListener.php b/src/Symfony/src/OtelBundle/Console/ConsoleListener.php index 04caf6111..74aa4af64 100644 --- a/src/Symfony/src/OtelBundle/Console/ConsoleListener.php +++ b/src/Symfony/src/OtelBundle/Console/ConsoleListener.php @@ -28,7 +28,7 @@ public function __construct( $this->tracer = $tracerProvider->getTracer( OtelBundle::instrumentationName(), OtelBundle::instrumentationVersion(), - TraceAttributes::SCHEMA_URL, + 'https://opentelemetry.io/schemas/1.30.0', ); } @@ -60,7 +60,7 @@ public function startCommand(ConsoleCommandEvent $event): void $span = $this->tracer ->spanBuilder($name ?? 'command') - ->setAttribute(TraceAttributes::CODE_FUNCTION, 'run') + ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, 'run') ->setAttribute(TraceAttributes::CODE_NAMESPACE, $class) ->startSpan(); diff --git a/src/Symfony/src/OtelBundle/HttpKernel/RequestListener.php b/src/Symfony/src/OtelBundle/HttpKernel/RequestListener.php index 1b2e27d8f..b3afb00bd 100644 --- a/src/Symfony/src/OtelBundle/HttpKernel/RequestListener.php +++ b/src/Symfony/src/OtelBundle/HttpKernel/RequestListener.php @@ -57,7 +57,7 @@ public function __construct( $this->tracer = $tracerProvider->getTracer( OtelBundle::instrumentationName(), OtelBundle::instrumentationVersion(), - TraceAttributes::SCHEMA_URL, + 'https://opentelemetry.io/schemas/1.30.0', ); $this->propagator = $propagator; $this->propagationGetter = new HeadersPropagator(); From baaa1255ccadd16529ccd3459e06e7c4ccae4b67 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 16:54:17 +1100 Subject: [PATCH 24/35] logs --- src/Logs/Monolog/src/Handler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Logs/Monolog/src/Handler.php b/src/Logs/Monolog/src/Handler.php index d4fc86f35..60f7568b0 100644 --- a/src/Logs/Monolog/src/Handler.php +++ b/src/Logs/Monolog/src/Handler.php @@ -48,7 +48,7 @@ protected function write($record): void $formatted = $record['formatted']; $logRecord = (new API\LogRecord()) ->setTimestamp((int) $record['datetime']->format('Uu') * 1000) - ->setSeverityNumber(API\Map\Psr3::severityNumber($record['level_name'])) + ->setSeverityNumber(API\Severity::fromPsr3($record['level_name'])) ->setSeverityText($record['level_name']) ->setBody($formatted['message']) ; From d0206c96874ecb70a3a8a7280d16defa263b492b Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 17:00:53 +1100 Subject: [PATCH 25/35] hard-code schema url for 8.0-supporting packages on 8.0 these packages won't be able to use the SemConv::Version enum --- src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php | 2 +- .../CodeIgniter/src/CodeIgniterInstrumentation.php | 2 +- src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php | 2 +- .../HttpAsyncClient/src/HttpAsyncClientInstrumentation.php | 2 +- src/Instrumentation/Laravel/src/LaravelInstrumentation.php | 2 +- src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php | 2 +- src/Instrumentation/Psr14/src/Psr14Instrumentation.php | 2 +- src/Instrumentation/Psr15/src/Psr15Instrumentation.php | 2 +- src/Instrumentation/Psr16/src/Psr16Instrumentation.php | 2 +- src/Instrumentation/Psr18/src/Psr18Instrumentation.php | 2 +- src/Instrumentation/Psr3/src/Psr3Instrumentation.php | 2 +- src/Instrumentation/Psr6/src/Psr6Instrumentation.php | 2 +- src/Instrumentation/Slim/src/SlimInstrumentation.php | 2 +- src/Instrumentation/Symfony/src/HttpClientInstrumentation.php | 2 +- src/Instrumentation/Symfony/src/MessengerInstrumentation.php | 2 +- src/Instrumentation/Symfony/src/SymfonyInstrumentation.php | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php b/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php index 347cc5d01..e11b6a566 100644 --- a/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php +++ b/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php @@ -19,7 +19,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.cakephp', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); Server::hook($instrumentation); Controller::hook($instrumentation); diff --git a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php index 3438fc1c8..ef9baee2d 100644 --- a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php +++ b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php @@ -27,7 +27,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.codeigniter', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); // The method that creates request/response/controller objects is in the same class as the method diff --git a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php index 44b6f6232..f824e261d 100644 --- a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php +++ b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php @@ -32,7 +32,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.guzzle', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); hook( diff --git a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php index 10363dac3..b8591c571 100644 --- a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php +++ b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php @@ -27,7 +27,7 @@ public static function register(): void { $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.http-async-client', - schemaUrl: Version::VERSION_1_30_0->url() + schemaUrl: 'https://opentelemetry.io/schemas/1.30.0', ); hook( diff --git a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php index 3e2d52154..a8956fe1e 100644 --- a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php +++ b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php @@ -17,7 +17,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.laravel', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); Hooks\Illuminate\Console\Command::hook($instrumentation); diff --git a/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php b/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php index a8dc4ec5c..6544eb3e5 100644 --- a/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php +++ b/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php @@ -20,7 +20,7 @@ public static function register(?callable $commandSerializer = null): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.mongodb', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); $commandSerializer ??= self::defaultCommandSerializer(); /** @psalm-suppress UnusedFunctionCall */ diff --git a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php index 8690cbf95..13b250b6e 100644 --- a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php +++ b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php @@ -28,7 +28,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr14', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-psr14'), - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); /** diff --git a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php index 6d263c962..2e6db1dab 100644 --- a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php +++ b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php @@ -32,7 +32,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr15', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); /** diff --git a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php index ffeecea60..c83ccde5c 100644 --- a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php +++ b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php @@ -29,7 +29,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr16', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-psr16'), - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); $pre = static function (CacheInterface $cacheItem, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($instrumentation) { diff --git a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php index 2ea0ecefb..ee491fe0b 100644 --- a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php +++ b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php @@ -30,7 +30,7 @@ public static function register(): void { $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr18', - schemaUrl: Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); hook( diff --git a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php index faf0f5643..c9a47b95b 100644 --- a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php +++ b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php @@ -64,7 +64,7 @@ public static function register(): void $instrumentation ??= new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr3', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); if ($function === 'log') { $level = $params[0]; diff --git a/src/Instrumentation/Psr6/src/Psr6Instrumentation.php b/src/Instrumentation/Psr6/src/Psr6Instrumentation.php index 944fed2c0..e1f98a311 100644 --- a/src/Instrumentation/Psr6/src/Psr6Instrumentation.php +++ b/src/Instrumentation/Psr6/src/Psr6Instrumentation.php @@ -30,7 +30,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.psr6', InstalledVersions::getVersion('open-telemetry/opentelemetry-auto-psr6'), - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); $pre = static function (CacheItemPoolInterface $pool, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($instrumentation) { diff --git a/src/Instrumentation/Slim/src/SlimInstrumentation.php b/src/Instrumentation/Slim/src/SlimInstrumentation.php index 561fe8033..09b247cb2 100644 --- a/src/Instrumentation/Slim/src/SlimInstrumentation.php +++ b/src/Instrumentation/Slim/src/SlimInstrumentation.php @@ -33,7 +33,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.slim', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); /** diff --git a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php index d4f6d8ba1..e18975f3b 100644 --- a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php +++ b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php @@ -41,7 +41,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.symfony_http', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); hook( diff --git a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php index 5fa9f11ba..6637bc03f 100644 --- a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php +++ b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php @@ -38,7 +38,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.symfony_messenger', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); /** diff --git a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php index ff9bb79cb..5a8d14928 100644 --- a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php +++ b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php @@ -28,7 +28,7 @@ public static function register(): void $instrumentation = new CachedInstrumentation( 'io.opentelemetry.contrib.php.symfony', null, - Version::VERSION_1_30_0->url(), + 'https://opentelemetry.io/schemas/1.30.0', ); hook( From 34c5896945f3fdc951367002eac6c359deee3654 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 17:01:35 +1100 Subject: [PATCH 26/35] no-plugins for composer make targets this avoids the annoying 'do you trust...' composer questions --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 33e0c6e65..de4792958 100644 --- a/Makefile +++ b/Makefile @@ -19,9 +19,9 @@ build: ## Build image install: ## Install dependencies $(DC_RUN_PHP) env XDEBUG_MODE=off composer install update: ## Update dependencies - $(DC_RUN_PHP) env XDEBUG_MODE=off composer update + $(DC_RUN_PHP) env XDEBUG_MODE=off composer update --no-plugins update-lowest: ## Update dependencies to lowest supported versions - $(DC_RUN_PHP) env XDEBUG_MODE=off composer update --prefer-lowest + $(DC_RUN_PHP) env XDEBUG_MODE=off composer update --no-plugins --prefer-lowest test: ## Run all tests $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/phpunit --testdox --colors=always test-unit: ## Run unit tests @@ -39,7 +39,7 @@ psalm-info: ## Run psalm with info phpstan: ## Run phpstan $(DC_RUN_PHP) env XDEBUG_MODE=off vendor/bin/phpstan analyse --memory-limit=256M validate: ## Validate composer file - $(DC_RUN_PHP) env XDEBUG_MODE=off composer validate + $(DC_RUN_PHP) env XDEBUG_MODE=off composer validate --no-plugins packages-composer: ## Validate all composer packages $(DC_RUN) php env XDEBUG_MODE=off vendor/bin/otel packages:composer:validate bash: ## Bash shell From 09ed0165c897130f9c56a22a2768965d321e7915 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 17:20:52 +1100 Subject: [PATCH 27/35] drop 7.4 testing --- .github/workflows/php.yml | 44 +------------------ .../CakePHP/src/CakePHPInstrumentation.php | 1 - .../src/CodeIgniterInstrumentation.php | 1 - .../Guzzle/src/GuzzleInstrumentation.php | 1 - .../src/HttpAsyncClientInstrumentation.php | 1 - .../Laravel/src/LaravelInstrumentation.php | 1 - .../MongoDB/src/MongoDBInstrumentation.php | 1 - .../Psr14/src/Psr14Instrumentation.php | 1 - .../Psr15/src/Psr15Instrumentation.php | 1 - .../Psr16/src/Psr16Instrumentation.php | 1 - .../Psr18/src/Psr18Instrumentation.php | 1 - .../Psr3/src/Psr3Instrumentation.php | 1 - .../Psr6/src/Psr6Instrumentation.php | 1 - .../Slim/src/SlimInstrumentation.php | 1 - .../Symfony/src/HttpClientInstrumentation.php | 1 - .../Symfony/src/MessengerInstrumentation.php | 1 - .../Symfony/src/SymfonyInstrumentation.php | 1 - 17 files changed, 1 insertion(+), 59 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index dffd46f91..1b1309ceb 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['7.4', '8.0', '8.1', '8.2', '8.3'] + php-version: ['8.0', '8.1', '8.2', '8.3'] # Sorted alphabetically to ease finding the desired run in the GitHub Workflow UI. project: [ 'Aws', @@ -55,34 +55,6 @@ jobs: 'Symfony', ] exclude: - - project: 'Instrumentation/Guzzle' - php-version: 7.4 - - project: 'Instrumentation/HttpAsyncClient' - php-version: 7.4 - - project: 'Instrumentation/Slim' - php-version: 7.4 - - project: 'Instrumentation/Psr3' - php-version: 7.4 - - project: 'Instrumentation/Psr6' - php-version: 7.4 - - project: 'Instrumentation/Psr14' - php-version: 7.4 - - project: 'Instrumentation/Psr15' - php-version: 7.4 - - project: 'Instrumentation/Psr16' - php-version: 7.4 - - project: 'Instrumentation/Psr18' - php-version: 7.4 - - project: 'Instrumentation/IO' - php-version: 7.4 - - project: 'Instrumentation/Symfony' - php-version: 7.4 - - project: 'Instrumentation/Laravel' - php-version: 7.4 - - project: 'Instrumentation/CodeIgniter' - php-version: 7.4 - - project: 'Instrumentation/Yii' - php-version: 7.4 - project: 'Instrumentation/IO' php-version: 8.0 - project: 'Instrumentation/IO' @@ -105,8 +77,6 @@ jobs: php-version: 8.0 - project: 'Instrumentation/PDO' php-version: 8.1 - - project: 'Instrumentation/ExtAmqp' - php-version: 7.4 - project: 'Instrumentation/ExtAmqp' php-version: 8.0 - project: 'Instrumentation/ExtAmqp' @@ -117,22 +87,10 @@ jobs: php-version: 8.0 - project: 'Instrumentation/ExtRdKafka' php-version: 8.1 - - project: 'Instrumentation/OpenAIPHP' - php-version: 7.4 - project: 'Instrumentation/OpenAIPHP' php-version: 8.0 - - project: 'Instrumentation/CakePHP' - php-version: 7.4 - - project: 'Propagation/ServerTiming' - php-version: 7.4 - - project: 'ResourceDetectors/Container' - php-version: 7.4 - - project: 'Sampler/RuleBased' - php-version: 7.4 - project: 'Sampler/RuleBased' php-version: 8.0 - - project: 'Symfony' - php-version: 7.4 - project: 'Symfony' php-version: 8.0 steps: diff --git a/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php b/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php index e11b6a566..6442723f5 100644 --- a/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php +++ b/src/Instrumentation/CakePHP/src/CakePHPInstrumentation.php @@ -8,7 +8,6 @@ use OpenTelemetry\Contrib\Instrumentation\CakePHP\Hooks\Cake\Command\Command; use OpenTelemetry\Contrib\Instrumentation\CakePHP\Hooks\Cake\Controller\Controller; use OpenTelemetry\Contrib\Instrumentation\CakePHP\Hooks\Cake\Http\Server; -use OpenTelemetry\SemConv\Version; class CakePHPInstrumentation { diff --git a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php index ef9baee2d..9345190e1 100644 --- a/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php +++ b/src/Instrumentation/CodeIgniter/src/CodeIgniterInstrumentation.php @@ -16,7 +16,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; class CodeIgniterInstrumentation { diff --git a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php index f824e261d..8327f8f4f 100644 --- a/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php +++ b/src/Instrumentation/Guzzle/src/GuzzleInstrumentation.php @@ -15,7 +15,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use function sprintf; diff --git a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php index b8591c571..516eb4345 100644 --- a/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php +++ b/src/Instrumentation/HttpAsyncClient/src/HttpAsyncClientInstrumentation.php @@ -14,7 +14,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Throwable; diff --git a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php index a8956fe1e..2af06f418 100644 --- a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php +++ b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php @@ -6,7 +6,6 @@ use OpenTelemetry\API\Instrumentation\CachedInstrumentation; use OpenTelemetry\SDK\Common\Configuration\Configuration; -use OpenTelemetry\SemConv\Version; class LaravelInstrumentation { diff --git a/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php b/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php index 6544eb3e5..148acc8d1 100644 --- a/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php +++ b/src/Instrumentation/MongoDB/src/MongoDBInstrumentation.php @@ -6,7 +6,6 @@ use function MongoDB\Driver\Monitoring\addSubscriber; use OpenTelemetry\API\Instrumentation\CachedInstrumentation; -use OpenTelemetry\SemConv\Version; final class MongoDBInstrumentation { diff --git a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php index 13b250b6e..e15459942 100644 --- a/src/Instrumentation/Psr14/src/Psr14Instrumentation.php +++ b/src/Instrumentation/Psr14/src/Psr14Instrumentation.php @@ -11,7 +11,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\EventDispatcher\EventDispatcherInterface; use Throwable; diff --git a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php index 2e6db1dab..025966fde 100644 --- a/src/Instrumentation/Psr15/src/Psr15Instrumentation.php +++ b/src/Instrumentation/Psr15/src/Psr15Instrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; diff --git a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php index c83ccde5c..f2f55f3b1 100644 --- a/src/Instrumentation/Psr16/src/Psr16Instrumentation.php +++ b/src/Instrumentation/Psr16/src/Psr16Instrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\SimpleCache\CacheInterface; use Throwable; diff --git a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php index ee491fe0b..3d085bd5f 100644 --- a/src/Instrumentation/Psr18/src/Psr18Instrumentation.php +++ b/src/Instrumentation/Psr18/src/Psr18Instrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; diff --git a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php index c9a47b95b..e39b9e9ba 100644 --- a/src/Instrumentation/Psr3/src/Psr3Instrumentation.php +++ b/src/Instrumentation/Psr3/src/Psr3Instrumentation.php @@ -10,7 +10,6 @@ use OpenTelemetry\API\Trace\Span; use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; -use OpenTelemetry\SemConv\Version; use Psr\Log\LoggerInterface; use Psr\Log\LoggerTrait; diff --git a/src/Instrumentation/Psr6/src/Psr6Instrumentation.php b/src/Instrumentation/Psr6/src/Psr6Instrumentation.php index e1f98a311..3b6727e34 100644 --- a/src/Instrumentation/Psr6/src/Psr6Instrumentation.php +++ b/src/Instrumentation/Psr6/src/Psr6Instrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\Cache\CacheItemInterface; use Psr\Cache\CacheItemPoolInterface; use Throwable; diff --git a/src/Instrumentation/Slim/src/SlimInstrumentation.php b/src/Instrumentation/Slim/src/SlimInstrumentation.php index 09b247cb2..b90a18e70 100644 --- a/src/Instrumentation/Slim/src/SlimInstrumentation.php +++ b/src/Instrumentation/Slim/src/SlimInstrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\App; diff --git a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php index e18975f3b..53b0b77f0 100644 --- a/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php +++ b/src/Instrumentation/Symfony/src/HttpClientInstrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; diff --git a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php index 6637bc03f..1a3565ef3 100644 --- a/src/Instrumentation/Symfony/src/MessengerInstrumentation.php +++ b/src/Instrumentation/Symfony/src/MessengerInstrumentation.php @@ -11,7 +11,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; diff --git a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php index 5a8d14928..934e6632f 100644 --- a/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php +++ b/src/Instrumentation/Symfony/src/SymfonyInstrumentation.php @@ -13,7 +13,6 @@ use OpenTelemetry\Context\Context; use function OpenTelemetry\Instrumentation\hook; use OpenTelemetry\SemConv\TraceAttributes; -use OpenTelemetry\SemConv\Version; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernel; From 73b1952d00d9a8fbc40dc1f3ea698ed922085cd3 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 17:29:45 +1100 Subject: [PATCH 28/35] fixing build errors - bump psr3 + monolog deps to php8.1 - fix azure detector semconv, add composer dependency --- .github/workflows/php.yml | 6 ++++-- src/Instrumentation/Psr3/composer.json | 2 +- src/Logs/Monolog/composer.json | 1 + src/ResourceDetectors/Azure/composer.json | 3 ++- src/ResourceDetectors/Azure/src/AppService/Detector.php | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 1b1309ceb..ab56e2006 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -71,12 +71,12 @@ jobs: php-version: 8.0 - project: 'Instrumentation/MySqli' php-version: 8.1 - - project: 'Instrumentation/PDO' - php-version: 7.4 - 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' @@ -89,6 +89,8 @@ jobs: 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' diff --git a/src/Instrumentation/Psr3/composer.json b/src/Instrumentation/Psr3/composer.json index 942700d98..971ec8828 100644 --- a/src/Instrumentation/Psr3/composer.json +++ b/src/Instrumentation/Psr3/composer.json @@ -16,7 +16,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", diff --git a/src/Logs/Monolog/composer.json b/src/Logs/Monolog/composer.json index 95f1d0302..f9d87cc5d 100644 --- a/src/Logs/Monolog/composer.json +++ b/src/Logs/Monolog/composer.json @@ -9,6 +9,7 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { + "php": "^8.1", "monolog/monolog": "^1.1|^2|^3", "open-telemetry/api": "^1.0" }, diff --git a/src/ResourceDetectors/Azure/composer.json b/src/ResourceDetectors/Azure/composer.json index 456016633..dda9a0e38 100644 --- a/src/ResourceDetectors/Azure/composer.json +++ b/src/ResourceDetectors/Azure/composer.json @@ -15,7 +15,8 @@ "require": { "php": "^7.4 || ^8.0", "open-telemetry/api": "^1.0", - "open-telemetry/sdk": "^1.0" + "open-telemetry/sdk": "^1.0", + "open-telemetry/sem-conv": "^1.30" }, "require-dev": { "assertwell/phpunit-global-state": "^0.2.2", diff --git a/src/ResourceDetectors/Azure/src/AppService/Detector.php b/src/ResourceDetectors/Azure/src/AppService/Detector.php index d98a63540..6ed306dfa 100644 --- a/src/ResourceDetectors/Azure/src/AppService/Detector.php +++ b/src/ResourceDetectors/Azure/src/AppService/Detector.php @@ -60,7 +60,7 @@ public function getResource(): ResourceInfo ResourceAttributes::CLOUD_PROVIDER => self::CLOUD_PROVIDER, ResourceAttributes::CLOUD_REGION => getenv(self::ENV_REGION_NAME_KEY), ResourceAttributes::CLOUD_RESOURCE_ID => self::generateAzureResourceUri($name, $groupName, $subscriptionId), - ResourceAttributes::DEPLOYMENT_ENVIRONMENT => getenv(self::ENV_WEBSITE_SLOT_NAME_KEY), + ResourceAttributes::DEPLOYMENT_ENVIRONMENT_NAME => getenv(self::ENV_WEBSITE_SLOT_NAME_KEY), ResourceAttributes::HOST_ID => getenv(self::ENV_WEBSITE_HOSTNAME_KEY), ResourceAttributes::SERVICE_INSTANCE_ID => getenv(self::ENV_WEBSITE_INSTANCE_ID_KEY), ResourceAttributes::SERVICE_NAME => $name, From 01ce1821203b0e77641a10d8e22e9279948cc547 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 17:58:12 +1100 Subject: [PATCH 29/35] fixing more broken things --- .../Curl/tests/Integration/CurlMultiInstrumentationTest.php | 2 +- src/Instrumentation/Laravel/src/Watchers/LogWatcher.php | 5 +++-- .../Azure/tests/Unit/AppService/DetectorTest.php | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php b/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php index ebdd71503..13f825659 100644 --- a/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php +++ b/src/Instrumentation/Curl/tests/Integration/CurlMultiInstrumentationTest.php @@ -93,7 +93,7 @@ public function test_curl_multi_error() $this->assertCount(1, $this->storage); $span = $this->storage->offsetGet(0); - $this->assertEquals('curl_multi_exec', $span->getAttributes()->get(TraceAttributes::CODE_FUNCTION)); + $this->assertEquals('curl_multi_exec', $span->getAttributes()->get(TraceAttributes::CODE_FUNCTION_NAME)); $this->assertEquals('unknown://scheme.com/', actual: $span->getAttributes()->get(TraceAttributes::URL_FULL)); $this->assertSame('GET', $span->getName()); } diff --git a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php index 4b6e9eb9a..4070e970f 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\Severity; +use OpenTelemetry\API\Logs\Map\Psr3; use TypeError; class LogWatcher extends Watcher @@ -56,9 +56,10 @@ public function recordLog(MessageLogged $log): void $logger = $this->instrumentation->logger(); + /* @phan-suppressPhanUndeclaredClassMethod */ $record = (new LogRecord($log->message)) ->setSeverityText($log->level) - ->setSeverityNumber(Severity::fromPsr3($log->level)) + ->setSeverityNumber(Psr3::severityNumber($log->level)) ->setAttributes($attributes); $logger->emit($record); diff --git a/src/ResourceDetectors/Azure/tests/Unit/AppService/DetectorTest.php b/src/ResourceDetectors/Azure/tests/Unit/AppService/DetectorTest.php index 4c91ebf5a..e8cc97542 100644 --- a/src/ResourceDetectors/Azure/tests/Unit/AppService/DetectorTest.php +++ b/src/ResourceDetectors/Azure/tests/Unit/AppService/DetectorTest.php @@ -32,7 +32,7 @@ public function test_valid_app_service_attributes() [ResourceAttributes::CLOUD_PROVIDER, null, 'azure'], [ResourceAttributes::CLOUD_RESOURCE_ID, Detector::ENV_REGION_NAME_KEY, '/subscriptions/owner_name/resourceGroups/resouce_group/providers/Microsoft.Web/sites/demo-app'], [ResourceAttributes::CLOUD_REGION, Detector::ENV_REGION_NAME_KEY, 'westus'], - [ResourceAttributes::DEPLOYMENT_ENVIRONMENT, Detector::ENV_WEBSITE_SLOT_NAME_KEY, 'testing'], + [ResourceAttributes::DEPLOYMENT_ENVIRONMENT_NAME, Detector::ENV_WEBSITE_SLOT_NAME_KEY, 'testing'], [ResourceAttributes::HOST_ID, Detector::ENV_WEBSITE_HOSTNAME_KEY, 'example.com'], [ResourceAttributes::SERVICE_INSTANCE_ID, Detector::ENV_WEBSITE_INSTANCE_ID_KEY, uniqid()], [ResourceAttributes::SERVICE_NAME, Detector::ENV_WEBSITE_SITE_NAME_KEY, self::SERVICE_NAME], From 32b35cd57378ec70375337b1853a0efef6e13e3c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 18:11:06 +1100 Subject: [PATCH 30/35] laravel lint --- src/Instrumentation/Laravel/src/Watchers/LogWatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php index 4070e970f..5d31a5c63 100644 --- a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php @@ -56,7 +56,7 @@ public function recordLog(MessageLogged $log): void $logger = $this->instrumentation->logger(); - /* @phan-suppressPhanUndeclaredClassMethod */ + // @phan-suppressPhanUndeclaredClassMethod $record = (new LogRecord($log->message)) ->setSeverityText($log->level) ->setSeverityNumber(Psr3::severityNumber($log->level)) From a174a30040e9944140e861411eb99d5e5eb7d09f Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 20:33:23 +1100 Subject: [PATCH 31/35] fix laravel phan deprecation error --- src/Instrumentation/Laravel/src/Watchers/LogWatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php index 5d31a5c63..bdeb64588 100644 --- a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php +++ b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php @@ -32,6 +32,7 @@ public function register(Application $app): void /** * Record a log. + * @phan-suppress PhanDeprecatedFunction */ public function recordLog(MessageLogged $log): void { @@ -56,7 +57,6 @@ public function recordLog(MessageLogged $log): void $logger = $this->instrumentation->logger(); - // @phan-suppressPhanUndeclaredClassMethod $record = (new LogRecord($log->message)) ->setSeverityText($log->level) ->setSeverityNumber(Psr3::severityNumber($log->level)) From fea2bacbaf99ff5c0723c9dd166b2a3d405164c9 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Thu, 6 Feb 2025 20:38:24 +1100 Subject: [PATCH 32/35] skip failing cake test on 8.0 --- src/Instrumentation/CakePHP/tests/Integration/CommandTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php b/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php index 8473058ea..a1f77f186 100644 --- a/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php +++ b/src/Instrumentation/CakePHP/tests/Integration/CommandTest.php @@ -12,6 +12,9 @@ class CommandTest extends TestCase public function test_command_tracing(): void { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped(); + } $this->assertCount(0, $this->storage); $this->exec('dummy'); From 3d4232aa7ae1f4b588f0cd12bdaef9a897e2422c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Mon, 10 Feb 2025 11:38:05 +1100 Subject: [PATCH 33/35] fix message span names in semconv 1.27 the order of operation+queue switched --- .../ExtRdKafka/src/ExtRdKafkaInstrumentation.php | 4 ++-- .../tests/Integration/ExtRdKafkaInstrumentationTest.php | 6 +++--- .../Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php | 2 +- .../Laravel/tests/Integration/Queue/QueueTest.php | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php b/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php index 98afb317d..c0360c731 100644 --- a/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php +++ b/src/Instrumentation/ExtRdKafka/src/ExtRdKafkaInstrumentation.php @@ -75,7 +75,7 @@ private static function addProductionHooks($instrumentation) /** @var CachedInstrumentation $instrumentation */ $builder = $instrumentation ->tracer() - ->spanBuilder(sprintf('%s %s', $exchange->getName(), TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND)) + ->spanBuilder(sprintf('%s %s', TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND, $exchange->getName())) ->setSpanKind(SpanKind::KIND_PRODUCER) ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, $function) ->setAttribute(TraceAttributes::CODE_NAMESPACE, $class) @@ -148,7 +148,7 @@ private static function addConsumeHooks($instrumentation) $builder = $instrumentation ->tracer() // @phan-suppress-next-line PhanTypeMismatchArgumentInternal - Doesn't seem to know this has to be a string - ->spanBuilder(sprintf('%s %s', $message->topic_name, TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND)) + ->spanBuilder(sprintf('%s %s', TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND, $message->topic_name)) ->setSpanKind(SpanKind::KIND_CONSUMER) ->setAttribute(TraceAttributes::MESSAGING_SYSTEM, TraceAttributeValues::MESSAGING_SYSTEM_KAFKA) ->setAttribute(TraceAttributes::MESSAGING_OPERATION_TYPE, TraceAttributeValues::MESSAGING_OPERATION_TYPE_PROCESS) diff --git a/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php b/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php index 8de199d79..82d737af2 100644 --- a/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php +++ b/src/Instrumentation/ExtRdKafka/tests/Integration/ExtRdKafkaInstrumentationTest.php @@ -62,7 +62,7 @@ public function test_consume_creates_new_span(): void $this->assertCount(1, $this->storage); /** @var ImmutableSpan $span */ $span = $this->storage->offsetGet(0); - $this->assertEquals('test send', $span->getName()); + $this->assertEquals('send test', $span->getName()); } public function test_context_propagated_on_consumption(): void @@ -91,7 +91,7 @@ public function test_context_propagated_on_consumption(): void $this->assertCount(3, $this->storage); /** @var ImmutableSpan $span */ $span = $this->storage->offsetGet(2); - $this->assertEquals('test send', $span->getName()); + $this->assertEquals('send test', $span->getName()); $this->assertEquals($expectedTraceId, $span->getContext()->getTraceId()); } @@ -130,7 +130,7 @@ public function test_produce_creates_new_span() $this->assertCount(1, $this->storage); $span = $this->storage->offsetGet(0); - $this->assertEquals('test send', $span->getName()); + $this->assertEquals('send test', $span->getName()); } private function produceMessage( 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 531099b0a..f509fd2e3 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php @@ -49,9 +49,9 @@ protected function hookBulk(): bool $span = $this->instrumentation ->tracer() ->spanBuilder(vsprintf('%s %s', [ + TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND, /** @phan-suppress-next-line PhanUndeclaredMethod */ method_exists($queue, 'getQueue') ? $queue->getQueue($params[2] ?? null) : $queue->getConnectionName(), - TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND, ])) ->setSpanKind(SpanKind::KIND_PRODUCER) ->setAttributes($attributes) diff --git a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php index c4584a071..f370210df 100644 --- a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php @@ -86,7 +86,7 @@ public function test_it_can_publish_in_bulk(): void /** @psalm-suppress PossiblyUndefinedMethod */ $mockQueue->bulk($jobs); - $this->assertEquals('dummy-queue send', $this->storage[0]->getName()); + $this->assertEquals('send dummy-queue', $this->storage[0]->getName()); $this->assertEquals(10, $this->storage[0]->getAttributes()->get(TraceAttributes::MESSAGING_BATCH_MESSAGE_COUNT)); } @@ -107,7 +107,7 @@ public function test_it_can_create_with_redis(): void new DummyJob('B'), ]); - $this->assertEquals('queues:default send', $this->storage[0]->getName()); + $this->assertEquals('send queues:default', $this->storage[0]->getName()); $this->assertEquals(2, $this->storage[0]->getAttributes()->get(TraceAttributes::MESSAGING_BATCH_MESSAGE_COUNT)); $this->assertEquals('redis', $this->storage[0]->getAttributes()->get(TraceAttributes::MESSAGING_SYSTEM)); } From 223700d1db67f4e54c0e97dc9392f877a81d5d2c Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 12 Feb 2025 07:43:50 +1100 Subject: [PATCH 34/35] flip messaging span names --- .../Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php | 2 +- .../Laravel/src/Hooks/Illuminate/Queue/Worker.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 f509fd2e3..a0c2e1093 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php @@ -124,8 +124,8 @@ protected function hookPushRaw(): bool $span = $this->instrumentation ->tracer() ->spanBuilder(vsprintf('%s %s', [ - $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], TraceAttributeValues::MESSAGING_OPERATION_TYPE_CREATE, + $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], ])) ->setSpanKind(SpanKind::KIND_PRODUCER) ->setAttributes($attributes) diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php index 2e7ef69a4..a14455347 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php @@ -98,8 +98,8 @@ private function hookWorkerGetNextJob(): bool $span = $this->instrumentation ->tracer() ->spanBuilder(vsprintf('%s %s', [ - $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], TraceAttributeValues::MESSAGING_OPERATION_TYPE_RECEIVE, + $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], ])) ->setSpanKind(SpanKind::KIND_CONSUMER) ->setAttributes($attributes) From 402dc538eee911ea58d5846cf61225e71f6b6b58 Mon Sep 17 00:00:00 2001 From: Brett McBride Date: Wed, 12 Feb 2025 08:09:17 +1100 Subject: [PATCH 35/35] more messaging switch + fixed tests --- .../Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php | 2 +- .../Laravel/src/Hooks/Illuminate/Queue/Worker.php | 2 +- .../Laravel/tests/Integration/Queue/QueueTest.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) 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 a0c2e1093..197c05e1f 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php @@ -92,9 +92,9 @@ protected function hookLater(): bool $span = $this->instrumentation ->tracer() ->spanBuilder(vsprintf('%s %s', [ + TraceAttributeValues::MESSAGING_OPERATION_TYPE_CREATE, /** @phan-suppress-next-line PhanUndeclaredMethod */ method_exists($queue, 'getQueue') ? $queue->getQueue($params[2] ?? null) : $queue->getConnectionName(), - 'create', ])) ->setSpanKind(SpanKind::KIND_PRODUCER) ->setAttributes($attributes) diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php index a14455347..fb012cbae 100644 --- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php +++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php @@ -51,8 +51,8 @@ private function hookWorkerProcess(): bool $span = $this->instrumentation ->tracer() ->spanBuilder(vsprintf('%s %s', [ + TraceAttributeValues::MESSAGING_OPERATION_TYPE_PROCESS, $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME], - 'process', ])) ->setSpanKind(SpanKind::KIND_CONSUMER) ->setParent($parent) diff --git a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php index f370210df..63991dccf 100644 --- a/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php +++ b/src/Instrumentation/Laravel/tests/Integration/Queue/QueueTest.php @@ -55,17 +55,17 @@ public function test_it_can_push_a_message_with_a_delay(): void $this->queue->later(new DateInterval('PT10M'), new DummyJob('DateInterval')); $this->queue->later(new DateTimeImmutable('2024-04-15 22:29:00.123Z'), new DummyJob('DateTime')); - $this->assertEquals('sync create', $this->storage[2]->getName()); + $this->assertEquals('create sync', $this->storage[2]->getName()); $this->assertIsInt( $this->storage[2]->getAttributes()->get('messaging.message.delivery_timestamp'), ); - $this->assertEquals('sync create', $this->storage[5]->getName()); + $this->assertEquals('create sync', $this->storage[5]->getName()); $this->assertIsInt( $this->storage[5]->getAttributes()->get('messaging.message.delivery_timestamp'), ); - $this->assertEquals('sync create', $this->storage[8]->getName()); + $this->assertEquals('create sync', $this->storage[8]->getName()); $this->assertIsInt( $this->storage[8]->getAttributes()->get('messaging.message.delivery_timestamp'), );