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
+ * take an extra step to wrap the call in a try/catch block. This means we need
34
+ * to have an additionial zend_string_eval to get the result, but we avoid fatal
35
+ * errors.
54
36
*/
55
37
void nr_lib_aws_sdk_php_handle_version () {
56
- zval * zval_version = NULL ;
57
- zend_class_entry * class_entry = NULL ;
58
38
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 );
39
+ zval retval ;
40
+ int result = FAILURE ;
41
+
42
+ result = zend_eval_string (
43
+ "$nr_aws_sdk_version = '';"
44
+ "try {"
45
+ " $nr_aws_sdk_version = Aws\\Sdk::VERSION;"
46
+ "} catch(Throwable $_e) {"
47
+ "}" ,
48
+ NULL , "Set nr_aws_sdk_version" );
49
+
50
+ if (SUCCESS == result ) {
51
+ result = zend_eval_string ("$nr_aws_sdk_version" , & retval ,
52
+ "Get nr_aws_sdk_version" );
53
+
54
+ /* See if we got a non-empty/non-null string for version. */
55
+ if (SUCCESS == result ) {
56
+ if (nr_php_is_zval_non_empty_string (& retval )) {
57
+ version = Z_STRVAL (retval );
58
+ }
66
59
}
67
60
}
61
+
68
62
if (NRINI (vulnerability_management_package_detection_enabled )) {
69
63
/* Add php package to transaction */
70
64
nr_txn_add_php_package (NRPRG (txn ), PHP_PACKAGE_NAME , version );
@@ -73,7 +67,7 @@ void nr_lib_aws_sdk_php_handle_version() {
73
67
nr_txn_suggest_package_supportability_metric (NRPRG (txn ), PHP_PACKAGE_NAME ,
74
68
version );
75
69
76
- nr_php_zval_free ( & zval_version );
70
+ zval_dtor ( & retval );
77
71
}
78
72
79
73
void nr_lib_aws_sdk_php_add_supportability_service_metric (
@@ -96,13 +90,6 @@ void nr_lib_aws_sdk_php_add_supportability_service_metric(
96
90
nrm_force_add (NRPRG (txn ) ? NRTXN (unscoped_metrics ) : 0 , buf , 0 );
97
91
}
98
92
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
93
/*
107
94
* AwsClient::parseClass
108
95
* This is called from the base AwsClient class for every client associated
@@ -144,7 +131,7 @@ NR_PHP_WRAPPER_END
144
131
* optimizable library. Small overhead incurred when encountering an autoload
145
132
* file, but detects aws-sdk-php immediately before any sdk code executes
146
133
* (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
134
+ * 2. use a file that gets called later and only when AwsClient.php file is
148
135
* called. It's called later and we'll miss some instrumentation, but if we're
149
136
* only ever going to be interested in Client calls anyway, maybe that's ok?
150
137
* Doesn't detect Sdk.php (optimized out) so when customers only use that or
@@ -158,22 +145,24 @@ NR_PHP_WRAPPER_END
158
145
* to wrap, this will add overhead to every hash map lookup. Currently
159
146
* implemented option is 2, use the AwsClient.php as this is our main focus.
160
147
* 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.
148
+ * all calls including aws\sdk calls are ignored.
149
+ *
150
+ * Version detection will be called directly from Aws\Sdk.php
166
151
*/
167
152
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
-
153
+ /*
154
+ * Set the UNKNOWN package first, so it doesn't overwrite what we find with
155
+ * nr_lib_aws_sdk_php_handle_version.
156
+ */
175
157
if (NRINI (vulnerability_management_package_detection_enabled )) {
176
158
nr_txn_add_php_package (NRPRG (txn ), PHP_PACKAGE_NAME ,
177
159
PHP_PACKAGE_VERSION_UNKNOWN );
178
160
}
161
+
162
+ /* Extract the version for aws-sdk 3+ */
163
+ nr_lib_aws_sdk_php_handle_version ();
164
+
165
+ /* Called when initializing all Clients */
166
+ nr_php_wrap_user_function (NR_PSTR ("Aws\\AwsClient::parseClass" ),
167
+ nr_create_aws_service_metric );
179
168
}
0 commit comments