Skip to content

Commit 787c147

Browse files
feat(agent): add function to convert ini to env (#892)
1 parent f000c13 commit 787c147

File tree

6 files changed

+210
-33
lines changed

6 files changed

+210
-33
lines changed

agent/Makefile.frag

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ TEST_BINARIES = \
9797
tests/test_pdo_mysql \
9898
tests/test_pdo_pgsql \
9999
tests/test_pgsql \
100-
tests/test_php_error \
100+
tests/test_php_error \
101101
tests/test_php_execute \
102102
tests/test_php_minit \
103+
tests/test_php_nrini \
103104
tests/test_php_stack \
104105
tests/test_php_stacked_segment \
105106
tests/test_php_wrapper \

agent/php_nrini.c

Lines changed: 93 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "php_hash.h"
99
#include "php_internal_instrument.h"
1010
#include "php_user_instrument.h"
11+
#include "php_nrini.h"
1112

1213
#include "nr_commands.h"
1314
#include "nr_configstrings.h"
@@ -222,6 +223,62 @@
222223

223224
ZEND_DECLARE_MODULE_GLOBALS(newrelic)
224225

226+
char* nr_ini_to_env(const char* ini_name) {
227+
const int NR_INI_PREFIX_LEN = nr_strlen("newrelic.");
228+
char* env_name = NULL;
229+
char* buf = NULL;
230+
char* ini_upper = NULL;
231+
int ini_len = nr_strlen(ini_name);
232+
233+
// 'newrelic.' is 9 characters - anything less should be rejected.
234+
if (NULL == ini_name || nr_strlen(ini_name) <= NR_INI_PREFIX_LEN) {
235+
return NULL;
236+
}
237+
238+
// ini value should start with the 'newrelic.' prefix
239+
if (0 != nr_stridx(ini_name, "newrelic.")) {
240+
return NULL;
241+
}
242+
243+
// algorithm:
244+
// 1. uppercase ini string
245+
// 2. iterate through uppercase ini string and copy each character to the new
246+
// buffer, swapping each '.' with '_'.
247+
// 3. snprintf append the string to 'NEW_RELIC'
248+
// 4. return result
249+
250+
ini_upper = nr_string_to_uppercase(ini_name);
251+
252+
buf = (char*)nr_zalloc(ini_len - NR_INI_PREFIX_LEN + 1);
253+
254+
for (int i = NR_INI_PREFIX_LEN, j = 0; i < nr_strlen(ini_upper); i++) {
255+
if (NR_INI_PREFIX_LEN == i
256+
&& ('.' == ini_upper[i] || '_' == ini_upper[i])) {
257+
// skip if the first character is '.' or '_' to avoid double underscores
258+
continue;
259+
} else if ('_' == ini_upper[i] && '_' == ini_upper[i - 1]) {
260+
// skip double '_' characters
261+
continue;
262+
} else if ('.' == ini_upper[i] && '_' != ini_upper[i - 1]) {
263+
// replace a '.' with '_', provided the previous character is not also '_'
264+
buf[j] = '_';
265+
} else {
266+
// copy the character
267+
buf[j] = ini_upper[i];
268+
}
269+
j++;
270+
}
271+
272+
env_name = (char*)nr_zalloc(ini_len + 2);
273+
274+
snprintf(env_name, ini_len + 2, "%s_%s", "NEW_RELIC", buf);
275+
276+
nr_free(buf);
277+
nr_free(ini_upper);
278+
279+
return env_name;
280+
}
281+
225282
typedef void (*foreach_fn_t)(const char* name, int namelen TSRMLS_DC);
226283

227284
static void foreach_list(const char* str, foreach_fn_t f_eachname TSRMLS_DC) {
@@ -3039,42 +3096,46 @@ STD_PHP_INI_ENTRY_EX("newrelic.application_logging.metrics.enabled",
30393096
zend_newrelic_globals,
30403097
newrelic_globals,
30413098
nr_enabled_disabled_dh)
3042-
STD_PHP_INI_ENTRY_EX("newrelic.application_logging.forwarding.context_data.enabled",
3043-
"0",
3044-
NR_PHP_REQUEST,
3045-
nr_boolean_mh,
3046-
log_context_data_attributes.enabled,
3047-
zend_newrelic_globals,
3048-
newrelic_globals,
3049-
nr_enabled_disabled_dh)
3050-
STD_PHP_INI_ENTRY_EX("newrelic.application_logging.forwarding.context_data.include",
3051-
"",
3052-
NR_PHP_REQUEST,
3053-
nr_string_mh,
3054-
log_context_data_attributes.include,
3055-
zend_newrelic_globals,
3056-
newrelic_globals,
3057-
0)
3058-
STD_PHP_INI_ENTRY_EX("newrelic.application_logging.forwarding.context_data.exclude",
3059-
"",
3060-
NR_PHP_REQUEST,
3061-
nr_string_mh,
3062-
log_context_data_attributes.exclude,
3063-
zend_newrelic_globals,
3064-
newrelic_globals,
3065-
0)
3099+
STD_PHP_INI_ENTRY_EX(
3100+
"newrelic.application_logging.forwarding.context_data.enabled",
3101+
"0",
3102+
NR_PHP_REQUEST,
3103+
nr_boolean_mh,
3104+
log_context_data_attributes.enabled,
3105+
zend_newrelic_globals,
3106+
newrelic_globals,
3107+
nr_enabled_disabled_dh)
3108+
STD_PHP_INI_ENTRY_EX(
3109+
"newrelic.application_logging.forwarding.context_data.include",
3110+
"",
3111+
NR_PHP_REQUEST,
3112+
nr_string_mh,
3113+
log_context_data_attributes.include,
3114+
zend_newrelic_globals,
3115+
newrelic_globals,
3116+
0)
3117+
STD_PHP_INI_ENTRY_EX(
3118+
"newrelic.application_logging.forwarding.context_data.exclude",
3119+
"",
3120+
NR_PHP_REQUEST,
3121+
nr_string_mh,
3122+
log_context_data_attributes.exclude,
3123+
zend_newrelic_globals,
3124+
newrelic_globals,
3125+
0)
30663126

30673127
/*
30683128
* Vulnerability Management
30693129
*/
3070-
STD_PHP_INI_ENTRY_EX("newrelic.vulnerability_management.package_detection.enabled",
3071-
"1",
3072-
NR_PHP_REQUEST,
3073-
nr_boolean_mh,
3074-
vulnerability_management_package_detection_enabled,
3075-
zend_newrelic_globals,
3076-
newrelic_globals,
3077-
nr_enabled_disabled_dh)
3130+
STD_PHP_INI_ENTRY_EX(
3131+
"newrelic.vulnerability_management.package_detection.enabled",
3132+
"1",
3133+
NR_PHP_REQUEST,
3134+
nr_boolean_mh,
3135+
vulnerability_management_package_detection_enabled,
3136+
zend_newrelic_globals,
3137+
newrelic_globals,
3138+
nr_enabled_disabled_dh)
30783139

30793140
PHP_INI_END() /* } */
30803141

agent/php_nrini.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
* Copyright 2020 New Relic Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* This file declares nrini functions.
6+
*/
7+
#ifndef PHP_NRINI_HDR
8+
#define PHP_NRINI_HDR
9+
extern char* nr_ini_to_env(const char* ini_name);
10+
#endif /* PHP_NRINI_HDR */

agent/tests/test_php_nrini.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2020 New Relic Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "tlib_main.h"
7+
#include "tlib_php.h"
8+
9+
#include "php_agent.h"
10+
#include "php_nrini.h"
11+
12+
static void test_nr_ini_to_env(void) {
13+
char* res = NULL;
14+
15+
res = nr_ini_to_env("newrelic.enabled");
16+
17+
tlib_pass_if_str_equal("ini converted to env", "NEW_RELIC_ENABLED", res);
18+
19+
nr_free(res);
20+
21+
res = nr_ini_to_env(
22+
"newrelic.application_logging.forwarding.context_data.include");
23+
24+
tlib_pass_if_str_equal(
25+
"ini converted to env",
26+
"NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CONTEXT_DATA_INCLUDE", res);
27+
28+
nr_free(res);
29+
30+
res = nr_ini_to_env("newrelic.12345");
31+
32+
tlib_pass_if_str_equal("numerical values handled correctly",
33+
"NEW_RELIC_12345", res);
34+
35+
nr_free(res);
36+
37+
res = nr_ini_to_env("not_a_newrelic.ini_value");
38+
39+
tlib_pass_if_null("invalid ini not converted", res);
40+
41+
nr_free(res);
42+
43+
res = nr_ini_to_env("newrelic.");
44+
45+
tlib_pass_if_null("no value after prefix", res);
46+
47+
nr_free(res);
48+
49+
res = nr_ini_to_env(NULL);
50+
51+
tlib_pass_if_null("reject null values", res);
52+
53+
nr_free(res);
54+
55+
res = nr_ini_to_env("newrelic.ini__value");
56+
57+
tlib_pass_if_str_equal("double underscores handled correctly",
58+
"NEW_RELIC_INI_VALUE", res);
59+
60+
nr_free(res);
61+
62+
res = nr_ini_to_env("newrelic._option_");
63+
64+
tlib_pass_if_str_equal("dot and underscores handled correctly",
65+
"NEW_RELIC_OPTION_", res);
66+
67+
nr_free(res);
68+
}
69+
70+
tlib_parallel_info_t parallel_info
71+
= {.suggested_nthreads = -1, .state_size = 0};
72+
73+
void test_main(void* p NRUNUSED) {
74+
test_nr_ini_to_env();
75+
}

axiom/util_strings.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,25 @@ char* nr_string_to_lowercase(const char* str) {
3636
return low;
3737
}
3838

39+
char* nr_string_to_uppercase(const char* str) {
40+
int i;
41+
char* upper;
42+
43+
if (NULL == str) {
44+
return NULL;
45+
}
46+
47+
upper = nr_strdup(str);
48+
if (NULL == upper) {
49+
return NULL;
50+
}
51+
52+
for (i = 0; upper[i]; i++) {
53+
upper[i] = nr_toupper(upper[i]);
54+
}
55+
return upper;
56+
}
57+
3958
char* nr_formatf(const char* fmt, ...) {
4059
int rv;
4160
va_list ap;

axiom/util_strings.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@
3232
*/
3333
extern char* nr_string_to_lowercase(const char* str);
3434

35+
/*
36+
* Purpose : Convert a string to upper case, following USASCII rules, returning
37+
* a newly allocated string.
38+
*
39+
* Params : 1. The string to uppercase.
40+
*
41+
* Returns : The newly created string. The caller must arrange to free the
42+
* string.
43+
*/
44+
extern char* nr_string_to_uppercase(const char* str);
45+
3546
/*
3647
* Purpose : Wrap asprintf to increase convenience and safety: asprintf behavior
3748
* is not in POSIX, and the return string may not be defined in the

0 commit comments

Comments
 (0)