Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(agent): Add RabbitMQ instrumentation using the php-amqplib library #1009

Open
wants to merge 73 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
2df782f
feat(agent): Add RabbitMQ instrumentation using the php-amqplib library
zsistla Jan 18, 2025
0b184ca
feat(agent): Add RabbitMQ instrumentation using the php-amqplib library
zsistla Jan 18, 2025
3e7dc66
Merge branch 'feat/rabbitmq_instrumentation' of github.com:newrelic/n…
zsistla Jan 22, 2025
feba725
fix(agent): Typo remove AWS references
zsistla Jan 23, 2025
feef4be
fix(agent): typo
zsistla Jan 23, 2025
761de36
feat(agent): Add additional unit test
zsistla Jan 23, 2025
80be7a5
chore(agent): Clarifying comment.
zsistla Jan 23, 2025
b50a5d2
feat(axiom): Update message segment to handle rabbitmq
zsistla Jan 25, 2025
075e297
feat(agent): Add php_amqplib basic_publish instrumentation.
zsistla Jan 29, 2025
f106a20
fix(axiom): Handle final metrix/txn naming when publish_name exists.
zsistla Jan 29, 2025
631ae54
feat(agent): Add php_libamqp basic_get instrumentation.
zsistla Jan 29, 2025
f3502b5
fix(tests): Update tests to understand the precedence of publish_name
zsistla Jan 29, 2025
eaac00d
fix(agent): Handle vagaries of different Connection classes
zsistla Jan 30, 2025
095f82d
fix(agent): check long not scalar
zsistla Jan 31, 2025
71e5e02
fix(agent): add an unperist macro
zsistla Jan 31, 2025
2335634
Merge branch 'dev' into feat/rabbitmq_instrumentation
zsistla Jan 31, 2025
ead28c2
fix(agent): Only set to 'default' in case of valid but empty string
zsistla Jan 31, 2025
0d708cb
feat(agent): Insert/retrieve DT headers on rabbitmq
zsistla Feb 4, 2025
0009a56
fix(agent): Update docstring
zsistla Feb 4, 2025
88c904d
style(agent): rename variable
zsistla Feb 4, 2025
4aa2522
style(agent): Comment clarification
zsistla Feb 5, 2025
b5c7def
style(agent): Comment update
zsistla Feb 5, 2025
0e6ec90
fix(agent): Update comment
zsistla Feb 5, 2025
127e62a
fix(agent): Comment about support.
zsistla Feb 5, 2025
a8569a2
Update agent/lib_php_amqplib.c
zsistla Feb 5, 2025
d6f40fa
fix(agent): belongs inside the block that checked for valid retval
zsistla Feb 5, 2025
e27a78e
fix(agent): Expectations needed to be flipped after a previous refactor
zsistla Feb 5, 2025
23a8a34
fix(agent): unneeded var
zsistla Feb 5, 2025
10858da
fix(agent): Update comments regarding DT vs w3c header behavior
zsistla Feb 6, 2025
89d2937
fix(agent): just bail early from headers if DT isn't on
zsistla Feb 6, 2025
90da3b7
fix(agent): use zval is integer function
zsistla Feb 6, 2025
f160b3b
fix(agent): Move dtors closer to where the values are initialized
zsistla Feb 6, 2025
6e05947
fix(agent): add dtor closer to init
zsistla Feb 6, 2025
cd431ec
fix(agent): Calling order
zsistla Feb 7, 2025
ebb6ff0
feat(agent): Add RabbitMQ instrumentation using the php-amqplib library
zsistla Jan 18, 2025
96f15aa
fix(agent): Typo remove AWS references
zsistla Jan 23, 2025
33765b2
fix(agent): typo
zsistla Jan 23, 2025
90c8aa9
feat(agent): Add additional unit test
zsistla Jan 23, 2025
32a46a1
chore(agent): Clarifying comment.
zsistla Jan 23, 2025
ba1ab3f
feat(axiom): Update message segment to handle rabbitmq
zsistla Jan 25, 2025
22f9185
feat(agent): Add php_amqplib basic_publish instrumentation.
zsistla Jan 29, 2025
7453159
fix(axiom): Handle final metrix/txn naming when publish_name exists.
zsistla Jan 29, 2025
cdbafd3
feat(agent): Add php_libamqp basic_get instrumentation.
zsistla Jan 29, 2025
98061cd
fix(tests): Update tests to understand the precedence of publish_name
zsistla Jan 29, 2025
de70737
fix(agent): Handle vagaries of different Connection classes
zsistla Jan 30, 2025
49f93b3
fix(agent): check long not scalar
zsistla Jan 31, 2025
c937d74
fix(agent): add an unperist macro
zsistla Jan 31, 2025
08bf3ff
fix(agent): Only set to 'default' in case of valid but empty string
zsistla Jan 31, 2025
a9b7d62
feat(agent): Insert/retrieve DT headers on rabbitmq
zsistla Feb 4, 2025
8a30861
fix(agent): Update docstring
zsistla Feb 4, 2025
fc2e880
style(agent): rename variable
zsistla Feb 4, 2025
24d9617
style(agent): Comment clarification
zsistla Feb 5, 2025
2bd6f97
style(agent): Comment update
zsistla Feb 5, 2025
b024ce6
fix(agent): Update comment
zsistla Feb 5, 2025
e246369
fix(agent): Comment about support.
zsistla Feb 5, 2025
a965d83
Update agent/lib_php_amqplib.c
zsistla Feb 5, 2025
e2c8e05
fix(agent): belongs inside the block that checked for valid retval
zsistla Feb 5, 2025
b814dc4
fix(agent): Expectations needed to be flipped after a previous refactor
zsistla Feb 5, 2025
7a4c0b9
fix(agent): unneeded var
zsistla Feb 5, 2025
fc6769d
fix(agent): Update comments regarding DT vs w3c header behavior
zsistla Feb 6, 2025
011a6f7
fix(agent): just bail early from headers if DT isn't on
zsistla Feb 6, 2025
d4fc082
fix(agent): use zval is integer function
zsistla Feb 6, 2025
60fd628
fix(agent): Move dtors closer to where the values are initialized
zsistla Feb 6, 2025
e623e99
fix(agent): add dtor closer to init
zsistla Feb 6, 2025
839b098
fix(agent): Calling order
zsistla Feb 7, 2025
ba45e6c
Update agent/lib_php_amqplib.c
zsistla Feb 7, 2025
87f641e
fix(agent): return null in version check and handle that outcome
zsistla Feb 7, 2025
7eb5a8e
Merge branch 'feat/rabbitmq_instrumentation' of github.com:newrelic/n…
zsistla Feb 7, 2025
3fa60ec
fix(agent): revert rebase error
zsistla Feb 7, 2025
268c28b
fix(agent): It's actually fine if version is null
zsistla Feb 8, 2025
73b47b2
fix(agent): check if Channel class exists before trying to manually l…
zsistla Feb 10, 2025
54f720d
style(agent): rename eval_string last param
zsistla Feb 10, 2025
55383f0
fix(agent): use zend_eval_stringl
zsistla Feb 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions agent/Makefile.frag
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ TEST_BINARIES = \
tests/test_internal_instrument \
tests/test_hash \
tests/test_lib_aws_sdk_php \
tests/test_lib_php_ampqlib \
tests/test_memcached \
tests/test_mongodb \
tests/test_monolog \
Expand Down
2 changes: 1 addition & 1 deletion agent/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ if test "$PHP_NEWRELIC" = "yes"; then
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_composer.c"
lib_composer.c lib_php_amqplib.c"
PHP_NEW_EXTENSION(newrelic, $FRAMEWORKS $LIBRARIES $NEWRELIC_AGENT, $ext_shared,, $(NEWRELIC_CFLAGS))

PHP_SUBST(NEWRELIC_CFLAGS)
Expand Down
1 change: 1 addition & 0 deletions agent/fw_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ extern void nr_guzzle4_enable(TSRMLS_D);
extern void nr_guzzle6_enable(TSRMLS_D);
extern void nr_laminas_http_enable(TSRMLS_D);
extern void nr_mongodb_enable(TSRMLS_D);
extern void nr_php_amqplib_enable();
extern void nr_phpunit_enable(TSRMLS_D);
extern void nr_predis_enable(TSRMLS_D);
extern void nr_zend_http_enable(TSRMLS_D);
Expand Down
82 changes: 82 additions & 0 deletions agent/lib_php_amqplib.c
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
lavarou marked this conversation as resolved.
Show resolved Hide resolved
* 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 {"
mfulb marked this conversation as resolved.
Show resolved Hide resolved
" $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) {
mfulb marked this conversation as resolved.
Show resolved Hide resolved
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"),
mfulb marked this conversation as resolved.
Show resolved Hide resolved
// nr_create_aws_service_metric);
}
13 changes: 13 additions & 0 deletions agent/lib_php_amqplib.h
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 */
4 changes: 4 additions & 0 deletions agent/php_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ static nr_library_table_t libraries[] = {

{"MongoDB", NR_PSTR("mongodb/src/client.php"), nr_mongodb_enable},

/* php-amqplib RabbitMQ >= 3.7 */
lavarou marked this conversation as resolved.
Show resolved Hide resolved
{"php-amqplib", NR_PSTR("phpamqplib/connection/abstractconnection.php"),
nr_php_amqplib_enable},
lavarou marked this conversation as resolved.
Show resolved Hide resolved

/*
* The first path is for Composer installs, the second is for
* /usr/local/bin.
Expand Down
110 changes: 110 additions & 0 deletions agent/tests/test_lib_php_amqplib.c
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();
}

mfulb marked this conversation as resolved.
Show resolved Hide resolved
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
Loading