-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(agent): Add RabbitMQ instrumentation using the php-amqplib library
Initial commit does the following: * Detect library via magic file * Detect package and version information. * Basic unit tests
- Loading branch information
Showing
7 changed files
with
212 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/* | ||
* Functions relating to instrumenting the AWS-SDK-PHP. | ||
* https://github.com/aws/aws-sdk-php | ||
*/ | ||
#include "php_agent.h" | ||
#include "php_call.h" | ||
#include "php_hash.h" | ||
#include "php_wrapper.h" | ||
#include "fw_hooks.h" | ||
#include "fw_support.h" | ||
#include "util_logging.h" | ||
#include "lib_php_amqplib.h" | ||
|
||
#define PHP_PACKAGE_NAME "php-amqplib/php-amqplib" | ||
|
||
/* | ||
* nr_php_amqplib_handle_version will automatically load the class if it isn't | ||
* loaded yet and then evaluate the string. To avoid the VERY unlikely but not | ||
* impossible fatal error if the file/class isn't loaded yet, we need to wrap | ||
* the call in a try/catch block and make it a lambda so that we avoid fatal | ||
* errors. | ||
*/ | ||
void nr_php_amqplib_handle_version() { | ||
char* version = NULL; | ||
zval retval; | ||
int result = FAILURE; | ||
|
||
result = zend_eval_string( | ||
"(function() {" | ||
" $nr_php_amqplib_version = '';" | ||
" try {" | ||
" $nr_php_amqplib_version = PhpAmqpLib\\Package::VERSION;" | ||
" } catch (Throwable $e) {" | ||
" }" | ||
" return $nr_php_amqplib_version;" | ||
"})();", | ||
&retval, "Get nr_php_amqplib_version"); | ||
|
||
/* See if we got a non-empty/non-null string for version. */ | ||
if (SUCCESS == result) { | ||
if (nr_php_is_zval_non_empty_string(&retval)) { | ||
version = Z_STRVAL(retval); | ||
} | ||
} | ||
|
||
if (NRINI(vulnerability_management_package_detection_enabled)) { | ||
/* Add php package to transaction */ | ||
nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, version); | ||
} | ||
|
||
nr_txn_suggest_package_supportability_metric(NRPRG(txn), PHP_PACKAGE_NAME, | ||
version); | ||
|
||
zval_dtor(&retval); | ||
} | ||
|
||
/* | ||
* | ||
* Version detection will be called directly from Aws\Sdk.php | ||
*/ | ||
void nr_php_amqplib_enable() { | ||
/* | ||
* Set the UNKNOWN package first, so it doesn't overwrite what we find with | ||
* nr_lib_aws_sdk_php_handle_version. | ||
*/ | ||
if (NRINI(vulnerability_management_package_detection_enabled)) { | ||
nr_txn_add_php_package(NRPRG(txn), PHP_PACKAGE_NAME, | ||
PHP_PACKAGE_VERSION_UNKNOWN); | ||
} | ||
|
||
/* Extract the version for aws-sdk 3+ */ | ||
nr_php_amqplib_handle_version(); | ||
|
||
/* Called when initializing all Clients */ | ||
// nr_php_wrap_user_function(NR_PSTR("Aws\\AwsClient::parseClass"), | ||
// nr_create_aws_service_metric); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Functions relating to instrumenting AWS-SDK-PHP. | ||
*/ | ||
#ifndef LIB_PHP_AMQPLIB | ||
#define LIB_PHP_AMQPLIB | ||
|
||
extern void nr_aws_php_amqplib_enable(); | ||
extern void nr_php_amqplib_handle_version(); | ||
|
||
#endif /* LIB_PHP_AMQPLIB */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "tlib_php.h" | ||
|
||
#include "php_agent.h" | ||
#include "lib_php_amqplib.h" | ||
#include "fw_support.h" | ||
|
||
tlib_parallel_info_t parallel_info | ||
= {.suggested_nthreads = -1, .state_size = 0}; | ||
|
||
#if ZEND_MODULE_API_NO > ZEND_7_1_X_API_NO | ||
|
||
static void declare_php_amqplib_package_class(const char* ns, | ||
const char* klass, | ||
const char* sdk_version) { | ||
char* source = nr_formatf( | ||
"namespace %s;" | ||
"class %s{" | ||
"const VERSION = '%s';" | ||
"}", | ||
ns, klass, sdk_version); | ||
|
||
tlib_php_request_eval(source); | ||
|
||
nr_free(source); | ||
} | ||
|
||
static void test_nr_lib_php_amqplib_handle_version(void) { | ||
#define LIBRARY_NAME "php-amqplib/php-amqplib" | ||
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_php_amqplib_handle_version with library_versions[%ld]=%s: package " \ | ||
"major version metric - %s" | ||
char* test_description = NULL; | ||
size_t i = 0; | ||
|
||
/* | ||
* If lib_php_amqplib_handle_version function is ever called, we have already | ||
* detected the php-amqplib library. | ||
*/ | ||
|
||
/* | ||
* PhpAmqpLib/Package class exists. Should create php-amqplib package metric | ||
* suggestion with version | ||
*/ | ||
for (i = 0; i < sizeof(library_versions) / sizeof(library_versions[0]); i++) { | ||
tlib_php_request_start(); | ||
|
||
declare_php_amqplib_package_class("PhpAmqpLib", "Package", | ||
library_versions[i]); | ||
nr_lib_php_amqplib_handle_version(); | ||
|
||
p = nr_php_packages_get_package( | ||
NRPRG(txn)->php_package_major_version_metrics_suggestions, | ||
LIBRARY_NAME); | ||
|
||
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); | ||
|
||
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_end(); | ||
} | ||
|
||
/* | ||
* PhpAmqpLib/Package 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_php_amqplib_handle_version(); | ||
|
||
p = nr_php_packages_get_package( | ||
NRPRG(txn)->php_package_major_version_metrics_suggestions, LIBRARY_NAME); | ||
|
||
tlib_pass_if_not_null( | ||
"nr_lib_php_amqplib_handle_version when PhpAmqpLib\\Package class is not " | ||
"defined - " | ||
"suggestion created", | ||
p); | ||
tlib_pass_if_str_equal( | ||
"nr_lib_php_amqplib_handle_version when PhpAmqpLib\\Package class is not " | ||
"defined - " | ||
"suggested version set to PHP_PACKAGE_VERSION_UNKNOWN", | ||
PHP_PACKAGE_VERSION_UNKNOWN, p->package_version); | ||
|
||
tlib_php_request_end(); | ||
} | ||
|
||
void test_main(void* p NRUNUSED) { | ||
tlib_php_engine_create(""); | ||
test_nr_lib_php_amqplib_handle_version(); | ||
tlib_php_engine_destroy(); | ||
} | ||
#else | ||
void test_main(void* p NRUNUSED) {} | ||
#endif |