Skip to content

Commit

Permalink
Merge pull request #479 from newrelic/dev
Browse files Browse the repository at this point in the history
Release 10.0.0
  • Loading branch information
ZNeumann committed Jun 28, 2022
2 parents 96828fa + 6609646 commit 9fd43b5
Show file tree
Hide file tree
Showing 72 changed files with 2,518 additions and 589 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,9 @@ package-clean:
.PHONY: lasp-test
lasp-test: daemon
if [ ! $(SUITE_LASP) ]; then echo "USAGE: make lasp-test SUITE_LASP=suite-most-secure"; exit 1; fi
if [ "$(LICENSE_lasp_$(subst -,_,$(SUITE_LASP)))" = "" ] ; then echo "Missing license for $(SUITE_LASP)"; exit 1; fi
@if [ "$(LICENSE_lasp_$(subst -,_,$(SUITE_LASP)))" = "" ] ; then echo "Missing license for $(SUITE_LASP)"; exit 1; fi
if [ ! -d "tests/lasp/$(SUITE_LASP)" ]; then echo "No such suite in tests/lasp folder"; exit 1; fi
for PHP in $${PHPS:-8.1 8.0 7.4 7.3 7.2 7.1 7.0 5.6 5.5}; do \
@for PHP in $${PHPS:-8.1 8.0 7.4 7.3 7.2 7.1 7.0 5.6 5.5}; do \
echo; echo "# PHP=$${PHP}"; \
NRLAMP_PHP=$${PHP} bin/integration_runner $(INTEGRATION_ARGS) -loglevel debug \
-license $(LICENSE_lasp_$(subst -,_,$(SUITE_LASP))) \
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.21.0
10.0.0
129 changes: 129 additions & 0 deletions agent/php_environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,134 @@ static void nr_php_gather_dispatcher_information(nrobj_t* env) {

nro_set_hash_string(env, "Dispatcher", dstring);
}
void nr_php_process_environment_variable_to_nrobj(const char* prefix,
const char* key,
const char* value,
nrobj_t* kv_hash) {
if ((NULL == prefix) || (NULL == kv_hash) || (NULL == key)) {
return;
}

if (nr_strlen(prefix) >= nr_strlen(key)) {
return;
}

if (0 == nr_strncmp(key, prefix, nr_strlen(prefix))) {
nro_set_hash_string(kv_hash, key, value);
}
}

char* nr_php_process_environment_variable_to_string(const char* prefix,
const char* key,
const char* value,
char* kv_string,
const char* kv_delimiter,
const char* delimiter) {
if ((NULL == prefix) || (NULL == key)) {
return kv_string;
}

if (nr_strlen(prefix) >= nr_strlen(key)) {
return kv_string;
}

if (0 == nr_strncmp(key, prefix, nr_strlen(prefix))) {
kv_string = nr_str_append(kv_string, key + nr_strlen(prefix), delimiter);
kv_string = nr_str_append(kv_string, value, kv_delimiter);
}
return kv_string;
}

/*
* Current variables we scan are:
* 1. Variables with the key prefix NEW_RELIC_METADATA_
* 2. Variables with the key prefix NEW_RELIC_LABEL_
* 3. Variable with the key NEW_RELIC_LABELS
*/
static void nr_php_get_environment_variables(TSRMLS_D) {
nrobj_t* parsed_key_val = NULL;
const char* plural_label = NULL;

/*
* `environ` works for non-windows machines.
* Otherwise, we'd need to use *__p__environ() as well.
*/
extern char** environ;

/*
* Initialize the metadata hash. If there aren't any variables, we still need
* to send the empty hash.
*/
NR_PHP_PROCESS_GLOBALS(metadata) = nro_new_hash();

/* Initialize the environment labels string to collect labels.
* If labels are specified in both the agent configuration file and the
* NEW_RELIC_LABELS environment variable or prefixed with the NEW_RELIC_LABEL_
* key prefix, the agent MUST use existing configuration precedence rules to
* determine which set of labels to send to New Relic. Configuration via
* environment variables always trumps file-based configuration, so if
* duplicate labels are specified in both the agent configuration file and the
* environment variable, the duplicate labels from the environment variable
* should be used. By appending the environment variables to the end of the
* ini string, we ensure the environmental variables take precedence when it
* is entered into the label hash. Additionally, with the environmental and
* ini values combined, we are able to take advantage of all the previous
* label structures, tests, and string validation when `nr_php_txn_get_labels`
* puts the string in a hash.
*/
NR_PHP_PROCESS_GLOBALS(env_labels)
= nr_str_append(NR_PHP_PROCESS_GLOBALS(env_labels), NRINI(labels), ";");

/*
* Search environment for the specific keys (not a prefix) that NR supports.
*/

/*
* Plural labels key.
*/
plural_label = getenv(NR_LABELS_PLURAL_KEY);
if (!nr_strempty(plural_label)) {
NR_PHP_PROCESS_GLOBALS(env_labels)
= nr_str_append(NR_PHP_PROCESS_GLOBALS(env_labels), plural_label, ";");
}

/*
* Get the environment to parse the variables for that have prefixes we are
* interested in. If we are unable to get the environment don't try to parse
* it.
*/
if (NULL == environ) {
nrl_warning(NRL_AGENT, "%s: Unable to access environmental variables.",
__func__);
return;
}

/*
* Iterate through the environment variables, searching for a single key or
* a set of keys with a prefix that the agent will use.
*/
for (size_t i = 0; environ[i] != NULL; i++) {
parsed_key_val = nr_strsplit(environ[i], "=", 0);
if ((NULL == parsed_key_val) || (2 != nro_getsize(parsed_key_val))) {
nrl_verbosedebug(NRL_AGENT,
"%s: Skipping malformed environmental variable %s",
__func__, environ[i]);
} else {
const char* key = nro_get_array_string(parsed_key_val, 1, NULL);
const char* value = nro_get_array_string(parsed_key_val, 2, NULL);
nr_php_process_environment_variable_to_nrobj(
NR_METADATA_KEY_PREFIX, key, value, NR_PHP_PROCESS_GLOBALS(metadata));
NR_PHP_PROCESS_GLOBALS(env_labels)
= nr_php_process_environment_variable_to_string(
NR_LABELS_SINGULAR_KEY_PREFIX, key, value,
NR_PHP_PROCESS_GLOBALS(env_labels), ":", ";");
}
nro_delete(parsed_key_val);
}
nrl_verbosedebug(NRL_AGENT,
"%s: set NR_PHP_PROCESS_GLOBALS(env_labels) labels %s",
__func__, NR_PHP_PROCESS_GLOBALS(env_labels));
}

nrobj_t* nr_php_get_environment(TSRMLS_D) {
nrobj_t* env;
Expand All @@ -391,6 +519,7 @@ nrobj_t* nr_php_get_environment(TSRMLS_D) {
nr_php_gather_machine_information(env);
nr_php_gather_dynamic_modules(env TSRMLS_CC);
nr_php_gather_dispatcher_information(env);
nr_php_get_environment_variables(TSRMLS_C);

return env;
}
55 changes: 55 additions & 0 deletions agent/php_environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#ifndef PHP_ENVIRONMENT_HDR
#define PHP_ENVIRONMENT_HDR

#define NR_METADATA_KEY_PREFIX "NEW_RELIC_METADATA_"
#define NR_LABELS_PLURAL_KEY "NEW_RELIC_LABELS"
#define NR_LABELS_SINGULAR_KEY_PREFIX "NEW_RELIC_LABEL_"

/*
* Purpose : Produce the object that describes the invariant parts of the
* execution environment.
Expand Down Expand Up @@ -42,4 +46,55 @@ extern nrobj_t* nr_php_get_environment(TSRMLS_D);
*/
void nr_php_parse_rocket_assignment_list(char* s, size_t len, nrobj_t* kv_hash);

/*
* Purpose : Compare the given prefix to a key in a key value pair. If matched,
* add the key value pair to the given hash.
*
* The scanner looks for lines holding "=" style
* assignments:
*
* key = value
*
* This format is generally seen with system environment variable
* output.
*
* Params : 1. The prefix to scan for.
* 2. The key to compare to the prefix.
* 3. The value associated with the prefix.
* 4. The object that will have the key/value pair added to it.
*
*/
void nr_php_process_environment_variable_to_nrobj(const char* prefix,
const char* key,
const char* value,
nrobj_t* kv_hash);

/*
* Purpose : Compare the given prefix to a key in a key value pair. If matched,
* add the key value pair to the given hash.
*
* The scanner looks for lines holding "=" style
* assignments:
*
* key = value
*
* This format is generally seen with system environment variable
* output.
*
* Params : 1. The prefix to scan for.
* 2. The key to compare to the prefix.
* 3. The value associated with the prefix.
* 4. The string that will have the key/value pair added to it.
* 5. The delimiter used to separate the key and value in the string.
* 6. The delimiter used to separate key/value pairs in the string.
*
* Returns : String with matching key/value appended.
*/
char* nr_php_process_environment_variable_to_string(const char* prefix,
const char* key,
const char* value,
char* kv_hash,
const char* kv_delimeter,
const char* delimeter);

#endif /* PHP_ENVIRONMENT_HDR */
2 changes: 2 additions & 0 deletions agent/php_globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ static void nr_php_per_process_globals_dispose(void) {
nr_free(nr_php_per_process_globals.php_version);
nr_free(nr_php_per_process_globals.upgrade_license_key);
nro_delete(nr_php_per_process_globals.appenv);
nro_delete(nr_php_per_process_globals.metadata);
nr_free(nr_php_per_process_globals.env_labels);
nr_free(nr_php_per_process_globals.apache_add);

nr_memset(&nr_php_per_process_globals, 0, sizeof(nr_php_per_process_globals));
Expand Down
5 changes: 5 additions & 0 deletions agent/php_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ typedef struct _nrphpglobals_t {
mode */
int daemon_special_integration; /* Cause daemon to dump special log entries to
help integration testing. */
nrobj_t* metadata; /* P17 metadata taken from environment variables with the
* prefix `NEW_RELIC_METADATA_` */
char* env_labels; /* Labels taken from environment variables with the
* prefix `NEW_RELIC_LABEL_` and from the environment
* variable with the key `NEW_RELIC_LABELS` */
#if ZEND_MODULE_API_NO >= ZEND_8_1_X_API_NO /* PHP 8.1+ */
zend_long zend_offset; /* Zend extension offset */
zend_long
Expand Down
26 changes: 26 additions & 0 deletions agent/php_minit.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,22 @@ static char* nr_php_check_for_upgrade_license_key(void) {
return 0;
}

static nr_status_t nr_php_check_8T_DT_config(TSRMLS_D) {
/* check if infinite tracing is enabled and DT disabled */
if (!nr_strempty(NRINI(trace_observer_host))
&& !NRINI(distributed_tracing_enabled)) {
nrl_warning(
NRL_INIT,
"Infinite tracing will be DISABLED because distributed tracing is"
" disabled and infinite tracing requires distributed tracing to be "
"enabled. Please check the"
" value of 'newrelic.distributed_tracing_enabled' in the agent "
"configuration.");
return NR_FAILURE;
}
return NR_SUCCESS;
}

static char* nr_php_get_agent_specific_info(void) {
const char* php_version;
const char* zend_type;
Expand Down Expand Up @@ -553,6 +569,16 @@ PHP_MINIT_FUNCTION(newrelic) {
nr_agent_close_daemon_connection();
}

/* Do some sanity checking of configuration settings and handle accordingly */

/* If infinite tracing (8T) is enabled but distributed tracing (DT) is
* disabled this is an unworkable combination because span IDs cannot be
* assigned to segments and this causes problems in
* axiom/nr_segment.c::nr_segment_to_span_event() Output a warning about this
* config issue and also that 8T will be disabled
*/
nr_php_check_8T_DT_config(TSRMLS_C);

/*
* Save the original PHP hooks and then apply our own hooks. The agent is
* almost fully operational now. The last remaining initialization that
Expand Down
7 changes: 6 additions & 1 deletion agent/php_nrini.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ NR_PHP_UTILIZATION_MH(azure)
NR_PHP_UTILIZATION_MH(gcp)
NR_PHP_UTILIZATION_MH(pcf)
NR_PHP_UTILIZATION_MH(docker)
NR_PHP_UTILIZATION_MH(kubernetes)

static PHP_INI_MH(nr_daemon_special_curl_verbose_mh) {
int val;
Expand Down Expand Up @@ -1936,7 +1937,11 @@ PHP_INI_ENTRY_EX("newrelic.daemon.utilization.detect_docker",
NR_PHP_SYSTEM,
NR_PHP_UTILIZATION_MH_NAME(docker),
nr_enabled_disabled_dh)

PHP_INI_ENTRY_EX("newrelic.daemon.utilization.detect_kubernetes",
"1",
NR_PHP_SYSTEM,
NR_PHP_UTILIZATION_MH_NAME(kubernetes),
nr_enabled_disabled_dh)
/*
* This daemon flag is for internal development use only. It should not be
* documented to customers.
Expand Down
48 changes: 35 additions & 13 deletions agent/php_txn.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,15 +511,15 @@ static nr_attribute_config_t* nr_php_create_attribute_config(TSRMLS_D) {
return config;
}

static nrobj_t* nr_php_txn_get_labels(TSRMLS_D) {
const char* input;

static nrobj_t* nr_php_txn_get_labels() {
/*
* Specifying labels via an environment variable is not supported.
* By appending the environment variables to the end of the ini string, we
* ensure the environmental variables take precedence when it is entered into
* the label hash. Additionally, with the environmental and ini values
* combined, we are able to take advantage of all the previous label
* structures, tests, and string validation.
*/
input = NRINI(labels);

return nr_labels_parse(input);
return nr_labels_parse(NR_PHP_PROCESS_GLOBALS(env_labels));
}

static void nr_php_txn_prepared_statement_destroy(void* sql) {
Expand Down Expand Up @@ -605,6 +605,25 @@ nrobj_t* nr_php_txn_get_supported_security_policy_settings(nrtxnopt_t* opts) {
return supported_policy_settings;
}

#define NR_APP_ERROR_DT_ON_TT_OFF_BACKOFF_SECONDS 60

static void nr_php_txn_log_error_dt_on_tt_off(void) {
static unsigned n_occur = 0;
static time_t last_warn = (time_t)(0);
time_t now = time(0);

n_occur++;

if ((now - last_warn) > NR_APP_ERROR_DT_ON_TT_OFF_BACKOFF_SECONDS) {
last_warn = now;
nrl_error(NRL_INIT,
"newrelic.transaction_tracer.enabled must be enabled in order "
"to use distributed tracing. Occurred %u times.",
n_occur);
n_occur = 0;
}
}

nr_status_t nr_php_txn_begin(const char* appnames,
const char* license TSRMLS_DC) {
nrtxnopt_t opts;
Expand Down Expand Up @@ -708,7 +727,8 @@ nr_status_t nr_php_txn_begin(const char* appnames,
info.license = nr_strdup(lic_to_use);
info.settings = NULL; /* Populated through callback. */
info.environment = nro_copy(NR_PHP_PROCESS_GLOBALS(appenv));
info.labels = nr_php_txn_get_labels(TSRMLS_C);
info.metadata = nro_copy(NR_PHP_PROCESS_GLOBALS(metadata));
info.labels = nr_php_txn_get_labels();
info.host_display_name = nr_strdup(NRINI(process_host_display_name));
info.lang = nr_strdup("php");
info.version = nr_strdup(nr_version());
Expand All @@ -717,11 +737,15 @@ nr_status_t nr_php_txn_begin(const char* appnames,
info.security_policies_token = nr_strdup(NRINI(security_policies_token));
info.supported_security_policies
= nr_php_txn_get_supported_security_policy_settings(&opts);
info.trace_observer_host = nr_strdup(NRINI(trace_observer_host));
/* if DT is disabled we cannot stream 8T events so disable observer host */
if (NRINI(distributed_tracing_enabled))
info.trace_observer_host = nr_strdup(NRINI(trace_observer_host));
else
info.trace_observer_host = nr_strdup("");
/* observer port setting does not really depend on DT being enabled */
info.trace_observer_port = NRINI(trace_observer_port);
info.span_queue_size = NRINI(span_queue_size);
info.span_events_max_samples_stored = NRINI(span_events_max_samples_stored);

NRPRG(app) = nr_agent_find_or_add_app(
nr_agent_applist, &info,
/*
Expand Down Expand Up @@ -843,9 +867,7 @@ nr_status_t nr_php_txn_begin(const char* appnames,

if (NRPRG(txn)->options.distributed_tracing_enabled
&& !NRPRG(txn)->options.tt_enabled) {
nrl_error(NRL_INIT,
"newrelic.transaction_tracer.enabled must be enabled in order "
"to use distributed tracing");
nr_php_txn_log_error_dt_on_tt_off();
}

#if ZEND_MODULE_API_NO >= ZEND_8_1_X_API_NO
Expand Down
Loading

0 comments on commit 9fd43b5

Please sign in to comment.