22
22
* In a normal course of events, the following line will always work
23
23
* zend_eval_string("Aws\\Sdk::VERSION;", &retval, "Get AWS Version")
24
24
* By the time we have detected the existence of the aws-sdk-php and with
25
- * default composer profject settings, it callable even from
25
+ * default composer project settings, it is callable even from
26
26
* nr_aws_sdk_php_enable which will automatically load the class if it isn't
27
- * loaded yet and then evaluate the string. However, in the rare case that files
27
+ * loaded yet and then evaluate the string. In the rare case that files
28
28
* are not loaded via autoloader and/or have non-default composer classload
29
- * settings, if the class is not found, PHP 8.2+ will generate a fatal
30
- * unrecoverable uncatchable error error whenever it cannot find a class. While
31
- * calling this from nr_aws_sdk_php_enable would have been great and would allow
32
- * the sdk version value to be set only once, to avoid the very unlikely but not
33
- * impossible fatal error, this will be called from the
34
- * "Aws\\ClientResolver::_apply_user_agent" wrapper which GUARANTEES that
35
- * aws/sdk exists and is already loaded.
36
- *
37
- *
38
- * Additionally given that aws-sdk-php is currently detected from the
39
- * AwsClient.php file, this method will always be called when a client is
40
- * created unlike Sdk::construct which doesn't show with PHP 8.2+.
41
- *
42
- * Using Aws/Sdk::__construct for version is currently nonviable as it is
43
- * unreliable as a version determiner.
44
- * Having separate functionality to extract from Aws/Sdk::__construct
45
- * is both not required and is redundant and causes additional overhead and
46
- * so only one function is needed to extract version.
47
- *
48
- * Aws\\ClientResolver::_apply_user_agent a reliable function as it is
49
- * always called on client initialization since it is key to populating
50
- * the request headers, and it loads Sdk by default.
51
- *
52
- * Concerns about future/past proofing to the checking prioritized the following
53
- * implementation vs using the eval method.
29
+ * settings, if the class is not found, PHP 8.2+ will generate an
30
+ * error whenever it cannot find a class which must be caught. Calling this
31
+ * from nr_aws_sdk_php_enable would allow the sdk version value to be set only
32
+ * once. To avoid the VERY unlikely but not impossible fatal error, we need to
33
+ * wrap the call in a try/catch block and make it a lambda so that we avoid
34
+ * fatal errors.
54
35
*/
55
36
void nr_lib_aws_sdk_php_handle_version () {
56
- zval * zval_version = NULL ;
57
- zend_class_entry * class_entry = NULL ;
58
37
char * version = NULL ;
59
-
60
- class_entry = nr_php_find_class ("aws\\sdk" );
61
- if (NULL != class_entry ) {
62
- zval_version = nr_php_get_class_constant (class_entry , "VERSION" );
63
-
64
- if (nr_php_is_zval_non_empty_string (zval_version )) {
65
- version = Z_STRVAL_P (zval_version );
38
+ zval retval ;
39
+ int result = FAILURE ;
40
+
41
+ result = zend_eval_string (
42
+ "(function() {"
43
+ " $nr_aws_sdk_version = '';"
44
+ " try {"
45
+ " $nr_aws_sdk_version = Aws\\Sdk::VERSION;"
46
+ " } catch (Throwable $e) {"
47
+ " }"
48
+ " return $nr_aws_sdk_version;"
49
+ "})();" ,
50
+ & retval , "Get nr_aws_sdk_version" );
51
+
52
+ /* See if we got a non-empty/non-null string for version. */
53
+ if (SUCCESS == result ) {
54
+ if (nr_php_is_zval_non_empty_string (& retval )) {
55
+ version = Z_STRVAL (retval );
66
56
}
67
57
}
58
+
68
59
if (NRINI (vulnerability_management_package_detection_enabled )) {
69
60
/* Add php package to transaction */
70
61
nr_txn_add_php_package (NRPRG (txn ), PHP_PACKAGE_NAME , version );
@@ -73,7 +64,7 @@ void nr_lib_aws_sdk_php_handle_version() {
73
64
nr_txn_suggest_package_supportability_metric (NRPRG (txn ), PHP_PACKAGE_NAME ,
74
65
version );
75
66
76
- nr_php_zval_free ( & zval_version );
67
+ zval_dtor ( & retval );
77
68
}
78
69
79
70
void nr_lib_aws_sdk_php_add_supportability_service_metric (
@@ -96,13 +87,6 @@ void nr_lib_aws_sdk_php_add_supportability_service_metric(
96
87
nrm_force_add (NRPRG (txn ) ? NRTXN (unscoped_metrics ) : 0 , buf , 0 );
97
88
}
98
89
99
- NR_PHP_WRAPPER (nr_create_aws_sdk_version_metrics ) {
100
- (void )wraprec ;
101
- NR_PHP_WRAPPER_CALL ;
102
- nr_lib_aws_sdk_php_handle_version ();
103
- }
104
- NR_PHP_WRAPPER_END
105
-
106
90
/*
107
91
* AwsClient::parseClass
108
92
* This is called from the base AwsClient class for every client associated
@@ -144,7 +128,7 @@ NR_PHP_WRAPPER_END
144
128
* optimizable library. Small overhead incurred when encountering an autoload
145
129
* file, but detects aws-sdk-php immediately before any sdk code executes
146
130
* (changes needed for this are detailed in the original PR)
147
- * 2. use a file that gets called later and only when AwsClient.php file file is
131
+ * 2. use a file that gets called later and only when AwsClient.php file is
148
132
* called. It's called later and we'll miss some instrumentation, but if we're
149
133
* only ever going to be interested in Client calls anyway, maybe that's ok?
150
134
* Doesn't detect Sdk.php (optimized out) so when customers only use that or
@@ -158,22 +142,24 @@ NR_PHP_WRAPPER_END
158
142
* to wrap, this will add overhead to every hash map lookup. Currently
159
143
* implemented option is 2, use the AwsClient.php as this is our main focus.
160
144
* This means until a call to an Aws/AwsClient function,
161
- * all calls including aws\sdk calls are ignored. Version detection will be
162
- * tied to Aws/ClientResolver::_apply_user_agent which is ALWAYS called when
163
- * dealing with aws clients. It will not be computed from
164
- * Aws/Sdk::__constructor which would at best be duplicate info and worst would
165
- * never be ignored until a client is called.
145
+ * all calls including aws\sdk calls are ignored.
146
+ *
147
+ * Version detection will be called directly from Aws\Sdk.php
166
148
*/
167
149
void nr_aws_sdk_php_enable () {
168
- /* This will be used to extract the version. */
169
- nr_php_wrap_user_function (NR_PSTR ("Aws\\ClientResolver::_apply_user_agent" ),
170
- nr_create_aws_sdk_version_metrics );
171
- /* Called when initializing all other Clients */
172
- nr_php_wrap_user_function (NR_PSTR ("Aws\\AwsClient::parseClass" ),
173
- nr_create_aws_service_metric );
174
-
150
+ /*
151
+ * Set the UNKNOWN package first, so it doesn't overwrite what we find with
152
+ * nr_lib_aws_sdk_php_handle_version.
153
+ */
175
154
if (NRINI (vulnerability_management_package_detection_enabled )) {
176
155
nr_txn_add_php_package (NRPRG (txn ), PHP_PACKAGE_NAME ,
177
156
PHP_PACKAGE_VERSION_UNKNOWN );
178
157
}
158
+
159
+ /* Extract the version for aws-sdk 3+ */
160
+ nr_lib_aws_sdk_php_handle_version ();
161
+
162
+ /* Called when initializing all Clients */
163
+ nr_php_wrap_user_function (NR_PSTR ("Aws\\AwsClient::parseClass" ),
164
+ nr_create_aws_service_metric );
179
165
}
0 commit comments