From 498b8f39dca6cf886a5d9b41d74501011ba6c586 Mon Sep 17 00:00:00 2001 From: Michal Nowacki Date: Thu, 26 Sep 2024 16:46:59 -0400 Subject: [PATCH] feat(agent): use composer for vuln mgmt package info (#962) If possible, use Composer's runtime API to collect information about PHP packages used by the application for New Relic Vulnerability Management. This feature is disabled by default and can be enabled by setting `newrelic.vulnerability_management.composer_detection.enabled` to `true`. --------- Co-authored-by: Hitesh Ahuja Co-authored-by: bduranleau-nr <106178551+bduranleau-nr@users.noreply.github.com> Co-authored-by: Hitesh Ahuja <108540135+hahuja2@users.noreply.github.com> Co-authored-by: Amber Sistla Co-authored-by: Michael Fulbright <89205663+mfulb@users.noreply.github.com> --- agent/Makefile.frag | 1 + agent/config.m4 | 3 +- agent/fw_drupal.c | 10 + agent/fw_drupal8.c | 5 +- agent/fw_hooks.h | 1 + agent/fw_laminas3.c | 7 +- agent/fw_laravel.c | 5 +- agent/fw_lumen.c | 8 +- agent/fw_slim.c | 4 +- agent/fw_support.c | 26 +- agent/fw_support.h | 5 +- agent/fw_symfony4.c | 7 +- agent/fw_wordpress.c | 8 +- agent/fw_yii.c | 9 + agent/lib_aws_sdk_php.c | 6 +- agent/lib_composer.c | 272 ++++++++++++++++++ agent/lib_doctrine2.c | 7 +- agent/lib_guzzle4.c | 7 +- agent/lib_guzzle6.c | 22 +- agent/lib_mongodb.c | 7 +- agent/lib_monolog.c | 7 +- agent/lib_phpunit.c | 7 +- agent/lib_predis.c | 6 +- agent/php_execute.c | 37 ++- agent/php_newrelic.h | 2 + agent/php_nrini.c | 9 + agent/php_txn.c | 49 ++++ agent/php_txn_private.h | 21 ++ agent/scripts/newrelic.ini.template | 9 + agent/tests/test_fw_support.c | 136 +++++++-- agent/tests/test_lib_aws_sdk_php.c | 107 +++---- agent/tests/test_php_txn.c | 268 +++++++++++++++++ axiom/nr_php_packages.c | 49 +++- axiom/nr_php_packages.h | 77 ++++- axiom/nr_txn.c | 43 ++- axiom/nr_txn.h | 55 +++- axiom/tests/.gitignore | 1 + axiom/tests/test_php_packages.c | 181 +++++++++++- axiom/tests/test_txn.c | 128 +++++++++ .../newrelic/integration/php_packages.go | 66 +++-- daemon/internal/newrelic/integration/test.go | 72 ++++- .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 32 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 31 ++ .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 40 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 31 ++ .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 40 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 39 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 31 ++ .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 42 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 31 ++ .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 39 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 31 ++ .../vendor/autoload.php | 12 + .../integration/autoloader/composer-show.php | 26 ++ .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 32 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 36 +++ .../vendor/symfony/http-kernel/HttpKernel.php | 12 + .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 32 +++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 36 +++ .../src/Illuminate/Foundation/Application.php | 25 ++ .../vendor/autoload.php | 12 + .../vendor/composer/InstalledVersions.php | 51 ++++ .../vendor/composer/autoload_real.php | 9 + .../vendor/composer/installed.php | 44 +++ .../src/Illuminate/Foundation/Application.php | 25 ++ ...est_autoloader_with_broken_composer_00.php | 32 +++ ...est_autoloader_with_broken_composer_01.php | 32 +++ ...est_autoloader_with_broken_composer_02.php | 32 +++ ...test_autoloader_with_composer_disabled.php | 28 ++ .../test_autoloader_with_composer_enabled.php | 29 ++ ...ser_enabled_package_detection_disabled.php | 30 ++ ...utoloader_with_composer_throwing_error.php | 34 +++ ...oader_with_composer_throwing_exception.php | 34 +++ ...t_autoloader_without_composer_disabled.php | 23 ++ ...st_autoloader_without_composer_enabled.php | 27 ++ .../test_packages_with_broken_composer_00.php | 40 +++ .../test_packages_with_broken_composer_01.php | 41 +++ .../test_packages_with_broken_composer_02.php | 44 +++ .../logging/monolog2/test_monolog_basic.php | 4 +- .../logging/monolog2/test_monolog_cat.php | 4 +- .../monolog2/test_monolog_context_simple.php | 2 +- ...test_monolog_decoration_and_forwarding.php | 4 +- .../monolog2/test_monolog_disable_metrics.php | 4 +- .../monolog2/test_monolog_drop_empty.php | 4 +- .../test_monolog_large_message_limit.php | 4 +- ...test_monolog_large_message_limit_drops.php | 4 +- .../test_monolog_limit_log_events.php | 4 +- .../test_monolog_limit_zero_events.php | 4 +- ...log_events_max_samples_stored_invalid1.php | 4 +- ...log_events_max_samples_stored_invalid2.php | 4 +- ...log_events_max_samples_stored_invalid3.php | 4 +- ...log_events_max_samples_stored_invalid4.php | 4 +- .../test_monolog_log_level_filter.php | 4 +- .../test_monolog_log_level_filter_invalid.php | 4 +- .../logging/monolog3/test_monolog_basic.php | 4 +- .../logging/monolog3/test_monolog_cat.php | 4 +- .../monolog3/test_monolog_context_simple.php | 2 +- ...test_monolog_decoration_and_forwarding.php | 4 +- .../monolog3/test_monolog_disable_metrics.php | 4 +- .../monolog3/test_monolog_drop_empty.php | 4 +- .../test_monolog_large_message_limit.php | 4 +- ...test_monolog_large_message_limit_drops.php | 4 +- .../test_monolog_limit_log_events.php | 4 +- .../test_monolog_limit_zero_events.php | 4 +- ...log_events_max_samples_stored_invalid1.php | 4 +- ...log_events_max_samples_stored_invalid2.php | 4 +- ...log_events_max_samples_stored_invalid3.php | 4 +- ...log_events_max_samples_stored_invalid4.php | 4 +- .../test_monolog_log_level_filter.php | 4 +- .../test_monolog_log_level_filter_invalid.php | 4 +- 126 files changed, 2972 insertions(+), 235 deletions(-) create mode 100644 agent/lib_composer.c create mode 100644 agent/tests/test_php_txn.c create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-00/vendor/autoload.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-00/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-00/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-00/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-01/vendor/autoload.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-01/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-01/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-01/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-02/vendor/autoload.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-02/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/autoload-with-broken-composer-02/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/autoload.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/autoload.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/autoload-with-composer/vendor/autoload.php create mode 100644 tests/integration/autoloader/autoload-with-composer/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/autoload-with-composer/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/autoload-with-composer/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/autoload-without-composer/vendor/autoload.php create mode 100644 tests/integration/autoloader/composer-show.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-00/vendor/autoload.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-00/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-00/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-00/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-00/vendor/symfony/http-kernel/HttpKernel.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-01/vendor/autoload.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-01/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-01/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-01/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-01/vendor/laravel/framework/src/Illuminate/Foundation/Application.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-02/vendor/autoload.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-02/vendor/composer/InstalledVersions.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-02/vendor/composer/autoload_real.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-02/vendor/composer/installed.php create mode 100644 tests/integration/autoloader/packages-with-broken-composer-02/vendor/laravel/framework/src/Illuminate/Foundation/Application.php create mode 100644 tests/integration/autoloader/test_autoloader_with_broken_composer_00.php create mode 100644 tests/integration/autoloader/test_autoloader_with_broken_composer_01.php create mode 100644 tests/integration/autoloader/test_autoloader_with_broken_composer_02.php create mode 100644 tests/integration/autoloader/test_autoloader_with_composer_disabled.php create mode 100644 tests/integration/autoloader/test_autoloader_with_composer_enabled.php create mode 100644 tests/integration/autoloader/test_autoloader_with_composer_enabled_package_detection_disabled.php create mode 100644 tests/integration/autoloader/test_autoloader_with_composer_throwing_error.php create mode 100644 tests/integration/autoloader/test_autoloader_with_composer_throwing_exception.php create mode 100644 tests/integration/autoloader/test_autoloader_without_composer_disabled.php create mode 100644 tests/integration/autoloader/test_autoloader_without_composer_enabled.php create mode 100644 tests/integration/autoloader/test_packages_with_broken_composer_00.php create mode 100644 tests/integration/autoloader/test_packages_with_broken_composer_01.php create mode 100644 tests/integration/autoloader/test_packages_with_broken_composer_02.php diff --git a/agent/Makefile.frag b/agent/Makefile.frag index 1cfe1606c..648fc84b3 100644 --- a/agent/Makefile.frag +++ b/agent/Makefile.frag @@ -107,6 +107,7 @@ TEST_BINARIES = \ tests/test_php_minit \ tests/test_php_stack \ tests/test_php_stacked_segment \ + tests/test_php_txn \ tests/test_php_wrapper \ tests/test_predis \ tests/test_redis \ diff --git a/agent/config.m4 b/agent/config.m4 index a77122c37..ee0859e30 100644 --- a/agent/config.m4 +++ b/agent/config.m4 @@ -230,7 +230,8 @@ if test "$PHP_NEWRELIC" = "yes"; then fw_zend2.c fw_zend.c" LIBRARIES="lib_aws_sdk_php.c lib_monolog.c lib_doctrine2.c lib_guzzle3.c \ lib_guzzle4.c lib_guzzle6.c lib_guzzle_common.c \ - lib_mongodb.c lib_phpunit.c lib_predis.c lib_zend_http.c" + lib_mongodb.c lib_phpunit.c lib_predis.c lib_zend_http.c \ + lib_composer.c" PHP_NEW_EXTENSION(newrelic, $FRAMEWORKS $LIBRARIES $NEWRELIC_AGENT, $ext_shared,, \\$(NEWRELIC_CFLAGS)) PHP_SUBST(NEWRELIC_CFLAGS) diff --git a/agent/fw_drupal.c b/agent/fw_drupal.c index 12e43b5cf..3537f8b42 100644 --- a/agent/fw_drupal.c +++ b/agent/fw_drupal.c @@ -20,6 +20,8 @@ #include "util_memory.h" #include "util_strings.h" +#define PHP_PACKAGE_NAME "drupal/drupal" + /* * Set the Web Transaction (WT) name to "(cached page)" * @@ -879,4 +881,12 @@ void nr_drupal_enable(TSRMLS_D) { nr_php_user_function_add_declared_callback( NR_PSTR("drupal_http_request"), nr_drupal_replace_http_request TSRMLS_CC); #endif + + if (NRINI(vulnerability_management_package_detection_enabled)) { + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); + } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/fw_drupal8.c b/agent/fw_drupal8.c index 6593e17a8..541cb8b87 100644 --- a/agent/fw_drupal8.c +++ b/agent/fw_drupal8.c @@ -689,8 +689,6 @@ void nr_drupal_version() { if (NRINI(vulnerability_management_package_detection_enabled)) { nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); } nr_php_zval_free(&zval_version); @@ -762,4 +760,7 @@ void nr_drupal8_enable(TSRMLS_D) { nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/fw_hooks.h b/agent/fw_hooks.h index e78f65cbd..c4500aeb2 100644 --- a/agent/fw_hooks.h +++ b/agent/fw_hooks.h @@ -56,6 +56,7 @@ extern void nr_phpunit_enable(TSRMLS_D); extern void nr_predis_enable(TSRMLS_D); extern void nr_zend_http_enable(TSRMLS_D); extern void nr_monolog_enable(TSRMLS_D); +extern void nr_composer_handle_autoload(const char* filename); /* Vulnerability Management Packages */ extern void nr_drupal_version(void); diff --git a/agent/fw_laminas3.c b/agent/fw_laminas3.c index 604976bf0..a5d27de94 100644 --- a/agent/fw_laminas3.c +++ b/agent/fw_laminas3.c @@ -13,6 +13,8 @@ #include "util_logging.h" #include "util_memory.h" +#define PHP_PACKAGE_NAME "laminas/laminas-mvc" + /* * Laminas is a rebranding of Zend, but the logic remains the same, * it is simply a name change and corresponds directly to Zend 3.x. @@ -163,7 +165,10 @@ void nr_laminas3_enable(TSRMLS_D) { nr_laminas3_name_the_wt TSRMLS_CC); if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "laminas/laminas-mvc", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/fw_laravel.c b/agent/fw_laravel.c index 11718a7e6..bbac65b20 100644 --- a/agent/fw_laravel.c +++ b/agent/fw_laravel.c @@ -963,8 +963,9 @@ NR_PHP_WRAPPER(nr_laravel_application_construct) { // Add php package to transaction nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); if (version) { nrl_debug(NRL_FRAMEWORK, "Laravel version is " NRP_FMT, NRP_PHP(version)); diff --git a/agent/fw_lumen.c b/agent/fw_lumen.c index 239578ae1..2d34551f0 100644 --- a/agent/fw_lumen.c +++ b/agent/fw_lumen.c @@ -11,10 +11,13 @@ #include "php_wrapper.h" #include "php_hash.h" #include "fw_hooks.h" +#include "fw_support.h" #include "util_logging.h" #include "util_memory.h" #include "util_strings.h" +#define PHP_PACKAGE_NAME "laravel/lumen-framework" + /* * Sets the web transaction name. If strip_base == true, * leading class path components will be stripped. @@ -232,7 +235,10 @@ void nr_lumen_enable(TSRMLS_D) { #endif if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "laravel/lumen-framework", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/fw_slim.c b/agent/fw_slim.c index a70323459..facaeecc1 100644 --- a/agent/fw_slim.c +++ b/agent/fw_slim.c @@ -163,8 +163,8 @@ NR_PHP_WRAPPER(nr_slim_application_construct) { nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); nr_free(version); nr_php_scope_release(&this_var); diff --git a/agent/fw_support.c b/agent/fw_support.c index daff2692c..23c9c44c1 100644 --- a/agent/fw_support.c +++ b/agent/fw_support.c @@ -58,23 +58,39 @@ void nr_fw_support_add_logging_supportability_metric(nrtxn_t* txn, void nr_fw_support_add_package_supportability_metric( nrtxn_t* txn, const char* package_name, - const char* package_version) { - if (NULL == txn || NULL == package_name || NULL == package_version) { + const char* package_version, + nr_php_package_t* p) { + if (NULL == txn || NULL == package_name) { return; } char* metname = NULL; char major_version[MAJOR_VERSION_LENGTH] = {0}; + const char* version = package_version; + + // override provided package_version only if: + // - php_package is provided + // - its version is not NULL + // - its version is not PHP_PACKAGE_VERSION_UNKNOWN + if (NULL != p && NULL != p->package_version + && 0 != nr_strcmp(p->package_version, PHP_PACKAGE_VERSION_UNKNOWN)) { + version = p->package_version; + } + + // only generate metric if version is known + if (NULL == version || 0 == nr_strcmp(version, PHP_PACKAGE_VERSION_UNKNOWN)) { + return; + } /* The below for loop checks if the major version of the package is more than * one digit and keeps looping until a '.' is encountered or one of the * conditions is met. */ - for (int i = 0; package_version[i] && i < MAJOR_VERSION_LENGTH - 1; i++) { - if ('.' == package_version[i]) { + for (int i = 0; version[i] && i < MAJOR_VERSION_LENGTH - 1; i++) { + if ('.' == version[i]) { break; } - major_version[i] = package_version[i]; + major_version[i] = version[i]; } if (NR_FW_UNSET == NRINI(force_framework)) { diff --git a/agent/fw_support.h b/agent/fw_support.h index 5099a7d35..ad4b02722 100644 --- a/agent/fw_support.h +++ b/agent/fw_support.h @@ -8,6 +8,7 @@ #define FW_SUPPORT_HDR #include "php_user_instrument.h" +#include "nr_php_packages.h" extern void nr_php_framework_add_supportability_metric( const char* framework_name, @@ -44,11 +45,13 @@ extern void nr_fw_support_add_logging_supportability_metric( * Params : 1. Transaction object * 2. Package name * 3. Package version + * 4. PHP package reported for vulnerability management * */ extern void nr_fw_support_add_package_supportability_metric( nrtxn_t* txn, const char* package_name, - const char* package_version); + const char* package_version, + nr_php_package_t* p); #endif /* FW_SUPPORT_HDR */ diff --git a/agent/fw_symfony4.c b/agent/fw_symfony4.c index 6e1c9982d..8592186ac 100644 --- a/agent/fw_symfony4.c +++ b/agent/fw_symfony4.c @@ -10,6 +10,8 @@ #include "fw_support.h" #include "fw_symfony_common.h" +#define PHP_PACKAGE_NAME "symfony/http-kernel" + NR_PHP_WRAPPER(nr_symfony4_exception) { int priority = nr_php_error_get_priority(E_ERROR); zval* event = NULL; @@ -277,7 +279,10 @@ void nr_symfony4_enable(TSRMLS_D) { #endif if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "symfony/http-kernel", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/fw_wordpress.c b/agent/fw_wordpress.c index 55a0be5f0..050750f6a 100644 --- a/agent/fw_wordpress.c +++ b/agent/fw_wordpress.c @@ -804,8 +804,7 @@ void nr_wordpress_version() { "})();"; zval retval; - int result - = zend_eval_string(func_string, &retval, "Get Wordpress Version"); + int result = zend_eval_string(func_string, &retval, "Get Wordpress Version"); // Add php package to transaction if (SUCCESS == result) { if (nr_php_is_zval_valid_string(&retval)) { @@ -813,8 +812,9 @@ void nr_wordpress_version() { if (NRINI(vulnerability_management_package_detection_enabled)) { nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); } zval_dtor(&retval); } diff --git a/agent/fw_yii.c b/agent/fw_yii.c index 74aa19335..0b1af7c96 100644 --- a/agent/fw_yii.c +++ b/agent/fw_yii.c @@ -14,6 +14,7 @@ #include "util_memory.h" #include "util_strings.h" +#define PHP_PACKAGE_NAME "yiisoft/yii2" /* * Yii1: Set the web transaction name from the controllerId + actionId combo. * @@ -221,4 +222,12 @@ void nr_yii2_enable(TSRMLS_D) { nr_php_wrap_user_function(NR_PSTR("yii\\base\\ErrorHandler::logException"), nr_yii2_error_handler_wrapper TSRMLS_CC); #endif + + if (NRINI(vulnerability_management_package_detection_enabled)) { + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); + } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/lib_aws_sdk_php.c b/agent/lib_aws_sdk_php.c index cff08dbfd..ad956ac1e 100644 --- a/agent/lib_aws_sdk_php.c +++ b/agent/lib_aws_sdk_php.c @@ -69,8 +69,10 @@ void nr_lib_aws_sdk_php_handle_version() { /* Add php package to transaction */ nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); + nr_php_zval_free(&zval_version); } diff --git a/agent/lib_composer.c b/agent/lib_composer.c new file mode 100644 index 000000000..f6596639a --- /dev/null +++ b/agent/lib_composer.c @@ -0,0 +1,272 @@ +/* + * Copyright 2022 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "php_agent.h" +#include "fw_hooks.h" +#include "fw_support.h" +#include "nr_txn.h" +#include "util_logging.h" +#include "util_memory.h" +#include "util_syscalls.h" + +static bool nr_execute_handle_autoload_composer_is_initialized() { + zend_class_entry* zce = NULL; + + if (NULL == (zce = nr_php_find_class("composer\\installedversions"))) { + nrl_verbosedebug(NRL_INSTRUMENT, + "Composer\\InstalledVersions class not found"); + return false; + }; + + // the class is found - there's hope! + if (NULL == nr_php_find_class_method(zce, "getallrawdata") + || NULL == nr_php_find_class_method(zce, "getrootpackage")) { + nrl_verbosedebug( + NRL_INSTRUMENT, + "Composer\\InstalledVersions class found, but methods not found"); + return false; + } + + return true; +} + +static int nr_execute_handle_autoload_composer_init(const char* vendor_path) { + char* code = NULL; + zval retval; + int result = FAILURE; + + if (nr_execute_handle_autoload_composer_is_initialized()) { + nrl_verbosedebug(NRL_INSTRUMENT, "%s: already initialized", __func__); + return NR_SUCCESS; + } + + code = nr_formatf("include_once '%s/composer/InstalledVersions.php';", + vendor_path); + + result = zend_eval_string(code, &retval, "newrelic\\init_composer_api"); + if (result != SUCCESS) { + nrl_verbosedebug(NRL_INSTRUMENT, + "%s: zend_eval_string(%s) failed, result=%d", __func__, + code, result); + nr_free(code); + return NR_FAILURE; + } + + zval_dtor(&retval); + nr_free(code); + + // Make sure runtime API is available after loading + // Composer\\InstalledVersions class: + if (!nr_execute_handle_autoload_composer_is_initialized()) { + nrl_verbosedebug(NRL_INSTRUMENT, + "%s: unable to initialize Composer runtime API", __func__); + return NR_FAILURE; + } + + return NR_SUCCESS; +} + +static void nr_execute_handle_autoload_composer_get_packages_information( + const char* vendor_path) { + zval retval; // This is used as a return value for zend_eval_string. + // It will only be set if the result of the eval is SUCCESS. + int result = FAILURE; + + // nrunlikely because this should alredy be ensured by the caller + if (nrunlikely(!NRINI(vulnerability_management_package_detection_enabled))) { + // do nothing when collecting package information for vulnerability + // management is disabled + return; + } + + // nrunlikely because this should alredy be ensured by the caller + if (nrunlikely(!NRINI(vulnerability_management_composer_api_enabled))) { + // do nothing when use of composer to collect package info is disabled + return; + } + + // clang-format off + char* getallrawdata + = "" + "(function() {" + " try {" + " $root_package = \\Composer\\InstalledVersions::getRootPackage();" + " $packages = array();" + " foreach (\\Composer\\InstalledVersions::getAllRawData() as $installed) { " + " foreach ($installed['versions'] as $packageName => $packageData) {" + " if (!is_string($packageName)) {" + " continue;" + " }" + " if (is_array($root_package) && array_key_exists('name', $root_package) && $packageName == $root_package['name']) {" + " continue;" + " }" + " if (!array_key_exists('pretty_version', $packageData)) {" + " continue;" + " }" + " $pretty_version = $packageData['pretty_version'];" + " if (is_string($pretty_version)) {" + " $packages[$packageName] = ltrim($pretty_version, 'v');" + " }" + " }" + " }" + " return $packages;" + " } catch (Throwable $e) {" + " return NULL;" + " }" + "})();"; + // clang-format on + + if (NR_SUCCESS != nr_execute_handle_autoload_composer_init(vendor_path)) { + nrl_debug(NRL_INSTRUMENT, + "%s - unable to initialize Composer runtime API - package info " + "unavailable", + __func__); + return; + } + + nrl_verbosedebug(NRL_INSTRUMENT, "%s - Composer runtime API available", + __func__); + + result + = zend_eval_string(getallrawdata, &retval, "composer_getallrawdata.php"); + if (SUCCESS != result) { + nrl_verbosedebug(NRL_INSTRUMENT, "%s - composer_getallrawdata.php failed", + __func__); + return; + } + if (IS_ARRAY == Z_TYPE(retval)) { + zend_string* package_name = NULL; + zval* package_version = NULL; + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL(retval), package_name, + package_version) { + if (NULL == package_name || NULL == package_version) { + continue; + } + if (nr_php_is_zval_non_empty_string(package_version)) { + nrl_verbosedebug(NRL_INSTRUMENT, "package %s, version %s", + NRSAFESTR(ZSTR_VAL(package_name)), + NRSAFESTR(Z_STRVAL_P(package_version))); + nr_txn_add_php_package_from_source(NRPRG(txn), ZSTR_VAL(package_name), + Z_STRVAL_P(package_version), + NR_PHP_PACKAGE_SOURCE_COMPOSER); + } + } + ZEND_HASH_FOREACH_END(); + } else { + char strbuf[80]; + nr_format_zval_for_debug(&retval, strbuf, 0, sizeof(strbuf) - 1, 0); + nrl_verbosedebug(NRL_INSTRUMENT, + "%s - installed packages is: " NRP_FMT ", not an array", + __func__, NRP_ARGSTR(strbuf)); + } + zval_dtor(&retval); +} + +static char* nr_execute_handle_autoload_composer_get_vendor_path( + const char* filename) { + char* vendor_path = NULL; // result of dirname(filename) + char* cp = NULL; + + // nrunlikely because this should alredy be ensured by the caller + if (nrunlikely(NULL == filename)) { + nrl_verbosedebug(NRL_FRAMEWORK, "%s - filename is NULL", __func__); + return NULL; + } + + // vendor_path = dirname(filename): + // 1. copy filename to vendor_path + vendor_path = nr_strdup(filename); + // 2. // find last occurence of '/' in vendor_path + cp = nr_strrchr(vendor_path, '/'); + // 3. replace '/' with '\0' to get the directory path + if (NULL != cp) { + *cp = '\0'; + } else { + nrl_verbosedebug(NRL_FRAMEWORK, "%s - no '/' in filename '%s'", __func__, + filename); + } + + return vendor_path; +} + +static bool nr_execute_handle_autoload_composer_file_exists( + const char* vendor_path, + const char* filename) { + char* composer_magic_file = NULL; // vendor_path + filename + bool file_exists = false; + + // nrunlikely because this should alredy be ensured by the caller + if (nrunlikely(NULL == vendor_path)) { + nrl_verbosedebug(NRL_FRAMEWORK, "%s - vendor_path is NULL", __func__); + return false; + } + + // nrunlikely because this should alredy be ensured by the caller + if (nrunlikely(NULL == filename)) { + nrl_verbosedebug(NRL_FRAMEWORK, "%s - filename is NULL", __func__); + return false; + } + + composer_magic_file = nr_formatf("%s/%s", vendor_path, filename); + if (0 == nr_access(composer_magic_file, F_OK | R_OK)) { + file_exists = true; + } + nr_free(composer_magic_file); + return file_exists; +} + +void nr_composer_handle_autoload(const char* filename) { +// Composer signature file" +#define COMPOSER_MAGIC_FILE_1 "composer/autoload_real.php" +#define COMPOSER_MAGIC_FILE_1_LEN (sizeof(COMPOSER_MAGIC_FILE_1) - 1) +// Composer runtime API files: +#define COMPOSER_MAGIC_FILE_2 "composer/InstalledVersions.php" +#define COMPOSER_MAGIC_FILE_2_LEN (sizeof(COMPOSER_MAGIC_FILE_2) - 1) +#define COMPOSER_MAGIC_FILE_3 "composer/installed.php" +#define COMPOSER_MAGIC_FILE_3_LEN (sizeof(COMPOSER_MAGIC_FILE_3) - 1) + char* vendor_path = NULL; // result of dirname(filename) + + // nrunlikely because this should alredy be ensured by the caller + if (nrunlikely(NULL == filename)) { + nrl_verbosedebug(NRL_FRAMEWORK, "%s - filename is NULL", __func__); + return; + } + + vendor_path = nr_execute_handle_autoload_composer_get_vendor_path(filename); + if (NULL == vendor_path) { + nrl_verbosedebug(NRL_FRAMEWORK, "unable to get vendor path from '%s'", + filename); + return; + } + + if (!nr_execute_handle_autoload_composer_file_exists(vendor_path, + COMPOSER_MAGIC_FILE_1)) { + nrl_verbosedebug(NRL_FRAMEWORK, "'%s' not found in '%s'", + COMPOSER_MAGIC_FILE_1, vendor_path); + goto leave; + } + + if (!nr_execute_handle_autoload_composer_file_exists(vendor_path, + COMPOSER_MAGIC_FILE_2)) { + nrl_verbosedebug(NRL_FRAMEWORK, "'%s' not found in '%s'", + COMPOSER_MAGIC_FILE_2, vendor_path); + goto leave; + } + + if (!nr_execute_handle_autoload_composer_file_exists(vendor_path, + COMPOSER_MAGIC_FILE_3)) { + nrl_verbosedebug(NRL_FRAMEWORK, "'%s' not found in '%s'", + COMPOSER_MAGIC_FILE_3, vendor_path); + goto leave; + } + + nrl_verbosedebug(NRL_FRAMEWORK, "detected composer"); + NRPRG(txn)->composer_info.composer_detected = true; + nr_fw_support_add_library_supportability_metric(NRPRG(txn), "Composer"); + + nr_execute_handle_autoload_composer_get_packages_information(vendor_path); +leave: + nr_free(vendor_path); +} diff --git a/agent/lib_doctrine2.c b/agent/lib_doctrine2.c index e767d253f..8f8b8dfe3 100644 --- a/agent/lib_doctrine2.c +++ b/agent/lib_doctrine2.c @@ -16,6 +16,8 @@ #include "php_call.h" #include "lib_doctrine2.h" +#define PHP_PACKAGE_NAME "doctrine/orm" + /* * This answers the somewhat complicated question of whether we should * instrument DQL, which is dependent on the input query setting as well as SQL @@ -106,7 +108,10 @@ void nr_doctrine2_enable(TSRMLS_D) { #endif /* OAPI */ if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "doctrine/orm", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/lib_guzzle4.c b/agent/lib_guzzle4.c index f3dfc94e9..c52ddffff 100644 --- a/agent/lib_guzzle4.c +++ b/agent/lib_guzzle4.c @@ -33,6 +33,8 @@ #include "util_logging.h" #include "util_memory.h" +#define PHP_PACKAGE_NAME "guzzlehttp/guzzle" + /* * We rely on the const correctness of certain Zend functions that weren't * const correct before 5.3 and/or 5.4: since Guzzle 4 requires 5.4.0 anyway, @@ -520,9 +522,12 @@ void nr_guzzle4_enable(TSRMLS_D) { nr_guzzle_client_construct TSRMLS_CC); if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "guzzlehttp/guzzle", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } void nr_guzzle4_minit(TSRMLS_D) { diff --git a/agent/lib_guzzle6.c b/agent/lib_guzzle6.c index d9003545c..e65a684b7 100644 --- a/agent/lib_guzzle6.c +++ b/agent/lib_guzzle6.c @@ -359,15 +359,25 @@ NR_PHP_WRAPPER_START(nr_guzzle6_client_construct) { } /* - * If we were unable to get the full version before, at least we can extract - * the major version to send to the supportability metric. - * This is relevant to guzzle7+ which no longer supplies full version. - */ + * If we were unable to get the full version before, at least we can extract + * the major version to send to the supportability metric now, as + * this incomplete version will not be stored in a php package record + * and so the supportability metric cannot be created later like for + * most packages. + * + * This is relevant to guzzle7+ which no longer supplies full version. + */ if (NULL == version) { version = nr_php_get_object_constant(this_var, "MAJOR_VERSION"); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); + + /* if version is still NULL that is OK this next call will accept + * that value and when supportability metrics are made for + * packages if another method has determined the package version + * (composer api for example) then it will be filled in at that time + */ + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); nr_free(version); (void)wraprec; diff --git a/agent/lib_mongodb.c b/agent/lib_mongodb.c index c21e1e01b..8d129ae9d 100644 --- a/agent/lib_mongodb.c +++ b/agent/lib_mongodb.c @@ -18,6 +18,8 @@ #include "lib_mongodb_private.h" +#define PHP_PACKAGE_NAME "mongodb/mongodb" + static int nr_mongodb_is_server(const zval* obj TSRMLS_DC) { return nr_php_object_instanceof_class(obj, "MongoDB\\Driver\\Server" TSRMLS_CC); @@ -445,7 +447,10 @@ void nr_mongodb_enable() { #endif /* OAPI */ if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "mongodb/mongodb", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/lib_monolog.c b/agent/lib_monolog.c index 667e33583..fcdb1ac06 100644 --- a/agent/lib_monolog.c +++ b/agent/lib_monolog.c @@ -378,8 +378,8 @@ NR_PHP_WRAPPER(nr_monolog_logger_addrecord) { = nr_monolog_get_timestamp(api, argc, NR_EXECUTE_ORIG_ARGS TSRMLS_CC); char version[MAJOR_VERSION_LENGTH]; snprintf(version, sizeof(version), "%d", api); - nr_fw_support_add_package_supportability_metric(NRPRG(txn), - PHP_PACKAGE_NAME, version); + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); } /* Record the log event */ @@ -523,4 +523,7 @@ void nr_monolog_enable(TSRMLS_D) { nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/lib_phpunit.c b/agent/lib_phpunit.c index e41c55b29..4050bf969 100644 --- a/agent/lib_phpunit.c +++ b/agent/lib_phpunit.c @@ -14,6 +14,8 @@ #include "util_logging.h" #include "util_strings.h" +#define PHP_PACKAGE_NAME "phpunit/phpunit" + /* * PHPUnit instrumentation * ======================= @@ -697,7 +699,10 @@ void nr_phpunit_enable(TSRMLS_D) { nr_phpunit_instrument_testresult_adderror TSRMLS_CC); if (NRINI(vulnerability_management_package_detection_enabled)) { - nr_txn_add_php_package(NRPRG(txn), "phpunit/phpunit", + nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, PHP_PACKAGE_VERSION_UNKNOWN); } + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); } diff --git a/agent/lib_predis.c b/agent/lib_predis.c index b299c5595..607e11ed2 100644 --- a/agent/lib_predis.c +++ b/agent/lib_predis.c @@ -654,8 +654,10 @@ NR_PHP_WRAPPER(nr_predis_client_construct) { // Add php package to transaction nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); } - nr_fw_support_add_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, - version); + + nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, + version); + nr_free(version); /* diff --git a/agent/php_execute.c b/agent/php_execute.c index 3ecb33100..83ff4d5a9 100644 --- a/agent/php_execute.c +++ b/agent/php_execute.c @@ -411,7 +411,7 @@ static const nr_framework_table_t all_frameworks[] = { NR_PSTR("symfony/bundle/frameworkbundle/frameworkbundle.php"), 0, nr_symfony2_enable, NR_FW_SYMFONY2}, /* also Symfony 3 */ {"Symfony4", "symfony4", NR_PSTR("http-kernel/httpkernel.php"), 0, - nr_symfony4_enable, NR_FW_SYMFONY4}, /* also Symfony 5 */ + nr_symfony4_enable, NR_FW_SYMFONY4}, /* also Symfony 5/6/7 */ {"WordPress", "wordpress", NR_PSTR("wp-config.php"), 0, nr_wordpress_enable, NR_FW_WORDPRESS}, @@ -931,6 +931,40 @@ static void nr_execute_handle_library(const char* filename, } } +static void nr_execute_handle_autoload(const char* filename, + const size_t filename_len) { +#define AUTOLOAD_MAGIC_FILE "vendor/autoload.php" +#define AUTOLOAD_MAGIC_FILE_LEN (sizeof(AUTOLOAD_MAGIC_FILE) - 1) + + if (!NRINI(vulnerability_management_package_detection_enabled)) { + // do nothing when vulnerability management package detection is disabled + return; + } + + if (!NRINI(vulnerability_management_composer_api_enabled)) { + // do nothing when use of composer to collect package info is disabled + return; + } + + if (NRPRG(txn)->composer_info.autoload_detected) { + // autoload already handled + return; + } + + if (!nr_striendswith(STR_AND_LEN(filename), AUTOLOAD_MAGIC_FILE, + AUTOLOAD_MAGIC_FILE_LEN)) { + // not an autoload file + return; + } + + nrl_debug(NRL_FRAMEWORK, "detected autoload with %s, which ends with %s", + filename, AUTOLOAD_MAGIC_FILE); + NRPRG(txn)->composer_info.autoload_detected = true; + nr_fw_support_add_library_supportability_metric(NRPRG(txn), "Autoloader"); + + nr_composer_handle_autoload(filename); +} + static void nr_execute_handle_logging_framework(const char* filename, const size_t filename_len TSRMLS_DC) { @@ -999,6 +1033,7 @@ static void nr_php_user_instrumentation_from_file(const char* filename, nr_execute_handle_framework(all_frameworks, num_all_frameworks, filename, filename_len TSRMLS_CC); nr_execute_handle_library(filename, filename_len TSRMLS_CC); + nr_execute_handle_autoload(filename, filename_len); nr_execute_handle_logging_framework(filename, filename_len TSRMLS_CC); if (NRINI(vulnerability_management_package_detection_enabled)) { nr_execute_handle_package(filename); diff --git a/agent/php_newrelic.h b/agent/php_newrelic.h index 04ebd1ad2..1860b5167 100644 --- a/agent/php_newrelic.h +++ b/agent/php_newrelic.h @@ -593,6 +593,8 @@ nrinibool_t nrinibool_t vulnerability_management_package_detection_enabled; /* newrelic.vulnerability_management.package_detection.enabled */ +nrinibool_t + vulnerability_management_composer_api_enabled; /* newrelic.vulnerability_management.composer_api.enabled */ #if ZEND_MODULE_API_NO < ZEND_7_4_X_API_NO /* diff --git a/agent/php_nrini.c b/agent/php_nrini.c index 6fdd898d3..6c21d1bdf 100644 --- a/agent/php_nrini.c +++ b/agent/php_nrini.c @@ -3091,6 +3091,15 @@ STD_PHP_INI_ENTRY_EX("newrelic.vulnerability_management.package_detection.enable newrelic_globals, nr_enabled_disabled_dh) +STD_PHP_INI_ENTRY_EX("newrelic.vulnerability_management.composer_api.enabled", + "0", + NR_PHP_REQUEST, + nr_boolean_mh, + vulnerability_management_composer_api_enabled, + zend_newrelic_globals, + newrelic_globals, + nr_enabled_disabled_dh) + PHP_INI_END() /* } */ void nr_php_register_ini_entries(int module_number TSRMLS_DC) { diff --git a/agent/php_txn.c b/agent/php_txn.c index 785007b41..b5b57975c 100644 --- a/agent/php_txn.c +++ b/agent/php_txn.c @@ -19,10 +19,12 @@ #include "nr_agent.h" #include "nr_commands.h" #include "nr_header.h" +#include "nr_php_packages.h" #include "nr_rum.h" #include "nr_segment_children.h" #include "nr_txn.h" #include "nr_version.h" +#include "fw_support.h" #include "util_labels.h" #include "util_logging.h" #include "util_memory.h" @@ -711,6 +713,50 @@ void nr_php_txn_create_agent_php_version_metrics(nrtxn_t* txn) { nr_php_txn_create_php_version_metric(txn, version); } +void nr_php_txn_php_package_create_major_metric(void* value, + const char* key, + size_t key_len, + void* user_data) { + nrtxn_t* txn = (nrtxn_t*)user_data; + nr_php_package_t* suggested = value; + nr_php_package_t* actual = NULL; + + (void)key; + (void)key_len; + + if (NULL == txn) { + return; + } + + if (NULL == suggested) { + return; + } + + /* see if the actual packages has a version we can use over the + * one provided with the suggested package + */ + actual + = nr_php_packages_get_package(txn->php_packages, suggested->package_name); + + nrl_verbosedebug( + NRL_INSTRUMENT, + "Creating PHP Package Supportability Metric for package " + "'%s', suggested version '%s', actual version '%s'", + NRSAFESTR(suggested->package_name), NRSAFESTR(suggested->package_version), + NRSAFESTR(NULL != actual ? actual->package_version : "NULL")); + nr_fw_support_add_package_supportability_metric( + txn, suggested->package_name, suggested->package_version, actual); +} + +void nr_php_txn_create_packages_major_metrics(nrtxn_t* txn) { + if (NULL == txn) { + return; + } + + nr_php_packages_iterate(txn->php_package_major_version_metrics_suggestions, + nr_php_txn_php_package_create_major_metric, txn); +} + nr_status_t nr_php_txn_begin(const char* appnames, const char* license TSRMLS_DC) { nrtxnopt_t opts; @@ -1165,6 +1211,9 @@ nr_status_t nr_php_txn_end(int ignoretxn, int in_post_deactivate TSRMLS_DC) { /* Agent and PHP version metrics*/ nr_php_txn_create_agent_php_version_metrics(txn); + /* PHP packages major version metrics */ + nr_php_txn_create_packages_major_metrics(txn); + /* Add CPU and memory metrics */ nr_php_resource_usage_sampler_end(TSRMLS_C); diff --git a/agent/php_txn_private.h b/agent/php_txn_private.h index bf49eb107..6788877ad 100644 --- a/agent/php_txn_private.h +++ b/agent/php_txn_private.h @@ -65,3 +65,24 @@ extern void nr_php_txn_create_agent_version_metric(nrtxn_t* txn); */ extern void nr_php_txn_create_php_version_metric(nrtxn_t* txn, const char* version); + +/* + * Purpose : Callback for nr_php_packages_iterate to create major + * version metrics. + * + * Params : 1. PHP suggestion package version + * 2. PHP suggestion package name + * 3. PHP suggestion package name length + * 4. The current transaction (via userdata) + */ +extern void nr_php_txn_php_package_create_major_metric(void* value, + const char* key, + size_t key_len, + void* user_data); + +/* + * Purpose : Create and record metric for a package major versions. + * + * Params : 1. The current transaction. + */ +extern void nr_php_txn_create_packages_major_metrics(nrtxn_t* txn); diff --git a/agent/scripts/newrelic.ini.template b/agent/scripts/newrelic.ini.template index 0e5da6ab3..4ed06a091 100644 --- a/agent/scripts/newrelic.ini.template +++ b/agent/scripts/newrelic.ini.template @@ -1332,3 +1332,12 @@ newrelic.daemon.logfile = "/var/log/newrelic/newrelic-daemon.log" ; for vulnerability management. ; ;newrelic.vulnerability_management.package_detection.enabled = true + +; Setting: newrelic.vulnerability_management.composer_api.enabled +; Type : boolean +; Scope : per-directory +; Default: false +; Info : Toggles whether the agent should try using Composer's runtime API +; to gather package information for vulnerability management. +; +;newrelic.vulnerability_management.composer_api.enabled = false diff --git a/agent/tests/test_fw_support.c b/agent/tests/test_fw_support.c index c8b8e021d..980dc02aa 100644 --- a/agent/tests/test_fw_support.c +++ b/agent/tests/test_fw_support.c @@ -11,7 +11,12 @@ tlib_parallel_info_t parallel_info = {.suggested_nthreads = -1, .state_size = 0}; -static void test_fw_supportability_metrics(void) { +// When package detection for vulnerability management is disabled, +// txn->php_packages is not populated and package version cannot +// be obtained from php_package. This test is to ensure that +// the package supportability metric is created in case php_package +// is not available and that fallback version is used. +static void test_fw_supportability_metrics_with_vm_disabled(void) { #define LIBRARY_NAME "php-package" #define LIBRARY_MAJOR_VERSION "7" #define LIBRARY_MAJOR_VERSION_2 "10" @@ -22,9 +27,11 @@ static void test_fw_supportability_metrics(void) { #define LIBRARY_MAJOR_VERSION_7 "0.4.5" #define LIBRARY_METRIC "Supportability/library/" LIBRARY_NAME "/detected" #define LOGGING_LIBRARY_METRIC "Supportability/Logging/PHP/" LIBRARY_NAME -#define PACKAGE_METRIC "Supportability/PHP/package/" LIBRARY_NAME +#define PACKAGE_METRIC_PREFIX "Supportability/PHP/package/" +#define PACKAGE_METRIC PACKAGE_METRIC_PREFIX LIBRARY_NAME nrtxn_t t; nrtxn_t* txn = &t; + nr_php_package_t* php_package = NULL; txn->unscoped_metrics = nrm_table_create(10); /* NULL tests - don't blow up */ @@ -44,15 +51,18 @@ static void test_fw_supportability_metrics(void) { tlib_pass_if_int_equal("NULL logging library metric not created", 0, nrm_table_size(txn->unscoped_metrics)); - nr_fw_support_add_package_supportability_metric(NULL, LIBRARY_NAME, LIBRARY_MAJOR_VERSION); + nr_fw_support_add_package_supportability_metric( + NULL, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, php_package); tlib_pass_if_int_equal("package metric not created in NULL metrics", 0, nrm_table_size(txn->unscoped_metrics)); - nr_fw_support_add_package_supportability_metric(txn, NULL, LIBRARY_MAJOR_VERSION); + nr_fw_support_add_package_supportability_metric( + txn, NULL, LIBRARY_MAJOR_VERSION, php_package); tlib_pass_if_int_equal("NULL package name, metric not created", 0, nrm_table_size(txn->unscoped_metrics)); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, NULL); + nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, NULL, + php_package); tlib_pass_if_int_equal("NULL major version, metric not created", 0, nrm_table_size(txn->unscoped_metrics)); @@ -71,51 +81,51 @@ static void test_fw_supportability_metrics(void) { "happy path: logging library metric created", nrm_find(txn->unscoped_metrics, LOGGING_LIBRARY_METRIC "/disabled")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, php_package); tlib_pass_if_not_null("happy path test 1: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION "/detected")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION_2); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION_2, php_package); tlib_pass_if_not_null("happy path test 2: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION_2 "/detected")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION_3); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION_3, php_package); tlib_pass_if_not_null("happy path test 3: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION_3 "/detected")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION_4); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION_4, php_package); tlib_pass_if_not_null( "happy path test 4: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/1/detected")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION_5); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION_5, php_package); tlib_pass_if_not_null( "happy path test 5: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/12/detected")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION_6); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION_6, php_package); tlib_pass_if_not_null( "happy path test 6: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/123/detected")); - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION_7); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION_7, php_package); tlib_pass_if_not_null( "happy path test 7: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/0/detected")); NRINI(force_framework) = true; - nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, - LIBRARY_MAJOR_VERSION); + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, php_package); tlib_pass_if_not_null( "happy path test 8: package metric created", nrm_find(txn->unscoped_metrics, PACKAGE_METRIC "/7/forced")); @@ -123,6 +133,88 @@ static void test_fw_supportability_metrics(void) { nrm_table_destroy(&txn->unscoped_metrics); } +// When package detection for vulnerability management is enabled, +// txn->php_packages is populated and package version can be obtained +// from php_package stored in txn->php_packages. This test is to ensure +// that the package supportability metric is created in case php_package +// is available and that package version from php_package is used. +static void test_fw_supportability_metrics_with_vm_enabled(void) { +#define PHP_PACKAGE_MAJOR_VERSION "8" +#define PHP_PACKAGE_VERSION PHP_PACKAGE_MAJOR_VERSION ".4.0" + nrtxn_t t; + nrtxn_t* txn = &t; + nr_php_package_t php_package + = {.package_name = LIBRARY_NAME, + .package_version = PHP_PACKAGE_VERSION, + .source_priority = NR_PHP_PACKAGE_SOURCE_COMPOSER}; + nr_php_package_t php_package_null_version + = {.package_name = LIBRARY_NAME, + .package_version = NULL, + .source_priority = NR_PHP_PACKAGE_SOURCE_COMPOSER}; + nr_php_package_t php_package_unknown_version + = {.package_name = LIBRARY_NAME, + .package_version = PHP_PACKAGE_VERSION_UNKNOWN, + .source_priority = NR_PHP_PACKAGE_SOURCE_COMPOSER}; + txn->unscoped_metrics = nrm_table_create(10); + + NRINI(force_framework) = false; + nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, NULL, + &php_package_null_version); + tlib_pass_if_null( + "library major version metric not created when version is unknown - " + "version is NULL and package version is NULL", + nrm_get_metric(txn->unscoped_metrics, 0)); + + nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN, + &php_package_null_version); + tlib_pass_if_null( + "library major version metric not created when version is unknown - " + "version is PHP_PACKAGE_VERSION_UNKNOWN and package version is NULL", + nrm_get_metric(txn->unscoped_metrics, 0)); + + nr_fw_support_add_package_supportability_metric(txn, LIBRARY_NAME, NULL, + &php_package_unknown_version); + tlib_pass_if_null( + "library major version metric not created when version is unknown - " + "version is NULL and package version is PHP_PACKAGE_VERSION_UNKNOWN", + nrm_get_metric(txn->unscoped_metrics, 0)); + + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, &php_package); + tlib_pass_if_not_null( + "php package major version is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" PHP_PACKAGE_MAJOR_VERSION "/detected")); + + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, &php_package_null_version); + tlib_pass_if_not_null( + "library major version is used for 'detected' metric when php package " + "version is NULL", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION "/detected")); + + NRINI(force_framework) = true; + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, &php_package); + tlib_pass_if_not_null( + "php package major version is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" PHP_PACKAGE_MAJOR_VERSION "/forced")); + + nr_fw_support_add_package_supportability_metric( + txn, LIBRARY_NAME, LIBRARY_MAJOR_VERSION, &php_package_null_version); + tlib_pass_if_not_null( + "library major version is used for 'forced' metric when php package " + "version is NULL", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION "/detected")); + + nrm_table_destroy(&txn->unscoped_metrics); +} + void test_main(void* p NRUNUSED) { - test_fw_supportability_metrics(); + test_fw_supportability_metrics_with_vm_disabled(); + test_fw_supportability_metrics_with_vm_enabled(); } diff --git a/agent/tests/test_lib_aws_sdk_php.c b/agent/tests/test_lib_aws_sdk_php.c index 8ddffce9d..91fa88b26 100644 --- a/agent/tests/test_lib_aws_sdk_php.c +++ b/agent/tests/test_lib_aws_sdk_php.c @@ -80,14 +80,14 @@ static void test_nr_lib_aws_sdk_php_add_supportability_service_metric(void) { static void test_nr_lib_aws_sdk_php_handle_version(void) { #define LIBRARY_NAME "aws/aws-sdk-php" -#define LIBRARY_MAJOR_VERSION "7" -#define LIBRARY_MAJOR_VERSION_2 "10" -#define LIBRARY_MAJOR_VERSION_3 "100" -#define LIBRARY_MAJOR_VERSION_4 "4.23" -#define LIBRARY_MAJOR_VERSION_55 "55.34" -#define LIBRARY_MAJOR_VERSION_6123 "6123.45" -#define LIBRARY_MAJOR_VERSION_0 "0.4.5" -#define PACKAGE_METRIC "Supportability/PHP/package/" LIBRARY_NAME + const char* library_versions[] + = {"7", "10", "100", "4.23", "55.34", "6123.45", "0.4.5"}; + nr_php_package_t* p = NULL; +#define TEST_DESCRIPTION_FMT \ + "nr_lib_aws_sdk_php_handle_version with library_versions[%ld]=%s: package " \ + "major version metric - %s" + char* test_description = NULL; + size_t i = 0; /* * If lib_aws_sdk_php_handle_version function is ever called, we have already @@ -95,73 +95,54 @@ static void test_nr_lib_aws_sdk_php_handle_version(void) { */ /* - * Aws/Sdk exists. Should return aws package metric with + * Aws/Sdk class exists. Should create aws package metric suggestion with * version */ - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null("version test 1: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC - "/" LIBRARY_MAJOR_VERSION "/detected")); - tlib_php_request_end(); + for (i = 0; i < sizeof(library_versions) / sizeof(library_versions[0]); i++) { + tlib_php_request_start(); - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION_2); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null("version test 2: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC - "/" LIBRARY_MAJOR_VERSION_2 "/detected")); - tlib_php_request_end(); + declare_aws_sdk_class("Aws", "Sdk", library_versions[i]); + nr_lib_aws_sdk_php_handle_version(); - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION_3); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null("version test 3: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC - "/" LIBRARY_MAJOR_VERSION_3 "/detected")); - tlib_php_request_end(); + p = nr_php_packages_get_package( + NRPRG(txn)->php_package_major_version_metrics_suggestions, + LIBRARY_NAME); - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION_4); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null( - "version test 4: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC "/4/detected")); - tlib_php_request_end(); + test_description = nr_formatf(TEST_DESCRIPTION_FMT, i, library_versions[i], + "suggestion created"); + tlib_pass_if_not_null(test_description, p); + nr_free(test_description); - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION_55); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null( - "version test 5: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC "/55/detected")); - tlib_php_request_end(); + test_description = nr_formatf(TEST_DESCRIPTION_FMT, i, library_versions[i], + "suggested version set"); + tlib_pass_if_str_equal(test_description, library_versions[i], + p->package_version); + nr_free(test_description); - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION_6123); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null( - "version test 6: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC "/6123/detected")); - tlib_php_request_end(); - - tlib_php_request_start(); - declare_aws_sdk_class("Aws", "Sdk", LIBRARY_MAJOR_VERSION_0); - nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_not_null( - "version test 7: package metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC "/0/detected")); - tlib_php_request_end(); + tlib_php_request_end(); + } /* - * Aws/Sdk does not exist, should not return package metric if no version - * This case should never happen in real situations. + * Aws/Sdk class does not exist, should create package metric suggestion + * with PHP_PACKAGE_VERSION_UNKNOWN version. This case should never happen + * in real situations. */ tlib_php_request_start(); + nr_lib_aws_sdk_php_handle_version(); - tlib_pass_if_null("aws library metric created", - nrm_find(NRPRG(txn)->unscoped_metrics, PACKAGE_METRIC)); + + p = nr_php_packages_get_package( + NRPRG(txn)->php_package_major_version_metrics_suggestions, LIBRARY_NAME); + + tlib_pass_if_not_null( + "nr_lib_aws_sdk_php_handle_version when Aws\\Sdk class is not defined - " + "suggestion created", + p); + tlib_pass_if_str_equal( + "nr_lib_aws_sdk_php_handle_version when Aws\\Sdk class is not defined - " + "suggested version set to PHP_PACKAGE_VERSION_UNKNOWN", + PHP_PACKAGE_VERSION_UNKNOWN, p->package_version); + tlib_php_request_end(); } diff --git a/agent/tests/test_php_txn.c b/agent/tests/test_php_txn.c new file mode 100644 index 000000000..d0665bb26 --- /dev/null +++ b/agent/tests/test_php_txn.c @@ -0,0 +1,268 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "tlib_php.h" + +#include "php_agent.h" +#include "php_txn_private.h" + +#define LIBRARY_NAME "vendor_name/package_name" +#define LIBRARY_VERSION "1.2.3" +#define DEVEL_LIBRARY_VERSION "1.2.x-dev" +#define LIBRARY_MAJOR_VERSION "1" +#define COMPOSER_PACKAGE_VERSION "2.1.3" +#define COMPOSER_MAJOR_VERSION "2" +#define PACKAGE_METRIC_PREFIX "Supportability/PHP/package/" +#define PACKAGE_METRIC PACKAGE_METRIC_PREFIX LIBRARY_NAME + +tlib_parallel_info_t parallel_info = {.suggested_nthreads = 1, .state_size = 0}; + +nr_php_package_t php_package + = {.package_name = LIBRARY_NAME, + .package_version = LIBRARY_VERSION, + .source_priority = NR_PHP_PACKAGE_SOURCE_COMPOSER}; + +static void test_nr_php_txn_php_package_create_major_metric() { + nrtxn_t t; + nrtxn_t* txn = &t; + + txn->unscoped_metrics = nrm_table_create(10); + txn->php_packages = nr_php_packages_create(); + txn->php_package_major_version_metrics_suggestions = nr_php_packages_create(); + + tlib_php_request_start(); + + /* need to call callback with invalid values to make sure it doesnt crash + * code depends on txn and txn->php_packages existing so these are created + * above with the package suggestions data structure included for good measure + */ + + /* this tests these params in callback: + * suggested = NULL + * actual = NULL + * key = NULL + * txn = NULL + */ + nr_php_txn_php_package_create_major_metric(NULL, NULL, 0, NULL); + tlib_pass_if_int_equal("NULL txn, metric not created", 0, + nrm_table_size(txn->unscoped_metrics)); + + /* this tests these params in callback: + * suggested = NULL + * actual = NULL + * key != NULL + * txn != NULL + */ + nr_php_txn_php_package_create_major_metric(NULL, LIBRARY_NAME, + strlen(LIBRARY_NAME), (void*)txn); + tlib_pass_if_int_equal("NULL value, metric not created", 0, + nrm_table_size(txn->unscoped_metrics)); + + /* the key is not actually used by the callback - just the package name + * in the suggested package so this casee will still create a metric + */ + /* this tests these params in callback: + * suggested != NULL + * actual = NULL + * key = NULL + * txn = != NULL + */ + nr_php_txn_php_package_create_major_metric(&php_package, NULL, 0, (void*)txn); + tlib_pass_if_int_equal("NULL key, metric created", 1, + nrm_table_size(txn->unscoped_metrics)); + + /* cleanup */ + nr_php_packages_destroy(&txn->php_packages); + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); + nrm_table_destroy(&txn->unscoped_metrics); + + tlib_php_request_end(); +} + +static void test_nr_php_txn_create_packages_major_metrics() { + nrtxn_t t; + nrtxn_t* txn = &t; + + txn->unscoped_metrics = nrm_table_create(10); + txn->php_packages = nr_php_packages_create(); + txn->php_package_major_version_metrics_suggestions = nr_php_packages_create(); + + tlib_php_request_start(); + + /* invalid txn should not crash */ + nr_php_txn_create_packages_major_metrics(NULL); + tlib_pass_if_int_equal("NULL txn, metric not created", 0, + nrm_table_size(txn->unscoped_metrics)); + + /* test with valid txn no package suggestions */ + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("valid txn with no suggestions, metric not created", 0, + nrm_table_size(txn->unscoped_metrics)); + + /* + * Tests: + * 1. suggestion with NULL version, no packages + * 2. suggestion with PHP_PACKAGE_VERSION_UNKNOWN version, no packages + * 3. suggestion with known version, no packages + * 4. package with known version and suggestion with known version + * 5. package with known version and suggestion with unknown version + * 6. package with unknown version and suggestion with known version + * 7. package with unknown version and suggestion with unknown version + * 8. test that causes "actual" to be NULL in callback + * 9. package with known "dev" version with and suggestion with unknown version + */ + + /* 1. suggestion with NULL version, no packages */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, NULL); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("suggestion with NULL version, metric not created", 0, + nrm_table_size(txn->unscoped_metrics)); + + /* 2. suggestion with PHP_PACKAGE_VERSION_UNKNOWN version, no packages + * also + * 8. test that causes "actual" to be NULL in callback + */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal( + "suggestion with PHP_PACKAGE_VERSION_UNKNOWN version, metric not created", + 0, nrm_table_size(txn->unscoped_metrics)); + + /* 3. suggestion with known version, no packages + * also + * 8. test that causes "actual" to be NULL in callback + */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, + LIBRARY_VERSION); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("suggestion with valid version, metric created", 1, + nrm_table_size(txn->unscoped_metrics)); + tlib_pass_if_not_null( + "php package major version is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION "/detected")); + + /* reset metrics */ + nrm_table_destroy(&txn->unscoped_metrics); + txn->unscoped_metrics = nrm_table_create(10); + + /* 4. package with known version and suggestion with known version + * + * add a package with a "better" version determined from composer api + * and use existing suggestion which has a different version + */ + nr_txn_add_php_package_from_source(txn, LIBRARY_NAME, + COMPOSER_PACKAGE_VERSION, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("suggestion with valid version, metric created", 1, + nrm_table_size(txn->unscoped_metrics)); + tlib_pass_if_not_null( + "php package major version is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" COMPOSER_MAJOR_VERSION "/detected")); + + /* reset suggestions, leave package with known version in place */ + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); + txn->php_package_major_version_metrics_suggestions = nr_php_packages_create(); + + /* reset metrics */ + nrm_table_destroy(&txn->unscoped_metrics); + txn->unscoped_metrics = nrm_table_create(10); + + /* 5. package with known version and suggestion with unknown version + * + * add a suggestion with no version and test metric uses package version + */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("suggestion with valid version, metric created", 1, + nrm_table_size(txn->unscoped_metrics)); + tlib_pass_if_not_null( + "php package major version is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" COMPOSER_MAJOR_VERSION "/detected")); + + /* reset everything */ + nrm_table_destroy(&txn->unscoped_metrics); + txn->unscoped_metrics = nrm_table_create(10); + nr_php_packages_destroy(&txn->php_packages); + txn->php_packages = nr_php_packages_create(); + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); + txn->php_package_major_version_metrics_suggestions = nr_php_packages_create(); + + /* 6. package with unknown version and suggestion with known version */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, + LIBRARY_VERSION); + nr_txn_add_php_package_from_source(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("suggestion with valid version, metric created", 1, + nrm_table_size(txn->unscoped_metrics)); + tlib_pass_if_not_null( + "php package suggestion major version is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION "/detected")); + + /* reset everything */ + nrm_table_destroy(&txn->unscoped_metrics); + txn->unscoped_metrics = nrm_table_create(10); + nr_php_packages_destroy(&txn->php_packages); + txn->php_packages = nr_php_packages_create(); + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); + txn->php_package_major_version_metrics_suggestions = nr_php_packages_create(); + + /* 7. package with unknown version and suggestion with unknown version */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); + nr_txn_add_php_package_from_source(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal( + "suggestion and package w/o version, metric not created", 0, + nrm_table_size(txn->unscoped_metrics)); + + /* reset everything */ + nrm_table_destroy(&txn->unscoped_metrics); + txn->unscoped_metrics = nrm_table_create(10); + nr_php_packages_destroy(&txn->php_packages); + txn->php_packages = nr_php_packages_create(); + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); + txn->php_package_major_version_metrics_suggestions = nr_php_packages_create(); + + /* 9. package with known "dev" version with and suggestion with unknown version */ + nr_txn_suggest_package_supportability_metric(txn, LIBRARY_NAME, + PHP_PACKAGE_VERSION_UNKNOWN); + nr_txn_add_php_package_from_source(txn, LIBRARY_NAME, + DEVEL_LIBRARY_VERSION, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + nr_php_txn_create_packages_major_metrics(txn); + tlib_pass_if_int_equal("suggestion with valid 'dev' version, metric created", 1, + nrm_table_size(txn->unscoped_metrics)); + tlib_pass_if_not_null( + "php package suggestion major version with 'dev' is used for 'detected' metric", + nrm_find(txn->unscoped_metrics, + PACKAGE_METRIC "/" LIBRARY_MAJOR_VERSION "/detected")); + + + /* cleanup */ + nr_php_packages_destroy(&txn->php_packages); + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); + nrm_table_destroy(&txn->unscoped_metrics); + + tlib_php_request_end(); +} + + +void test_main(void* p NRUNUSED) { + tlib_php_engine_create(""); + test_nr_php_txn_php_package_create_major_metric(); + test_nr_php_txn_create_packages_major_metrics(); + tlib_php_engine_destroy(); +} diff --git a/axiom/nr_php_packages.c b/axiom/nr_php_packages.c index 9c1f97ef8..b8a034086 100644 --- a/axiom/nr_php_packages.c +++ b/axiom/nr_php_packages.c @@ -23,7 +23,23 @@ typedef struct { bool package_added; } nr_php_package_json_builder_t; -nr_php_package_t* nr_php_package_create(char* name, char* version) { +static inline const char* nr_php_package_source_priority_to_string(const nr_php_package_source_priority_t source_priority) { + switch (source_priority) { + case NR_PHP_PACKAGE_SOURCE_SUGGESTION: + return "suggestion"; + case NR_PHP_PACKAGE_SOURCE_LEGACY: + return "legacy"; + case NR_PHP_PACKAGE_SOURCE_COMPOSER: + return "composer"; + default: + return "unknown"; + } +} + +nr_php_package_t* nr_php_package_create_with_source( + const char* name, + const char* version, + const nr_php_package_source_priority_t source_priority) { nr_php_package_t* p = NULL; if (NULL == name) { @@ -43,12 +59,17 @@ nr_php_package_t* nr_php_package_create(char* name, char* version) { PHP_PACKAGE_VERSION_UNKNOWN); // if null, version is set to an empty // string with a space according to spec } + p->source_priority = source_priority; - nrl_verbosedebug(NRL_INSTRUMENT, "Creating PHP Package '%s', version '%s'", - p->package_name, p->package_version); + nrl_verbosedebug(NRL_INSTRUMENT, "Creating PHP Package '%s', version '%s', source %s", + p->package_name, p->package_version, nr_php_package_source_priority_to_string(source_priority)); return p; } +nr_php_package_t* nr_php_package_create(const char* name, const char* version) { + return nr_php_package_create_with_source(name, version, NR_PHP_PACKAGE_SOURCE_LEGACY); +} + void nr_php_package_destroy(nr_php_package_t* p) { if (NULL != p) { nr_free(p->package_name); @@ -72,14 +93,15 @@ nr_php_packages_t* nr_php_packages_create() { return h; } -void nr_php_packages_add_package(nr_php_packages_t* h, nr_php_package_t* p) { +nr_php_package_t* nr_php_packages_add_package(nr_php_packages_t* h, + nr_php_package_t* p) { nr_php_package_t* package; if (NULL == h) { - return; + return NULL; } if (NULL == p || NULL == p->package_name || NULL == p->package_version) { - return; + return NULL; } // If package with the same key already exists, we will check if the value is @@ -87,15 +109,26 @@ void nr_php_packages_add_package(nr_php_packages_t* h, nr_php_package_t* p) { package = (nr_php_package_t*)nr_hashmap_get(h->data, p->package_name, nr_strlen(p->package_name)); if (NULL != package) { - if (0 != nr_strcmp(package->package_version, p->package_version)) { + if (package->source_priority <= p->source_priority && 0 != nr_strcmp(package->package_version, p->package_version)) { nr_free(package->package_version); package->package_version = nr_strdup(p->package_version); } nr_php_package_destroy(p); - return; + return package; } nr_hashmap_set(h->data, p->package_name, nr_strlen(p->package_name), p); + return p; +} + +void nr_php_packages_iterate(nr_php_packages_t* packages, + nr_php_packages_iter_t callback, + void* userdata) { + if (NULL == packages || NULL == callback) { + return; + } + + nr_hashmap_apply(packages->data, (nr_hashmap_apply_func_t)callback, userdata); } char* nr_php_package_to_json(nr_php_package_t* package) { diff --git a/axiom/nr_php_packages.h b/axiom/nr_php_packages.h index 118a63f79..f4945c43e 100644 --- a/axiom/nr_php_packages.h +++ b/axiom/nr_php_packages.h @@ -10,32 +10,65 @@ #include "util_random.h" #include "util_vector.h" #include "util_hashmap.h" +#include "util_strings.h" #define PHP_PACKAGE_VERSION_UNKNOWN " " +typedef enum { + NR_PHP_PACKAGE_SOURCE_SUGGESTION, + NR_PHP_PACKAGE_SOURCE_LEGACY, + NR_PHP_PACKAGE_SOURCE_COMPOSER +} nr_php_package_source_priority_t; + typedef struct _nr_php_package_t { char* package_name; char* package_version; + nr_php_package_source_priority_t source_priority; } nr_php_package_t; typedef struct _nr_php_packages_t { nr_hashmap_t* data; } nr_php_packages_t; +typedef void(nr_php_packages_iter_t)(void* value, + const char* name, + size_t name_len, + void* user_data); + /* - * Purpose : Create a new php package. If the name is null, then no package will + * Purpose : Create a new php package with desired source priority. If the name is null, then no package will * be created. If the version is null (version = NULL), then * the package will still be created and the version will be set to an * empty string with a space. * * Params : 1. Package name * 2. Package version + * 3. Package source priority (legacy or composer) * * Returns : A php package that has a name and version. If * nr_php_packages_add_package() is not called, then it must be freed * by nr_php_package_destroy() */ -extern nr_php_package_t* nr_php_package_create(char* name, char* version); +extern nr_php_package_t* nr_php_package_create_with_source( + const char* name, + const char* version, + const nr_php_package_source_priority_t source_priority); + +/* + * Purpose : Create a new php package with legacy source priority. If the name is null, then no package will + * be created. If the version is null (version = NULL), then + * the package will still be created and the version will be set to an + * empty string with a space. + * + * Params : 1. Package name + * 2. Package version + * + * Returns : A php package that has a name and version. If + * nr_php_packages_add_package() is not called, then it must be freed + * by nr_php_package_destroy() + */ +extern nr_php_package_t* nr_php_package_create(const char* name, + const char* version); /* * Purpose : Destroy/free php package @@ -64,10 +97,10 @@ extern nr_php_packages_t* nr_php_packages_create(void); * 2. A pointer to the php package that needs to be added to the * collection * - * Returns : Nothing + * Returns : pointer to added package on success or NULL otherwise. */ -extern void nr_php_packages_add_package(nr_php_packages_t* h, - nr_php_package_t* p); +extern nr_php_package_t* nr_php_packages_add_package(nr_php_packages_t* h, + nr_php_package_t* p); /* * Purpose : Destroy/free the collection @@ -118,6 +151,40 @@ static inline int nr_php_packages_has_package(nr_php_packages_t* h, return 0; } +/* + * Purpose : Retrieve a pointer to php package from the collection + * + * Params : 1. A pointer to nr_php_packages_t + * 2. The name of the package to retrieve + * + * Returns : Returns pointer to php package if the package exists or NULL + */ +static inline nr_php_package_t* nr_php_packages_get_package( + nr_php_packages_t* php_packages, + const char* package_name) { + if (NULL == package_name) { + return NULL; + } + + if (nrlikely(NULL != php_packages && NULL != php_packages->data)) { + return (nr_php_package_t*)nr_hashmap_get(php_packages->data, package_name, nr_strlen(package_name)); + } + return NULL; +} + +/* + * Purpose : Iterate over packages calling callback function + * + * Params : 1. A pointer to nr_php_packages_t + * 2. Callback function (nr_php_packages_iter_t) + * 3. Pointer to user data (can be NULL) + * + * Returns : Nothing + */ +void nr_php_packages_iterate(nr_php_packages_t* packages, + nr_php_packages_iter_t callback, + void* userdata); + /* * Purpose : Converts a package to a json * diff --git a/axiom/nr_txn.c b/axiom/nr_txn.c index c3667db81..774c44671 100644 --- a/axiom/nr_txn.c +++ b/axiom/nr_txn.c @@ -542,6 +542,7 @@ nrtxn_t* nr_txn_begin(nrapp_t* app, nt->custom_events = nr_analytics_events_create(app->limits.custom_events); nt->log_events = nr_log_events_create(app->limits.log_events); nt->php_packages = nr_php_packages_create(); + nt->php_package_major_version_metrics_suggestions = nr_php_packages_create(); /* * reset flag for creation of one-time logging metrics @@ -1246,6 +1247,7 @@ void nr_txn_destroy_fields(nrtxn_t* txn) { nr_segment_destroy_tree(txn->segment_root); nr_hashmap_destroy(&txn->parent_stacks); nr_php_packages_destroy(&txn->php_packages); + nr_php_packages_destroy(&txn->php_package_major_version_metrics_suggestions); nr_stack_destroy_fields(&txn->default_parent_stack); nr_slab_destroy(&txn->segment_slab); nr_minmax_heap_set_destructor(txn->segment_heap, NULL, NULL); @@ -3494,9 +3496,35 @@ void nr_txn_record_log_event(nrtxn_t* txn, nr_txn_add_logging_metrics(txn, log_level_name); } -void nr_txn_add_php_package(nrtxn_t* txn, - char* package_name, - char* package_version) { +nr_php_package_t* nr_txn_add_php_package_from_source( + nrtxn_t* txn, + char* package_name, + char* package_version, + const nr_php_package_source_priority_t source) { + nr_php_package_t* p = NULL; + + if (nrunlikely(NULL == txn)) { + return NULL; + } + + if (nr_strempty(package_name)) { + return NULL; + } + + p = nr_php_package_create_with_source(package_name, package_version, source); + return nr_php_packages_add_package(txn->php_packages, p); +} + +nr_php_package_t* nr_txn_add_php_package(nrtxn_t* txn, + char* package_name, + char* package_version) { + return nr_txn_add_php_package_from_source(txn, package_name, package_version, + NR_PHP_PACKAGE_SOURCE_LEGACY); +} + +void nr_txn_suggest_package_supportability_metric(nrtxn_t* txn, + const char* package_name, + const char* package_version) { nr_php_package_t* p = NULL; if (nrunlikely(NULL == txn)) { @@ -3507,6 +3535,11 @@ void nr_txn_add_php_package(nrtxn_t* txn, return; } - p = nr_php_package_create(package_name, package_version); - nr_php_packages_add_package(txn->php_packages, p); + nrl_verbosedebug(NRL_TXN, "Suggesting package %s %s", NRSAFESTR(package_name), + NRSAFESTR(package_version)); + + p = nr_php_package_create_with_source(package_name, package_version, + NR_PHP_PACKAGE_SOURCE_SUGGESTION); + nr_php_packages_add_package( + txn->php_package_major_version_metrics_suggestions, p); } diff --git a/axiom/nr_txn.h b/axiom/nr_txn.h index a6f942f66..8874260ec 100644 --- a/axiom/nr_txn.h +++ b/axiom/nr_txn.h @@ -203,6 +203,11 @@ typedef enum _nr_cpu_usage_t { NR_CPU_USAGE_COUNT = 2 } nr_cpu_usage_t; +typedef struct _nr_composer_info_t { + bool autoload_detected; + bool composer_detected; +} nr_composer_info_t; + /* * Possible transaction types, which go into the type bitfield in the nrtxn_t * struct. @@ -281,6 +286,9 @@ typedef struct _nrtxn_t { custom_events; /* Custom events created through the API. */ nr_log_events_t* log_events; /* Log events pool */ nr_php_packages_t* php_packages; /* Detected php packages */ + nr_php_packages_t* + php_package_major_version_metrics_suggestions; /* Suggested packages for + major metric creation */ nrtime_t user_cpu[NR_CPU_USAGE_COUNT]; /* User CPU usage */ nrtime_t sys_cpu[NR_CPU_USAGE_COUNT]; /* System CPU usage */ @@ -302,6 +310,7 @@ typedef struct _nrtxn_t { nr_distributed_trace_t* distributed_trace; /* distributed tracing metadata for the transaction */ nr_span_queue_t* span_queue; /* span queue when 8T is enabled */ + nr_composer_info_t composer_info; /* * flag to indicate if one time (per transaction) logging metrics @@ -1164,16 +1173,52 @@ static inline nr_segment_t* nr_txn_allocate_segment(nrtxn_t* txn) { } /* - * Purpose : Add php packages to transaction. This function should only be - * called when Vulnerability Management is enabled. + * Purpose : Add php package to transaction from desired source. This function + * should only be called when Vulnerability Management is enabled. + * + * Params : 1. The transaction + * 2. Package name + * 3. Package version + * 4. Source priority + * + * Returns : pointer to added package on success or NULL otherwise. + */ +nr_php_package_t* nr_txn_add_php_package_from_source( + nrtxn_t* txn, + char* package_name, + char* package_version, + const nr_php_package_source_priority_t source); + +/* + * Purpose : Add php package to transaction from legacy source. This function + * should only be called when Vulnerability Management is enabled. * * Params : 1. The transaction * 2. Package name * 3. Package version * + * Returns : pointer to added package on success or NULL otherwise. */ -void nr_txn_add_php_package(nrtxn_t* txn, - char* package_name, - char* package_version); +extern nr_php_package_t* nr_txn_add_php_package(nrtxn_t* txn, + char* package_name, + char* package_version); +/* + * Purpose : Add php package suggestion to transaction. This function + * can be used when Vulnerability Management is not enabled. It will + * add the package to the transaction's + * php_package_major_version_metrics_suggestions list. At the end of the + * transaction this list is traversed and any suggestions with a known version + * will have a package major version metric created. + * + * Params : 1. The transaction + * 2. Package name + * 3. Package version (can be NULL or PHP_PACKAGE_VERSION_UNKNOWN) + * + * Returns : Nothing. + */ +extern void nr_txn_suggest_package_supportability_metric( + nrtxn_t* txn, + const char* package_name, + const char* package_version); #endif /* NR_TXN_HDR */ diff --git a/axiom/tests/.gitignore b/axiom/tests/.gitignore index e2e2db564..22ee3b042 100644 --- a/axiom/tests/.gitignore +++ b/axiom/tests/.gitignore @@ -82,6 +82,7 @@ test_number_converter test_obfuscate test_object test_offsets +test_php_packages test_postgres test_quarantine test_random diff --git a/axiom/tests/test_php_packages.c b/axiom/tests/test_php_packages.c index 427ece058..bd2323b2f 100644 --- a/axiom/tests/test_php_packages.c +++ b/axiom/tests/test_php_packages.c @@ -192,6 +192,183 @@ static void test_php_package_without_version(void) { nr_php_packages_destroy(&hm); } +static void test_php_package_priority(void) { +#define PACKAGE_NAME "vendor/package" +#define NO_VERSION NULL +#define PACKAGE_VERSION "1.0.0" +#define COMPOSER_VERSION "1.0.1" +#define COMPOSER_VERSION_2 "2.0.1" + nr_php_package_t* legacy_package; + nr_php_package_t* composer_package; + nr_php_package_t* composer_package_2; + nr_php_package_t* p; + nr_php_packages_t* hm = NULL; + int count; + char* legacy_versions[] = {NO_VERSION, PACKAGE_VERSION}; + + // Package added with legacy priority first - version from composer should win + for (size_t i = 0; i < sizeof(legacy_versions) / sizeof(legacy_versions[0]); + i++) { + legacy_package = nr_php_package_create( + PACKAGE_NAME, legacy_versions[i]); // legacy priority + tlib_pass_if_int_equal("create package by uses legacy priority", + NR_PHP_PACKAGE_SOURCE_LEGACY, + legacy_package->source_priority); + composer_package = nr_php_package_create_with_source( + PACKAGE_NAME, COMPOSER_VERSION, + NR_PHP_PACKAGE_SOURCE_COMPOSER); // composer priority + tlib_pass_if_int_equal("create package by uses composer priority", + NR_PHP_PACKAGE_SOURCE_COMPOSER, + composer_package->source_priority); + + hm = nr_php_packages_create(); + // order of adding packages: legacy first, composer second + nr_php_packages_add_package(hm, legacy_package); + nr_php_packages_add_package(hm, composer_package); + + count = nr_php_packages_count(hm); + tlib_pass_if_int_equal("add same package", 1, count); + + p = nr_php_packages_get_package(hm, PACKAGE_NAME); + tlib_pass_if_not_null("package exists", p); + tlib_pass_if_str_equal("package version from composer wins", + COMPOSER_VERSION, p->package_version); + + nr_php_packages_destroy(&hm); + } + + // Package added with composer priority first - version from composer should + // win + for (size_t i = 0; i < sizeof(legacy_versions) / sizeof(legacy_versions[0]); + i++) { + legacy_package = nr_php_package_create( + PACKAGE_NAME, legacy_versions[i]); // legacy priority + tlib_pass_if_int_equal("create package by uses legacy priority", + NR_PHP_PACKAGE_SOURCE_LEGACY, + legacy_package->source_priority); + composer_package = nr_php_package_create_with_source( + PACKAGE_NAME, COMPOSER_VERSION, + NR_PHP_PACKAGE_SOURCE_COMPOSER); // composer priority + tlib_pass_if_int_equal("create package by uses composer priority", + NR_PHP_PACKAGE_SOURCE_COMPOSER, + composer_package->source_priority); + + hm = nr_php_packages_create(); + // order of adding packages: legacy first, composer second + nr_php_packages_add_package(hm, composer_package); + nr_php_packages_add_package(hm, legacy_package); + + count = nr_php_packages_count(hm); + tlib_pass_if_int_equal("add same package", 1, count); + + p = nr_php_packages_get_package(hm, PACKAGE_NAME); + tlib_pass_if_not_null("package exists", p); + tlib_pass_if_str_equal("package version from composer wins", + COMPOSER_VERSION, p->package_version); + + nr_php_packages_destroy(&hm); + } + + // Package added with composer priority only - last version from composer + // should win + composer_package = nr_php_package_create_with_source( + PACKAGE_NAME, COMPOSER_VERSION, + NR_PHP_PACKAGE_SOURCE_COMPOSER); // composer priority + tlib_pass_if_int_equal("create package by uses composer priority", + NR_PHP_PACKAGE_SOURCE_COMPOSER, + composer_package->source_priority); + + composer_package_2 = nr_php_package_create_with_source( + PACKAGE_NAME, COMPOSER_VERSION_2, + NR_PHP_PACKAGE_SOURCE_COMPOSER); // composer priority + tlib_pass_if_int_equal("create package by uses composer priority", + NR_PHP_PACKAGE_SOURCE_COMPOSER, + composer_package_2->source_priority); + + hm = nr_php_packages_create(); + // order of adding packages: composer first, composer second + nr_php_packages_add_package(hm, composer_package); + nr_php_packages_add_package(hm, composer_package_2); + + count = nr_php_packages_count(hm); + tlib_pass_if_int_equal("add same package", 1, count); + + p = nr_php_packages_get_package(hm, PACKAGE_NAME); + tlib_pass_if_not_null("package exists", p); + tlib_pass_if_str_equal("package version from last composer wins", + COMPOSER_VERSION_2, p->package_version); + + nr_php_packages_destroy(&hm); +} + +static void nr_php_packages_itereate_callback(void* value, + const char* key, + size_t key_len, + void* user_data) { + nr_php_package_t* package = value; + const char* name = key; + nrbuf_t* buf = (nrbuf_t*)user_data; + + if (NULL == buf) { + return; + } + + /* append name, len, version to string */ + nr_buffer_add(buf, name, key_len); + nr_buffer_add(buf, NR_PSTR(",")); + nr_buffer_add(buf, package->package_version, + nr_strlen(package->package_version)); + nr_buffer_add(buf, NR_PSTR("\n")); +} + +static void test_php_package_iterate(void) { + nr_php_package_t* package1; + nr_php_package_t* package2; + nr_php_package_t* package3; + nr_php_packages_t* hm = nr_php_packages_create(); + nrbuf_t* buf; + int count; + + // Test: create multiple new packages and add to hashmap + package1 = nr_php_package_create("name1", "name1_version"); + package2 = nr_php_package_create("name2", "name2_version"); + package3 = nr_php_package_create("name3", "name3_version"); + + nr_php_packages_add_package(hm, package1); + nr_php_packages_add_package(hm, package2); + nr_php_packages_add_package(hm, package3); + + count = nr_php_packages_count(hm); + + tlib_pass_if_int_equal("package count", 3, count); + + /* tests with invalid values + * NOTE: nr_buffer_cptr(buf) will return NULL if no data is in the buffer + */ + buf = nr_buffer_create(0, 0); + nr_php_packages_iterate(NULL, nr_php_packages_itereate_callback, (void*)buf); + tlib_pass_if_null("iterate with NULL hashmap", nr_buffer_cptr(buf)); + nr_php_packages_iterate(hm, nr_php_packages_itereate_callback, NULL); + tlib_pass_if_null("iterate with NULL userdata", nr_buffer_cptr(buf)); + nr_php_packages_iterate(hm, NULL, (void*)buf); + tlib_pass_if_null("iterate with NULL callback", nr_buffer_cptr(buf)); + nr_php_packages_iterate(NULL, NULL, NULL); + tlib_pass_if_null("iterate with all NULL", nr_buffer_cptr(buf)); + nr_buffer_destroy(&buf); + + /* test with valid values */ + buf = nr_buffer_create(0, 0); + nr_php_packages_iterate(hm, nr_php_packages_itereate_callback, (void*)buf); + nr_buffer_add(buf, NR_PSTR("\0")); + tlib_pass_if_str_equal("iterate created proper string", + "name1,name1_version\nname2,name2_version\nname3,name3_version\n", nr_buffer_cptr(buf)); + nr_buffer_destroy(&buf); + + nr_php_packages_destroy(&hm); +} + + + tlib_parallel_info_t parallel_info = {.suggested_nthreads = -1, .state_size = 0}; @@ -203,4 +380,6 @@ void test_main(void* p NRUNUSED) { test_php_packages_to_json(); test_php_package_exists_in_hashmap(); test_php_package_without_version(); -} \ No newline at end of file + test_php_package_priority(); + test_php_package_iterate(); +} diff --git a/axiom/tests/test_txn.c b/axiom/tests/test_txn.c index 59b19f9b0..9230a416a 100644 --- a/axiom/tests/test_txn.c +++ b/axiom/tests/test_txn.c @@ -8597,6 +8597,8 @@ static void test_nr_txn_add_php_package(void) { char* package_name4 = "Wordpress"; char* package_version4 = PHP_PACKAGE_VERSION_UNKNOWN; nrtxn_t* txn = new_txn(0); + nr_php_package_t* p1 = NULL; + nr_php_package_t* p2 = NULL; /* * NULL parameters: ensure it does not crash @@ -8621,6 +8623,130 @@ static void test_nr_txn_add_php_package(void) { nr_free(json); nr_txn_destroy(&txn); + + txn = new_txn(0); + p1 = nr_txn_add_php_package(txn, package_name1, package_version1); + p2 = nr_txn_add_php_package(txn, package_name1, package_version2); + tlib_pass_if_ptr_equal( + "same package name, different version, add returns same pointer", p1, p2); + nr_txn_destroy(&txn); +} + +static void test_nr_txn_add_php_package_from_source(void) { + char* json; + char* package_name1 = "Laravel"; + char* package_version1 = "8.83.27"; + char* package_name2 = "Slim"; + char* package_version2 = "4.12.0"; + char* package_name3 = "Drupal"; + char* package_version3 = NULL; + char* package_name4 = "Wordpress"; + char* package_version4 = PHP_PACKAGE_VERSION_UNKNOWN; + nrtxn_t* txn = new_txn(0); + nr_php_package_t* p1 = NULL; + nr_php_package_t* p2 = NULL; + + /* + * NULL parameters: ensure it does not crash + */ + nr_txn_add_php_package_from_source(NULL, NULL, NULL, 0); + nr_txn_add_php_package_from_source(NULL, package_name1, package_version1, 0); + nr_txn_add_php_package_from_source(txn, NULL, package_version1, 0); + nr_txn_add_php_package_from_source(txn, package_name1, NULL, 0); + + // Test: add php packages to transaction + nr_txn_add_php_package_from_source(txn, package_name1, package_version1, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + nr_txn_add_php_package_from_source(txn, package_name2, package_version2, + NR_PHP_PACKAGE_SOURCE_LEGACY); + nr_txn_add_php_package_from_source(txn, package_name3, package_version3, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + nr_txn_add_php_package_from_source(txn, package_name4, package_version4, + NR_PHP_PACKAGE_SOURCE_LEGACY); + json = nr_php_packages_to_json(txn->php_packages); + + tlib_pass_if_str_equal("correct json", + "[[\"Laravel\",\"8.83.27\",{}]," + "[\"Drupal\",\" \",{}],[\"Wordpress\",\" \",{}]," + "[\"Slim\",\"4.12.0\",{}]]", + json); + + nr_free(json); + nr_txn_destroy(&txn); + + txn = new_txn(0); + p1 = nr_txn_add_php_package_from_source(txn, package_name1, package_version1, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + p2 = nr_txn_add_php_package_from_source(txn, package_name1, package_version2, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + tlib_pass_if_ptr_equal( + "same package name, different version, add returns same pointer", p1, p2); + nr_txn_destroy(&txn); + + txn = new_txn(0); + p1 = nr_txn_add_php_package_from_source(txn, package_name1, package_version1, + NR_PHP_PACKAGE_SOURCE_LEGACY); + p2 = nr_txn_add_php_package_from_source(txn, package_name1, package_version2, + NR_PHP_PACKAGE_SOURCE_COMPOSER); + tlib_pass_if_ptr_equal( + "same package name, different version, add returns different pointer", p1, + p2); + tlib_pass_if_str_equal("composer version used", package_version2, + p2->package_version); + + nr_txn_destroy(&txn); +} + +static void test_nr_txn_suggest_package_supportability_metric(void) { + char* json; + char* package_name1 = "Laravel"; + char* package_version1 = "8.83.27"; + char* package_name2 = "Slim"; + char* package_version2 = "4.12.0"; + char* package_name3 = "Drupal"; + char* package_version3 = NULL; + char* package_name4 = "Wordpress"; + char* package_version4 = PHP_PACKAGE_VERSION_UNKNOWN; + nrtxn_t* txn = new_txn(0); + nr_php_package_t* p1 = NULL; + nr_php_package_t* p2 = NULL; + + /* + * NULL parameters: ensure it does not crash + */ + nr_txn_suggest_package_supportability_metric(NULL, NULL, NULL); + nr_txn_suggest_package_supportability_metric(NULL, package_name1, + package_version1); + nr_txn_suggest_package_supportability_metric(txn, NULL, package_version1); + nr_txn_suggest_package_supportability_metric(txn, package_name1, NULL); + + // Test: add php packages to transaction + nr_txn_suggest_package_supportability_metric(txn, package_name1, + package_version1); + nr_txn_suggest_package_supportability_metric(txn, package_name2, + package_version2); + nr_txn_suggest_package_supportability_metric(txn, package_name3, + package_version3); + nr_txn_suggest_package_supportability_metric(txn, package_name4, + package_version4); + json = nr_php_packages_to_json( + txn->php_package_major_version_metrics_suggestions); + + tlib_pass_if_str_equal("correct json", + "[[\"Laravel\",\"8.83.27\",{}]," + "[\"Drupal\",\" \",{}],[\"Wordpress\",\" \",{}]," + "[\"Slim\",\"4.12.0\",{}]]", + json); + + nr_free(json); + nr_txn_destroy(&txn); + + txn = new_txn(0); + p1 = nr_txn_add_php_package(txn, package_name1, package_version1); + p2 = nr_txn_add_php_package(txn, package_name1, package_version2); + tlib_pass_if_ptr_equal( + "same package name, different version, add returns same pointer", p1, p2); + nr_txn_destroy(&txn); } tlib_parallel_info_t parallel_info @@ -8725,4 +8851,6 @@ void test_main(void* p NRUNUSED) { test_record_log_event(); test_txn_log_configuration(); test_nr_txn_add_php_package(); + test_nr_txn_add_php_package_from_source(); + test_nr_txn_suggest_package_supportability_metric(); } diff --git a/daemon/internal/newrelic/integration/php_packages.go b/daemon/internal/newrelic/integration/php_packages.go index 375954b0d..fc9a10a59 100644 --- a/daemon/internal/newrelic/integration/php_packages.go +++ b/daemon/internal/newrelic/integration/php_packages.go @@ -31,12 +31,13 @@ type PhpPackagesCollection struct { // PHP packages config describes how to collect the JSON for the packages installed // for the current test case type PhpPackagesConfiguration struct { - path string - command string - supportedListFile string - overrideVersionsFile string - expectedPackages []string - packageNameOnly []string + path string // + command string // command to run to detect packages + supportedListFile string // JSON file containing list of packages we expect agent to detect + overrideVersionsFile string // JSON file containing overrides for expected package versions + expectedPackages []string // manual override of packages we expect to detect + packageNameOnly []string // list of packages which only have a name because agent cannot determine the version + expectAllDetected bool // flag to indicate we expect all packages detected by the command "command" } // composer package JSON @@ -159,16 +160,22 @@ func NewPhpPackagesCollection(path string, config []byte) (*PhpPackagesCollectio } } - if supportedOK && expectedOK { - return nil, fmt.Errorf("Improper EXPECT_PHP_PACKAGES config - cannot specify 'supported_packages' and 'expected packages' - got %+v", params) + // or "expect_all" which means we expect the agent to detect all the packages that the "command" option would detect + _, expectAllOK := params["expect_all"] + + if (supportedOK && expectedOK) || (supportedOK && expectAllOK) || (expectedOK && expectAllOK) { + return nil, fmt.Errorf("Improper EXPECT_PHP_PACKAGES config - must specify one of 'supported_packages', "+ + "'expected packages' or 'expect_all' - got %+v", params) } - if !supportedOK && !expectedOK { - return nil, fmt.Errorf("Improper EXPECT_PHP_PACKAGES config - must specify 'supported_packages' or 'expected packages' - got %+v", params) + if !supportedOK && !expectedOK && !expectAllOK { + return nil, fmt.Errorf("Improper EXPECT_PHP_PACKAGES config - must specify 'supported_packages' or 'expected packages' "+ + "or 'expect_all' - got %+v", params) } - if supportedOK && !commandOK { - return nil, fmt.Errorf("Improper EXPECT_PHP_PACKAGES config - must specify 'command' option with `supported_packages` - got %+v", params) + if (supportedOK || expectAllOK) && !commandOK { + return nil, fmt.Errorf("Improper EXPECT_PHP_PACKAGES config - must specify 'command' option with `supported_packages` / "+ + "'expect_all' - got %+v", params) } // optional option to specify which packages will only have a name because agent cannot determine the version @@ -209,7 +216,8 @@ func NewPhpPackagesCollection(path string, config []byte) (*PhpPackagesCollectio supportedListFile: supportedListFile, overrideVersionsFile: overrideVersionsFile, expectedPackages: expectedPackagesArr, - packageNameOnly: packageNameOnlyArr}, + packageNameOnly: packageNameOnlyArr, + expectAllDetected: expectAllOK}, } return p, nil @@ -296,18 +304,27 @@ func (pkgs *PhpPackagesCollection) GatherInstalledPackages() ([]PhpPackage, erro var supported []string // get list of packages we expected the agent to detect - // this can be one of 2 scenarios: + // this can be one of 3 scenarios: // 1) test case used the "supported_packages" option which gives a JSON file which // lists all the packages the agent can detect // 2) test case used the "expected_packages" options which provides a comma separated // list of packages we expect the agent to detect + // 3) test case used the "expect_all" option which means we expect the agent to + // detect all the packages that the "command" option would detect + // + // Options #1 and #2 are mutually exclusive, and are intended for testing the legacy VM detection + // mechanism where the agent looks for "magic" files of a package and examinew internals of the + // package to determine its version. // - // Option #1 is preferable as it provides the most comprehensive view of what the agent can do. + // Option #1 is preferable when it available as it provides the most comprehensive view of what the agent can do. // // Option #2 is needed because some test cases do not exercise all the packages which are // installed and so the agent will not detect everything for that test case run which it could // theorectically detect if the test case used all the available packages installed. // + // Option #3 is used when testing the agent's ability to detect packages using the Composer API. In + // this case we expect the agent to detect the exact same packages as composer would detect. + // // Once the list of packages the agent is expected to detect is created it is used to filter // down the package list returned by running the "command" (usually composer) option for the // test case provided. @@ -318,8 +335,9 @@ func (pkgs *PhpPackagesCollection) GatherInstalledPackages() ([]PhpPackage, erro } } else if 0 < len(pkgs.config.expectedPackages) { supported = pkgs.config.expectedPackages - } else { - return nil, fmt.Errorf("Error determining expected packages - supported_packages and expected_packages are both empty") + } else if !pkgs.config.expectAllDetected { + return nil, fmt.Errorf("Error determining expected packages - supported_packages and expected_packages are both empty " + + "and expect_all is false") } splitCmd := strings.Split(pkgs.config.command, " ") @@ -339,7 +357,7 @@ func (pkgs *PhpPackagesCollection) GatherInstalledPackages() ([]PhpPackage, erro json.Unmarshal([]byte(out), &detected) for _, v := range detected.Installed { //fmt.Printf("composer detected %s %s\n", v.Name, v.Version) - if StringSliceContains(supported, v.Name) { + if pkgs.config.expectAllDetected || StringSliceContains(supported, v.Name) { var version string // remove any 'v' from front of version string @@ -371,6 +389,18 @@ func (pkgs *PhpPackagesCollection) GatherInstalledPackages() ([]PhpPackage, erro if 0 < len(version) { pkgs.packages = append(pkgs.packages, PhpPackage{"wordpress", version}) } + } else if 1 < len(splitCmd) && "composer-show.php" == splitCmd[1] { + lines := strings.Split(string(out), "\n") + version := "" + for _, line := range lines { + //fmt.Printf("line is |%s|\n", line) + splitLine := strings.Split(line, "=>") + if 2 == len(splitLine) { + name := strings.TrimSpace(splitLine[0]) + version = strings.TrimSpace(splitLine[1]) + pkgs.packages = append(pkgs.packages, PhpPackage{name, version}) + } + } } else { return nil, fmt.Errorf("ERROR - unknown method '%s'\n", splitCmd[0]) } diff --git a/daemon/internal/newrelic/integration/test.go b/daemon/internal/newrelic/integration/test.go index 631be4615..3e70e769a 100644 --- a/daemon/internal/newrelic/integration/test.go +++ b/daemon/internal/newrelic/integration/test.go @@ -637,6 +637,7 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { var expectedPkgsCollection *PhpPackagesCollection var expectNullPkgs bool var version_overrides map[string]interface{} + var subsetMatch bool = false if nil != t.phpPackagesConfig { var err error @@ -656,6 +657,19 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { t.Fatal(err) return } + + // Determine if we expect an exact match between expected and actual packages + // when using the composer API in the agent to detect packages it is possible + // it will return packages which the "composer show" command does not. These + // are usually virtual or other types of packages which "composer show" + // decides to not show. + // + // Currently the test handles this by listing all the packages that the agent + // detected but "composer show" did not as "Notes" on the test results. + // + // Tests for the legacy package detection mechanism still expect an exact match. + // + subsetMatch = expectedPkgsCollection.config.expectAllDetected } } else { // no configuration given for package (no EXPECT_PHP_PACKAGES in test case) so don't run test @@ -690,22 +704,44 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { if nil == expectedPackages { t.Fail(fmt.Errorf("No expected PHP packages, harvest contains %+v\n", actualPackages)) } - // compare expected and actual lists of packages + // Compare expected and actual lists of packages // since package names should be identical, iterate over // expected list and compare element by element with same // position in actual list. Name and version should match. // this works because the functions which generate these // lists sort them by package name for us - if len(expectedPackages) != len(actualPackages) { + // + // As explained above - if testing results from the Composer API + // agent detection mechanism, we may not get an exact match so + // we relax the test that the lengths of the two lists are the same + if !subsetMatch && (len(expectedPackages) != len(actualPackages)) { t.Fail(fmt.Errorf("Expected and actual php packages differ in length %d vs %d: expected %+v actual %+v", len(expectedPackages), len(actualPackages), expectedPackages, actualPackages)) return } for i, _ := range expectedPackages { - if expectedPackages[i].Name == actualPackages[i].Name { + var matchingIdx int = -1 + for j, pkg := range actualPackages { + //fmt.Printf("Comparing %s to %s\n", pkg.Name, expectedPackages[i].Name) + if pkg.Name == expectedPackages[i].Name { + //fmt.Printf("Match - index = %d\n", j) + matchingIdx = j + break + } + } + + //fmt.Printf("MatchingIdx: %d\n", matchingIdx) + //fmt.Printf("expectedPatckages[%d]: %+v\n", i, expectedPackages[i]) + // if -1 != matchingIdx { + // fmt.Printf("actualPackages[%d]: %+v\n", matchingIdx, actualPackages[matchingIdx]) + // } else { + // fmt.Printf("no match in actualPackages!\n") + // } + + if -1 != matchingIdx { testPackageNameOnly := false if nil != expectedPkgsCollection.config.packageNameOnly { - testPackageNameOnly = StringSliceContains(expectedPkgsCollection.config.packageNameOnly, actualPackages[i].Name) + testPackageNameOnly = StringSliceContains(expectedPkgsCollection.config.packageNameOnly, actualPackages[matchingIdx].Name) if testPackageNameOnly { t.AddNote(fmt.Sprintf("Tested package name only for packages: %+v", expectedPkgsCollection.config.packageNameOnly)) } @@ -720,23 +756,41 @@ func (t *Test) comparePhpPackages(harvest *newrelic.Harvest) { } if testPackageNameOnly { - if " " != actualPackages[i].Version { + if " " != actualPackages[matchingIdx].Version { t.Fail(fmt.Errorf("Expected no package version and a package version was detected - expected \" \" actual %+v. ", - actualPackages[i].Version)) + actualPackages[matchingIdx].Version)) return } else { continue } } - if expected_version == actualPackages[i].Version { + if expected_version == actualPackages[matchingIdx].Version { continue + } else { + t.Fail(fmt.Errorf("Expected version %s does not match actual version %s for package %s", + expected_version, actualPackages[matchingIdx].Version, expectedPackages[i].Name)) + return } } - t.Fail(fmt.Errorf("Expected and actual Php packages do not match: expected %+v actual %+v. Complete expected %v actual %v.", - expectedPackages[i], actualPackages[i], expectedPackages, actualPackages)) + t.Fail(fmt.Errorf("Expected Php packages do not match any actual packages: expected %+v\nComplete:\nexpected %v\nactual %v.\n", + expectedPackages[i], expectedPackages, actualPackages)) return } + + // create notes for all packages in the actual list not in the expected list + for ii, _ := range actualPackages { + var found bool = false + for _, pkg := range expectedPackages { + if pkg.Name == actualPackages[ii].Name { + found = true + break + } + } + if !found { + t.AddNote(fmt.Sprintf("Detected package not in expected: %+v", actualPackages[ii])) + } + } } else { if nil != expectedPackages { t.Fail(fmt.Errorf("Expected PHP packages %+v, harvest contains none\n", expectedPackages)) diff --git a/tests/integration/autoloader/autoload-with-broken-composer-00/vendor/autoload.php b/tests/integration/autoloader/autoload-with-broken-composer-00/vendor/autoload.php new file mode 100644 index 000000000..01d206c0f --- /dev/null +++ b/tests/integration/autoloader/autoload-with-broken-composer-00/vendor/autoload.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/autoload-with-broken-composer-00/vendor/composer/autoload_real.php b/tests/integration/autoloader/autoload-with-broken-composer-00/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/autoload-with-broken-composer-00/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ) + ) + ); diff --git a/tests/integration/autoloader/autoload-with-broken-composer-01/vendor/autoload.php b/tests/integration/autoloader/autoload-with-broken-composer-01/vendor/autoload.php new file mode 100644 index 000000000..01d206c0f --- /dev/null +++ b/tests/integration/autoloader/autoload-with-broken-composer-01/vendor/autoload.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/autoload-with-broken-composer-01/vendor/composer/autoload_real.php b/tests/integration/autoloader/autoload-with-broken-composer-01/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/autoload-with-broken-composer-01/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ) + ) + ); diff --git a/tests/integration/autoloader/autoload-with-broken-composer-02/vendor/autoload.php b/tests/integration/autoloader/autoload-with-broken-composer-02/vendor/autoload.php new file mode 100644 index 000000000..01d206c0f --- /dev/null +++ b/tests/integration/autoloader/autoload-with-broken-composer-02/vendor/autoload.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/autoload-with-broken-composer-02/vendor/composer/autoload_real.php b/tests/integration/autoloader/autoload-with-broken-composer-02/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/autoload-with-broken-composer-02/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/composer/autoload_real.php b/tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/autoload-with-composer-throwing-error/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ) + ) + ); diff --git a/tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/autoload.php b/tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/autoload.php new file mode 100644 index 000000000..01d206c0f --- /dev/null +++ b/tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/autoload.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/composer/autoload_real.php b/tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/autoload-with-composer-throwing-exception/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ) + ) + ); diff --git a/tests/integration/autoloader/autoload-with-composer/vendor/autoload.php b/tests/integration/autoloader/autoload-with-composer/vendor/autoload.php new file mode 100644 index 000000000..01d206c0f --- /dev/null +++ b/tests/integration/autoloader/autoload-with-composer/vendor/autoload.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/autoload-with-composer/vendor/composer/autoload_real.php b/tests/integration/autoloader/autoload-with-composer/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/autoload-with-composer/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ) + ) + ); diff --git a/tests/integration/autoloader/autoload-without-composer/vendor/autoload.php b/tests/integration/autoloader/autoload-without-composer/vendor/autoload.php new file mode 100644 index 000000000..0a6947fef --- /dev/null +++ b/tests/integration/autoloader/autoload-without-composer/vendor/autoload.php @@ -0,0 +1,12 @@ + 1) { + $installedVersions = $argv[1]; +} + +include $installedVersions; +if ($argc > 2) { + $installed = Composer\InstalledVersions::getAllRawData(); + $package = $argv[2]; + $version = ltrim($installed[0]['versions'][$package]['pretty_version'], 'v'); + echo "$package => $version\n"; +} else { + Composer\InstalledVersions::show(); +} diff --git a/tests/integration/autoloader/packages-with-broken-composer-00/vendor/autoload.php b/tests/integration/autoloader/packages-with-broken-composer-00/vendor/autoload.php new file mode 100644 index 000000000..01d206c0f --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-00/vendor/autoload.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/packages-with-broken-composer-00/vendor/composer/autoload_real.php b/tests/integration/autoloader/packages-with-broken-composer-00/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-00/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ), + 'symfony/http-kernel' => array( + 'pretty_version' => '5.4.5', + 'version' => '5.4.5.0', + 'type' => 'library' + ), + ) + ); diff --git a/tests/integration/autoloader/packages-with-broken-composer-00/vendor/symfony/http-kernel/HttpKernel.php b/tests/integration/autoloader/packages-with-broken-composer-00/vendor/symfony/http-kernel/HttpKernel.php new file mode 100644 index 000000000..2cceb6ac7 --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-00/vendor/symfony/http-kernel/HttpKernel.php @@ -0,0 +1,12 @@ + $info) { + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/packages-with-broken-composer-01/vendor/composer/autoload_real.php b/tests/integration/autoloader/packages-with-broken-composer-01/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-01/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked data: installed packages and their versions + 'versions' => array( + 'vendor1/package1' => array( + 'pretty_version' => 'v1.1.3', + 'version' => '1.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'pretty_version' => '2.1.5', + 'version' => '2.1.5.0', + 'type' => 'library' + ), + 'laravel/framework' => array( + 'pretty_version' => '11.4.5', + 'version' => '11.4.5', + 'type' => 'library' + ), + ) + ); diff --git a/tests/integration/autoloader/packages-with-broken-composer-01/vendor/laravel/framework/src/Illuminate/Foundation/Application.php b/tests/integration/autoloader/packages-with-broken-composer-01/vendor/laravel/framework/src/Illuminate/Foundation/Application.php new file mode 100644 index 000000000..3c6718e89 --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-01/vendor/laravel/framework/src/Illuminate/Foundation/Application.php @@ -0,0 +1,25 @@ + $info) { + if (!is_string($package)) { + continue; + } + if (!is_array($info)) { + continue; + } + if (!array_key_exists('pretty_version', $info)) { + continue; + } + if (!is_string($info['pretty_version'])) { + continue; + } + $version = ltrim($info['pretty_version'], 'v'); + echo "$package => $version\n"; + } + } +} diff --git a/tests/integration/autoloader/packages-with-broken-composer-02/vendor/composer/autoload_real.php b/tests/integration/autoloader/packages-with-broken-composer-02/vendor/composer/autoload_real.php new file mode 100644 index 000000000..014c86e9a --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-02/vendor/composer/autoload_real.php @@ -0,0 +1,9 @@ + array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'type' => 'project' + ), + // Mocked invalid package data: + // - package without name and version + // - package without name but with version + // - package with name but without version + // Mocked valid package data: + // - package with name and version + 'versions' => array( + array( + 'version' => '1.1.3.0', + 'type' => 'library' + ), + array( + 'pretty_version' => 'v2.1.3', + 'version' => '2.1.3.0', + 'type' => 'library' + ), + 'vendor2/package2' => array( + 'version' => '3.1.5.0', + 'type' => 'library' + ), + 'laravel/framework' => array( + 'pretty_version' => '11.4.5', + 'version' => '11.4.5', + 'type' => 'library' + ), + ) + ); diff --git a/tests/integration/autoloader/packages-with-broken-composer-02/vendor/laravel/framework/src/Illuminate/Foundation/Application.php b/tests/integration/autoloader/packages-with-broken-composer-02/vendor/laravel/framework/src/Illuminate/Foundation/Application.php new file mode 100644 index 000000000..3c6718e89 --- /dev/null +++ b/tests/integration/autoloader/packages-with-broken-composer-02/vendor/laravel/framework/src/Illuminate/Foundation/Application.php @@ -0,0 +1,25 @@ +emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_cat.php b/tests/integration/logging/monolog2/test_monolog_cat.php index d96e38aec..b192b9ce9 100644 --- a/tests/integration/logging/monolog2/test_monolog_cat.php +++ b/tests/integration/logging/monolog2/test_monolog_cat.php @@ -56,7 +56,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -183,4 +183,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_context_simple.php b/tests/integration/logging/monolog2/test_monolog_context_simple.php index 769694845..a0f0b7260 100644 --- a/tests/integration/logging/monolog2/test_monolog_context_simple.php +++ b/tests/integration/logging/monolog2/test_monolog_context_simple.php @@ -59,7 +59,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], diff --git a/tests/integration/logging/monolog2/test_monolog_decoration_and_forwarding.php b/tests/integration/logging/monolog2/test_monolog_decoration_and_forwarding.php index 1737a919c..82ad4be61 100644 --- a/tests/integration/logging/monolog2/test_monolog_decoration_and_forwarding.php +++ b/tests/integration/logging/monolog2/test_monolog_decoration_and_forwarding.php @@ -113,7 +113,7 @@ [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/api/get_linking_metadata"}, [16, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -257,4 +257,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_disable_metrics.php b/tests/integration/logging/monolog2/test_monolog_disable_metrics.php index 95b84d636..eaed5d5d4 100644 --- a/tests/integration/logging/monolog2/test_monolog_disable_metrics.php +++ b/tests/integration/logging/monolog2/test_monolog_disable_metrics.php @@ -51,7 +51,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -153,4 +153,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_drop_empty.php b/tests/integration/logging/monolog2/test_monolog_drop_empty.php index 8139e3606..5d48030ca 100644 --- a/tests/integration/logging/monolog2/test_monolog_drop_empty.php +++ b/tests/integration/logging/monolog2/test_monolog_drop_empty.php @@ -57,7 +57,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -171,4 +171,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_large_message_limit.php b/tests/integration/logging/monolog2/test_monolog_large_message_limit.php index d7c9b677a..7a0e1eacd 100644 --- a/tests/integration/logging/monolog2/test_monolog_large_message_limit.php +++ b/tests/integration/logging/monolog2/test_monolog_large_message_limit.php @@ -40,7 +40,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -78,4 +78,4 @@ function test_logging() { } } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_large_message_limit_drops.php b/tests/integration/logging/monolog2/test_monolog_large_message_limit_drops.php index 0dfe1dc2d..313e73edd 100644 --- a/tests/integration/logging/monolog2/test_monolog_large_message_limit_drops.php +++ b/tests/integration/logging/monolog2/test_monolog_large_message_limit_drops.php @@ -40,7 +40,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1666, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -78,4 +78,4 @@ function test_logging() { } } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_limit_log_events.php b/tests/integration/logging/monolog2/test_monolog_limit_log_events.php index c9106b2ea..ccc75de41 100644 --- a/tests/integration/logging/monolog2/test_monolog_limit_log_events.php +++ b/tests/integration/logging/monolog2/test_monolog_limit_log_events.php @@ -58,7 +58,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -161,4 +161,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_limit_zero_events.php b/tests/integration/logging/monolog2/test_monolog_limit_zero_events.php index 6ff0fa7d1..573850d3a 100644 --- a/tests/integration/logging/monolog2/test_monolog_limit_zero_events.php +++ b/tests/integration/logging/monolog2/test_monolog_limit_zero_events.php @@ -58,7 +58,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -101,4 +101,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid1.php b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid1.php index f760b19ac..c346aa55e 100644 --- a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid1.php +++ b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid1.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid2.php b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid2.php index ada730ed7..ab55e0359 100644 --- a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid2.php +++ b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid2.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid3.php b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid3.php index cdd99bc5f..616eb81f8 100644 --- a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid3.php +++ b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid3.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid4.php b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid4.php index 354108a09..0f13144eb 100644 --- a/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid4.php +++ b/tests/integration/logging/monolog2/test_monolog_log_events_max_samples_stored_invalid4.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_log_level_filter.php b/tests/integration/logging/monolog2/test_monolog_log_level_filter.php index 939dd9cf5..fa7902395 100644 --- a/tests/integration/logging/monolog2/test_monolog_log_level_filter.php +++ b/tests/integration/logging/monolog2/test_monolog_log_level_filter.php @@ -60,7 +60,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -171,4 +171,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog2/test_monolog_log_level_filter_invalid.php b/tests/integration/logging/monolog2/test_monolog_log_level_filter_invalid.php index d2eac9410..22107fd98 100644 --- a/tests/integration/logging/monolog2/test_monolog_log_level_filter_invalid.php +++ b/tests/integration/logging/monolog2/test_monolog_log_level_filter_invalid.php @@ -61,7 +61,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/2/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -172,4 +172,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_basic.php b/tests/integration/logging/monolog3/test_monolog_basic.php index 5cbc3a1da..0e494b078 100644 --- a/tests/integration/logging/monolog3/test_monolog_basic.php +++ b/tests/integration/logging/monolog3/test_monolog_basic.php @@ -56,7 +56,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -200,4 +200,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_cat.php b/tests/integration/logging/monolog3/test_monolog_cat.php index dcf557213..12b0c76ae 100644 --- a/tests/integration/logging/monolog3/test_monolog_cat.php +++ b/tests/integration/logging/monolog3/test_monolog_cat.php @@ -56,7 +56,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -184,4 +184,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_context_simple.php b/tests/integration/logging/monolog3/test_monolog_context_simple.php index 1e77e6d25..ddcfd65f9 100644 --- a/tests/integration/logging/monolog3/test_monolog_context_simple.php +++ b/tests/integration/logging/monolog3/test_monolog_context_simple.php @@ -59,7 +59,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], diff --git a/tests/integration/logging/monolog3/test_monolog_decoration_and_forwarding.php b/tests/integration/logging/monolog3/test_monolog_decoration_and_forwarding.php index fa0bbb6cb..3d8edcc7c 100644 --- a/tests/integration/logging/monolog3/test_monolog_decoration_and_forwarding.php +++ b/tests/integration/logging/monolog3/test_monolog_decoration_and_forwarding.php @@ -113,7 +113,7 @@ [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/api/get_linking_metadata"}, [16, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -257,4 +257,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_disable_metrics.php b/tests/integration/logging/monolog3/test_monolog_disable_metrics.php index cb5beb8e1..11bad2177 100644 --- a/tests/integration/logging/monolog3/test_monolog_disable_metrics.php +++ b/tests/integration/logging/monolog3/test_monolog_disable_metrics.php @@ -51,7 +51,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -153,4 +153,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_drop_empty.php b/tests/integration/logging/monolog3/test_monolog_drop_empty.php index 61937fb9f..6a470653b 100644 --- a/tests/integration/logging/monolog3/test_monolog_drop_empty.php +++ b/tests/integration/logging/monolog3/test_monolog_drop_empty.php @@ -57,7 +57,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -171,4 +171,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_large_message_limit.php b/tests/integration/logging/monolog3/test_monolog_large_message_limit.php index 191800f49..50b2a26a5 100644 --- a/tests/integration/logging/monolog3/test_monolog_large_message_limit.php +++ b/tests/integration/logging/monolog3/test_monolog_large_message_limit.php @@ -40,7 +40,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -78,4 +78,4 @@ function test_logging() { } } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_large_message_limit_drops.php b/tests/integration/logging/monolog3/test_monolog_large_message_limit_drops.php index eed9a410a..c2913419d 100644 --- a/tests/integration/logging/monolog3/test_monolog_large_message_limit_drops.php +++ b/tests/integration/logging/monolog3/test_monolog_large_message_limit_drops.php @@ -40,7 +40,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1666, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -78,4 +78,4 @@ function test_logging() { } } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_limit_log_events.php b/tests/integration/logging/monolog3/test_monolog_limit_log_events.php index b1f72e6b6..b5ffaf258 100644 --- a/tests/integration/logging/monolog3/test_monolog_limit_log_events.php +++ b/tests/integration/logging/monolog3/test_monolog_limit_log_events.php @@ -58,7 +58,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -161,4 +161,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_limit_zero_events.php b/tests/integration/logging/monolog3/test_monolog_limit_zero_events.php index 38abfe890..4b65d64f3 100644 --- a/tests/integration/logging/monolog3/test_monolog_limit_zero_events.php +++ b/tests/integration/logging/monolog3/test_monolog_limit_zero_events.php @@ -58,7 +58,7 @@ [{"name": "OtherTransactionTotalTime"}, [1, "??", "??", "??", "??", "??"]], [{"name": "OtherTransactionTotalTime/php__FILE__"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], @@ -101,4 +101,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid1.php b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid1.php index f33d832af..f94ea94af 100644 --- a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid1.php +++ b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid1.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/LocalDecorating/PHP/disabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid2.php b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid2.php index 73c70e58e..5d0363243 100644 --- a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid2.php +++ b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid2.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid3.php b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid3.php index 72ca4b06b..8b451bdea 100644 --- a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid3.php +++ b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid3.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid4.php b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid4.php index 2f60d6bc1..fe4185197 100644 --- a/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid4.php +++ b/tests/integration/logging/monolog3/test_monolog_log_events_max_samples_stored_invalid4.php @@ -45,7 +45,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [833, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -81,4 +81,4 @@ function test_logging() { } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_log_level_filter.php b/tests/integration/logging/monolog3/test_monolog_log_level_filter.php index 529ef1459..69d482e9b 100644 --- a/tests/integration/logging/monolog3/test_monolog_log_level_filter.php +++ b/tests/integration/logging/monolog3/test_monolog_log_level_filter.php @@ -60,7 +60,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -171,4 +171,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging(); diff --git a/tests/integration/logging/monolog3/test_monolog_log_level_filter_invalid.php b/tests/integration/logging/monolog3/test_monolog_log_level_filter_invalid.php index e5387616f..649cd5acf 100644 --- a/tests/integration/logging/monolog3/test_monolog_log_level_filter_invalid.php +++ b/tests/integration/logging/monolog3/test_monolog_log_level_filter_invalid.php @@ -61,7 +61,7 @@ [{"name": "Supportability/Logging/Forwarding/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/Metrics/PHP/enabled"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/Logging/PHP/Monolog/enabled"}, [1, "??", "??", "??", "??", "??"]], - [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [8, "??", "??", "??", "??", "??"]], + [{"name": "Supportability/PHP/package/monolog/monolog/3/detected"}, [1, "??", "??", "??", "??", "??"]], [{"name": "Supportability/library/Monolog/detected"}, [1, "??", "??", "??", "??", "??"]] ] ] @@ -172,4 +172,4 @@ function test_logging() { $logger->emergency("emergency"); } -test_logging(); \ No newline at end of file +test_logging();