Skip to content

Commit b78ac2d

Browse files
authored
fix(agent): fix legacy package detection issues (#1107)
When Composer runtime API is used to get packages information, the agent should not generate packages information using legacy methods. This solves the problem of package data detected with the help of Composer's runtime API not to be sent to the backend in environments using “once-per-process” setting. The reason for is that the first request generates package information using Composer's runtime API but every next request only generates package information using legacy method. This in conjunction with the fact that daemon is only sending the last package information received from the daemon leads to a situation that package information returned by Composer runtime API is lost and never makes it to the backend.
1 parent c395102 commit b78ac2d

File tree

8 files changed

+75
-20
lines changed

8 files changed

+75
-20
lines changed

agent/lib_composer.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,25 @@ static int nr_execute_handle_autoload_composer_init(const char* vendor_path) {
6969
return NR_SUCCESS;
7070
}
7171

72-
static void nr_execute_handle_autoload_composer_get_packages_information(
72+
static nr_composer_api_status_t
73+
nr_execute_handle_autoload_composer_get_packages_information(
7374
const char* vendor_path) {
7475
zval retval; // This is used as a return value for zend_eval_string.
7576
// It will only be set if the result of the eval is SUCCESS.
7677
int result = FAILURE;
78+
nr_composer_api_status_t api_status = NR_COMPOSER_API_STATUS_UNSET;
7779

7880
// nrunlikely because this should alredy be ensured by the caller
7981
if (nrunlikely(!NRINI(vulnerability_management_package_detection_enabled))) {
8082
// do nothing when collecting package information for vulnerability
8183
// management is disabled
82-
return;
84+
return NR_COMPOSER_API_STATUS_INVALID_USE;
8385
}
8486

8587
// nrunlikely because this should alredy be ensured by the caller
8688
if (nrunlikely(!NRINI(vulnerability_management_composer_api_enabled))) {
8789
// do nothing when use of composer to collect package info is disabled
88-
return;
90+
return NR_COMPOSER_API_STATUS_INVALID_USE;
8991
}
9092

9193
// clang-format off
@@ -124,7 +126,7 @@ static void nr_execute_handle_autoload_composer_get_packages_information(
124126
"%s - unable to initialize Composer runtime API - package info "
125127
"unavailable",
126128
__func__);
127-
return;
129+
return NR_COMPOSER_API_STATUS_INIT_FAILURE;
128130
}
129131

130132
nrl_verbosedebug(NRL_INSTRUMENT, "%s - Composer runtime API available",
@@ -135,13 +137,7 @@ static void nr_execute_handle_autoload_composer_get_packages_information(
135137
if (SUCCESS != result) {
136138
nrl_verbosedebug(NRL_INSTRUMENT, "%s - composer_getallrawdata.php failed",
137139
__func__);
138-
return;
139-
}
140-
141-
if (NR_PHP_PROCESS_GLOBALS(composer_api_per_process_detection)) {
142-
// set the per-process flag to true to avoid re-running composer api
143-
// detection when the per-process detection is enabled.
144-
NR_PHP_PROCESS_GLOBALS(composer_packages_detected) = 1;
140+
return NR_COMPOSER_API_STATUS_CALL_FAILURE;
145141
}
146142

147143
if (IS_ARRAY == Z_TYPE(retval)) {
@@ -162,14 +158,17 @@ static void nr_execute_handle_autoload_composer_get_packages_information(
162158
}
163159
}
164160
ZEND_HASH_FOREACH_END();
161+
api_status = NR_COMPOSER_API_STATUS_PACKAGES_COLLECTED;
165162
} else {
166163
char strbuf[80];
167164
nr_format_zval_for_debug(&retval, strbuf, 0, sizeof(strbuf) - 1, 0);
168165
nrl_verbosedebug(NRL_INSTRUMENT,
169166
"%s - installed packages is: " NRP_FMT ", not an array",
170167
__func__, NRP_ARGSTR(strbuf));
168+
api_status = NR_COMPOSER_API_STATUS_INVALID_RESULT;
171169
}
172170
zval_dtor(&retval);
171+
return api_status;
173172
}
174173

175174
static char* nr_execute_handle_autoload_composer_get_vendor_path(
@@ -274,7 +273,9 @@ void nr_composer_handle_autoload(const char* filename) {
274273
NRPRG(txn)->composer_info.composer_detected = true;
275274
nr_fw_support_add_library_supportability_metric(NRPRG(txn), "Composer");
276275

277-
nr_execute_handle_autoload_composer_get_packages_information(vendor_path);
276+
NRTXN(composer_info.api_status)
277+
= nr_execute_handle_autoload_composer_get_packages_information(
278+
vendor_path);
278279
leave:
279280
nr_free(vendor_path);
280281
}

agent/php_execute.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -875,12 +875,13 @@ static void nr_execute_handle_autoload(const char* filename,
875875
return;
876876
}
877877

878-
if (NR_PHP_PROCESS_GLOBALS(composer_api_per_process_detection)
879-
&& NR_PHP_PROCESS_GLOBALS(composer_packages_detected)) {
880-
// do nothing if per-process detection is enabled and the flag to track
881-
// detection is true
878+
// clang-format off
879+
if (NR_PHP_PROCESS_GLOBALS(composer_api_per_process_detection) &&
880+
NR_COMPOSER_API_STATUS_UNSET != NR_PHP_PROCESS_GLOBALS(composer_api_status)) {
881+
// do nothing if per-process detection is enabled and composer api status is set
882882
return;
883883
}
884+
// clang-format on
884885

885886
if (!nr_striendswith(STR_AND_LEN(filename), AUTOLOAD_MAGIC_FILE,
886887
AUTOLOAD_MAGIC_FILE_LEN)) {

agent/php_globals.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ typedef struct _nrphpglobals_t {
7878
int composer_api_per_process_detection; /* Enables per-process VM package
7979
detection when Composer API is also
8080
enabled */
81-
int composer_packages_detected; /* Flag to indicate that Composer package
82-
detection has run. Used in conjunction with
83-
composer_api_per_process_detection. */
81+
nr_composer_api_status_t composer_api_status; /* Composer API's status */
8482
char* docker_id; /* 64 byte hex docker ID parsed from /proc/self/mountinfo */
8583

8684
/* Original PHP callback pointer contents */

agent/php_minit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ PHP_MINIT_FUNCTION(newrelic) {
456456
= nr_php_check_for_upgrade_license_key();
457457
NR_PHP_PROCESS_GLOBALS(high_security) = 0;
458458
NR_PHP_PROCESS_GLOBALS(preload_framework_library_detection) = 1;
459-
NR_PHP_PROCESS_GLOBALS(composer_packages_detected) = 0;
459+
NR_PHP_PROCESS_GLOBALS(composer_api_status) = NR_COMPOSER_API_STATUS_UNSET;
460460
nr_php_populate_apache_process_globals();
461461
nr_php_api_distributed_trace_register_userland_class(TSRMLS_C);
462462
/*

agent/php_txn.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,8 @@ nr_status_t nr_php_txn_begin(const char* appnames,
11511151
}
11521152
}
11531153

1154+
NRTXN(composer_info.api_status) = NR_PHP_PROCESS_GLOBALS(composer_api_status);
1155+
11541156
return NR_SUCCESS;
11551157
}
11561158

@@ -1340,6 +1342,8 @@ nr_status_t nr_php_txn_end(int ignoretxn, int in_post_deactivate TSRMLS_DC) {
13401342
if (NR_FAILURE == ret) {
13411343
nrl_debug(NRL_TXN, "failed to send txn");
13421344
}
1345+
NR_PHP_PROCESS_GLOBALS(composer_api_status)
1346+
= NRTXN(composer_info.api_status);
13431347
}
13441348
}
13451349

axiom/nr_txn.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3539,6 +3539,14 @@ nr_php_package_t* nr_txn_add_php_package_from_source(
35393539
return NULL;
35403540
}
35413541

3542+
if (NR_PHP_PACKAGE_SOURCE_LEGACY == source
3543+
&& NR_COMPOSER_API_STATUS_PACKAGES_COLLECTED
3544+
== txn->composer_info.api_status) {
3545+
// don't add packages from legacy source if packages have been detected
3546+
// using composer runtime api
3547+
return NULL;
3548+
}
3549+
35423550
p = nr_php_package_create_with_source(package_name, package_version, source);
35433551
return nr_php_packages_add_package(txn->php_packages, p);
35443552
}

axiom/nr_txn.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,19 @@ typedef enum _nr_cpu_usage_t {
207207
NR_CPU_USAGE_COUNT = 2
208208
} nr_cpu_usage_t;
209209

210+
typedef enum {
211+
NR_COMPOSER_API_STATUS_UNSET = 0,
212+
NR_COMPOSER_API_STATUS_INVALID_USE = 1,
213+
NR_COMPOSER_API_STATUS_INIT_FAILURE = 2,
214+
NR_COMPOSER_API_STATUS_CALL_FAILURE = 3,
215+
NR_COMPOSER_API_STATUS_PACKAGES_COLLECTED = 4,
216+
NR_COMPOSER_API_STATUS_INVALID_RESULT = 5,
217+
} nr_composer_api_status_t;
218+
210219
typedef struct _nr_composer_info_t {
211220
bool autoload_detected;
212221
bool composer_detected;
222+
nr_composer_api_status_t api_status;
213223
} nr_composer_info_t;
214224

215225
/*

axiom/tests/test_txn.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8665,6 +8665,16 @@ static void test_nr_txn_add_php_package(void) {
86658665
tlib_pass_if_ptr_equal(
86668666
"same package name, different version, add returns same pointer", p1, p2);
86678667
nr_txn_destroy(&txn);
8668+
8669+
txn = new_txn(0);
8670+
// simulate composer api was successfully used
8671+
txn->composer_info.api_status = NR_COMPOSER_API_STATUS_PACKAGES_COLLECTED;
8672+
p1 = nr_txn_add_php_package(txn, package_name1, package_version1);
8673+
tlib_pass_if_null(
8674+
"legacy package information not added to transaction after composer api "
8675+
"was called successfully",
8676+
p1);
8677+
nr_txn_destroy(&txn);
86688678
}
86698679

86708680
static void test_nr_txn_add_php_package_from_source(void) {
@@ -8730,6 +8740,29 @@ static void test_nr_txn_add_php_package_from_source(void) {
87308740
p2->package_version);
87318741

87328742
nr_txn_destroy(&txn);
8743+
8744+
txn = new_txn(0);
8745+
// simulate composer api was successfully used
8746+
txn->composer_info.api_status = NR_COMPOSER_API_STATUS_PACKAGES_COLLECTED;
8747+
p1 = nr_txn_add_php_package_from_source(txn, package_name1, package_version1,
8748+
NR_PHP_PACKAGE_SOURCE_LEGACY);
8749+
tlib_pass_if_null(
8750+
"legacy package information not added to transaction after composer api "
8751+
"was called successfully",
8752+
p1);
8753+
p1 = nr_txn_add_php_package_from_source(txn, package_name1, package_version1,
8754+
NR_PHP_PACKAGE_SOURCE_SUGGESTION);
8755+
tlib_pass_if_not_null(
8756+
"suggestion package information added to transaction even after composer "
8757+
"api was called successfully",
8758+
p1);
8759+
p1 = nr_txn_add_php_package_from_source(txn, package_name1, package_version1,
8760+
NR_PHP_PACKAGE_SOURCE_COMPOSER);
8761+
tlib_pass_if_not_null(
8762+
"composer package information added to transaction even after composer "
8763+
"api was called successfully",
8764+
p1);
8765+
nr_txn_destroy(&txn);
87338766
}
87348767

87358768
static void test_nr_txn_suggest_package_supportability_metric(void) {

0 commit comments

Comments
 (0)