diff --git a/agent/php_newrelic.h b/agent/php_newrelic.h index 9683bad28..b213bf091 100644 --- a/agent/php_newrelic.h +++ b/agent/php_newrelic.h @@ -491,6 +491,16 @@ nrinibool_t span_events_enabled; /* newrelic.span_events_enabled */ nriniuint_t span_events_max_samples_stored; /* newrelic.span_events.max_samples_stored */ + +nrinistr_t dt_remote_parent_sampled; /* newrelic.distributed_tracing.sampler.remote_parent_sampled */ +nrinistr_t + dt_remote_parent_not_sampled; /* newrelic.distributed_tracing.sampler.remote_parent_not_sampled */ +/* decoding of newrelic.distributed_tracing.sampler.remote_parent_sampled and + * newrelic.distributed_tracing.sampler.remote_parent_not_sampled. + */ +nr_upstream_parent_sampling_control_t dt_sampler_parent_sampled; +nr_upstream_parent_sampling_control_t dt_sampler_parent_not_sampled; + nrinistr_t trace_observer_host; /* newrelic.infinite_tracing.trace_observer.host */ nriniuint_t diff --git a/agent/php_nrini.c b/agent/php_nrini.c index 37da5a820..540e9ffdb 100644 --- a/agent/php_nrini.c +++ b/agent/php_nrini.c @@ -1970,6 +1970,55 @@ static PHP_INI_MH(nr_wordpress_hooks_options_mh) { return SUCCESS; } +static PHP_INI_MH(nr_dt_sampler_remote_parent_mh) { + nrinistr_t* p; + + char* base = (char*)mh_arg2; + p = (nrinistr_t*)(base + (size_t)mh_arg1); + bool parent_sampled = false; + + (void)mh_arg3; + NR_UNUSED_TSRMLS; + + p->where = 0; + + if (0 == nr_strcmp(ZEND_STRING_VALUE(entry->name), + "newrelic.distributed_tracing.sampler.remote_parent_sampled")) { + parent_sampled = true; + } + + if (0 == nr_strcmp(NEW_VALUE, "default")) { + if (parent_sampled) { + NRPRG(dt_sampler_parent_sampled) = DEFAULT; + } else { + NRPRG(dt_sampler_parent_not_sampled) = DEFAULT; + } + } else if (0 == nr_strcmp(NEW_VALUE, "always_on")) { + if (parent_sampled) { + NRPRG(dt_sampler_parent_sampled) = ALWAYS_KEEP; + } else { + NRPRG(dt_sampler_parent_not_sampled) = ALWAYS_KEEP; + } + } else if (0 == nr_strcmp(NEW_VALUE, "always_off")) { + if (parent_sampled) { + NRPRG(dt_sampler_parent_sampled) = ALWAYS_DROP; + } else { + NRPRG(dt_sampler_parent_not_sampled) = ALWAYS_DROP; + } + } else { + nrl_warning(NRL_INIT, "Invalid %s value \"%s\"; using \"%s\" instead.", + ZEND_STRING_VALUE(entry->name), NEW_VALUE, + DEFAULT_WORDPRESS_HOOKS_OPTIONS); + /* This will cause PHP to call the handler again with default value */ + return FAILURE; + } + + p->where = stage; + p->value = NEW_VALUE; + + return SUCCESS; +} + /* * Now for the actual INI entry table. Please note there are two types of INI * entry specification used. @@ -2930,6 +2979,24 @@ STD_PHP_INI_ENTRY_EX("newrelic.distributed_tracing_exclude_newrelic_header", newrelic_globals, 0) + +STD_PHP_INI_ENTRY_EX("newrelic.distributed_tracing.sampler.remote_parent_sampled", + "default", + NR_PHP_REQUEST, + nr_dt_sampler_remote_parent_mh, + dt_remote_parent_sampled, + zend_newrelic_globals, + newrelic_globals, + 0) +STD_PHP_INI_ENTRY_EX("newrelic.distributed_tracing.sampler.remote_parent_not_sampled", + "default", + NR_PHP_REQUEST, + nr_dt_sampler_remote_parent_mh, + dt_remote_parent_not_sampled, + zend_newrelic_globals, + newrelic_globals, + 0) + /* * This setting is not documented and affects the length of the interally used * trace id. This INI setting should not be modified unless requested by diff --git a/agent/php_txn.c b/agent/php_txn.c index 800cfb7f2..5a9e5bc21 100644 --- a/agent/php_txn.c +++ b/agent/php_txn.c @@ -942,6 +942,10 @@ nr_status_t nr_php_txn_begin(const char* appnames, = is_cli ? NRINI(tt_max_segments_cli) : NRINI(tt_max_segments_web); opts.span_queue_batch_size = NRINI(agent_span_queue_size); opts.span_queue_batch_timeout = NRINI(agent_span_queue_timeout); + opts.dt_sampler_parent_sampled + = NRPRG(dt_sampler_parent_sampled); + opts.dt_sampler_parent_not_sampled + = NRPRG(dt_sampler_parent_not_sampled); opts.logging_enabled = NRINI(logging_enabled); opts.log_decorating_enabled = NRINI(log_decorating_enabled); opts.log_forwarding_enabled = NRINI(log_forwarding_enabled); diff --git a/agent/scripts/newrelic.ini.template b/agent/scripts/newrelic.ini.template index 4c199f00b..ce752f1d4 100644 --- a/agent/scripts/newrelic.ini.template +++ b/agent/scripts/newrelic.ini.template @@ -911,6 +911,36 @@ newrelic.daemon.logfile = "/var/log/newrelic/newrelic-daemon.log" ; ;newrelic.distributed_tracing_exclude_newrelic_header = false +; Setting: newrelic.distributed_tracing.sampler.remote_parent_sampled +; Type : string +; Scope : per-directory +; Default: "default" +; Info : This option defines how the agent should handle sampling spans when +; their parent span from an upstream entity was sampled. For example, +; setting remote_parent_sampled: always_on means the agent will sample +; anything if the upstream entity sampled the parent. +; The possible values are: +; - "default": Use New Relic's standard sampling rules. +; - "always_on": Always sample spans whose upstream parent was not sampled. +; - "always_off": Always skip sampling spans whose upstream parent was not sampled. +; +;newrelic.distributed_tracing.sampler.remote_parent_sampled = "default" + +; Setting: newrelic.distributed_tracing.sampler.remote_parent_not_sampled +; Type : string +; Scope : per-directory +; Default: "default" +; Info : This option defines how the agent should handle sampling spans when +; their parent span from an upstream entity was not sampled. For example, +; setting remote_parent_not_sampled: always_off means the agent will not +; try to sample anything if the upstream entity did not sample the parent. +; The possible values are: +; - "default": Use New Relic's standard sampling rules. +; - "always_on": Always sample spans whose upstream parent was not sampled. +; - "always_off": Always skip sampling spans whose upstream parent was not sampled. +; +;newrelic.distributed_tracing.sampler.remote_parent_sampled = "default" + ; Setting: newrelic.span_events_enabled ; Type : boolean ; Scope : per-directory diff --git a/axiom/nr_distributed_trace.c b/axiom/nr_distributed_trace.c index 25fcd27d5..9da90fb53 100644 --- a/axiom/nr_distributed_trace.c +++ b/axiom/nr_distributed_trace.c @@ -1298,3 +1298,43 @@ char* nr_distributed_trace_create_w3c_traceparent_header(const char* trace_id, return trace_parent_header; } + +void nr_distributed_trace_handle_inbound_w3c_sampled_flag( + nr_distributed_trace_t* dt, + const nrobj_t* trace_headers, + nr_upstream_parent_sampling_control_t remote_parent_sampled, + nr_upstream_parent_sampling_control_t remote_parent_not_sampled) { + const nrobj_t* traceparent = NULL; + int sampled = 0; + nr_status_t parse_err = NR_FAILURE; + if (DEFAULT != remote_parent_sampled || DEFAULT != remote_parent_not_sampled) { + traceparent = nro_get_hash_value(trace_headers, "traceparent", &parse_err); + if (nrunlikely(NULL == traceparent || NR_SUCCESS != parse_err)) { + return; + } + sampled = nro_get_hash_int(traceparent, "trace_flags", &parse_err); + if (nrunlikely(NR_SUCCESS != parse_err)) { + return; + } + /* The final bit of the trace_flags indicates the sampling decision */ + if (sampled & 0x01) { + if (DEFAULT != remote_parent_sampled) { + if (ALWAYS_KEEP == remote_parent_sampled) { + dt->sampled = true; + dt->priority = 2; + } else { + dt->sampled = false; + } + } + } else { + if (DEFAULT != remote_parent_not_sampled) { + if (ALWAYS_DROP == remote_parent_not_sampled) { + dt->sampled = false; + } else { + dt->sampled = true; + dt->priority = 2; + } + } + } + } +} diff --git a/axiom/nr_distributed_trace.h b/axiom/nr_distributed_trace.h index f59d7ae24..2b2e5b45e 100644 --- a/axiom/nr_distributed_trace.h +++ b/axiom/nr_distributed_trace.h @@ -60,6 +60,16 @@ static const char NR_DISTRIBUTED_TRACE_W3C_TRACECONTEXT_ACCEPT_EXCEPTION[] typedef struct _nr_distributed_trace_t nr_distributed_trace_t; typedef struct _nr_distributed_trace_payload_t nr_distributed_trace_payload_t; +/* + * Control options for how to respect other-vendor upstream sampling + * decisions. + */ +typedef enum { + DEFAULT, + ALWAYS_KEEP, + ALWAYS_DROP +} nr_upstream_parent_sampling_control_t; + /* * Purpose : Creates/allocates a new distributed tracing metadata struct * instance. It's the responsibility of the caller to @@ -409,4 +419,18 @@ bool nr_distributed_trace_accept_inbound_w3c_payload( const char* transport_type, const char** error); +/* + * Purpose : Handle upstream w3c sampled flag according to settings + * + * Params : 1. The distributed trace object + * 2. W3C trace headers objet + * 3. Setting for if the upstream trace is sampled + * 4. Setting for if the upstream trace is not sampled + */ +void nr_distributed_trace_handle_inbound_w3c_sampled_flag( + nr_distributed_trace_t* dt, + const nrobj_t* trace_headers, + nr_upstream_parent_sampling_control_t remote_parent_sampled, + nr_upstream_parent_sampling_control_t remote_parent_not_sampled); + #endif /* NR_DISTRIBUTED_TRACE_HDR */ diff --git a/axiom/nr_txn.c b/axiom/nr_txn.c index 60e1ea5ee..744f9e077 100644 --- a/axiom/nr_txn.c +++ b/axiom/nr_txn.c @@ -2972,6 +2972,14 @@ static bool nr_txn_accept_w3c_trace_context_headers( nr_distributed_trace_accept_inbound_w3c_payload( txn->distributed_trace, trace_headers, transport_type, &error_metrics); + /* Depending on the user's INI settings, we may or may not want to + * consider the traceparent's sampled field */ + nr_distributed_trace_handle_inbound_w3c_sampled_flag( + txn->distributed_trace, + trace_headers, + txn->options.dt_sampler_parent_sampled, + txn->options.dt_sampler_parent_not_sampled); + if (error_metrics) { nr_txn_force_single_count(txn, error_metrics); } diff --git a/axiom/nr_txn.h b/axiom/nr_txn.h index 9a29fd878..2a1f3a569 100644 --- a/axiom/nr_txn.h +++ b/axiom/nr_txn.h @@ -100,6 +100,14 @@ typedef struct _nrtxnopt_t { headers in favor of only W3C trace context headers */ + nr_upstream_parent_sampling_control_t + dt_sampler_parent_sampled; /* how to sample spans when non- + New Relic upstream did sample. + */ + nr_upstream_parent_sampling_control_t + dt_sampler_parent_not_sampled; /* how to sample spans when non- + New Relic upstream didn't sample. + */ int span_events_enabled; /* Whether span events are enabled */ size_t span_events_max_samples_stored; /* The maximum number of span events per diff --git a/axiom/tests/test_txn.c b/axiom/tests/test_txn.c index 493213206..ab2c999ff 100644 --- a/axiom/tests/test_txn.c +++ b/axiom/tests/test_txn.c @@ -6299,6 +6299,181 @@ static void test_txn_accept_distributed_trace_payload_metrics(void) { nrm_table_destroy(&txn.unscoped_metrics); } +static void test_txn_accept_distributed_trace_payload_w3c_sample_flags(void) { + nrtxn_t txn = {0}; + nr_hashmap_t* headers; + bool rv = true; + char* TRACEPARENT_SAMPLED = "00-87b1c9a429205b25e5b687d890d4821f-7d3efb1b173fecfa-01"; + char* TRACEPARENT_NOT_SAMPLED = "00-87b1c9a429205b25e5b687d890d4821f-7d3efb1b173fecfa-00"; + char* TRACESTATE_SAMPLED = "123@nr=0-2-account-app-span-transaction-1-1.1273-1529445826000"; + char* TRACESTATE_NOT_SAMPLED = "123@nr=0-2-account-app-span-transaction-0-1.1273-1529445826000"; + nrtime_t payload_timestamp_ms = 1529445826000; + nrtime_t txn_timestamp_us = 15214458260000 * NR_TIME_DIVISOR_MS; + nrtime_t delta_timestamp_us = nr_time_duration( + (payload_timestamp_ms * NR_TIME_DIVISOR_MS), txn_timestamp_us); + + tlib_fail_if_int64_t_equal("Zero duration", 0, delta_timestamp_us); + + nr_memset(&txn, 0, sizeof(nrtxn_t)); + txn.app_connect_reply = nro_new_hash(); + txn.unscoped_metrics = nrm_table_create(0); + nro_set_hash_string(txn.app_connect_reply, "trusted_account_key", "123"); + // default value for padding can be used for this test, because other + // test (test_distributed_trace_create_trace_parent_header) already + // covers using trace_id of different lengths when w3c header is created. + txn.options.distributed_tracing_pad_trace_id = false; + txn.options.distributed_tracing_enabled = true; + +#define TEST_TXN_ACCEPT_DT_PAYLOAD_RESET \ + txn.distributed_trace->inbound.set = 0; \ + nrm_table_destroy(&txn.unscoped_metrics); \ + txn.unscoped_metrics = nrm_table_create(0); \ + txn.options.dt_sampler_parent_not_sampled = DEFAULT; \ + txn.options.dt_sampler_parent_sampled = DEFAULT; + + headers = nr_hashmap_create(NULL); + + /* + * Test : DT traceparent sampled flag INI settings + */ + // 1: upstream not sampled, agent discard + txn.options.dt_sampler_parent_not_sampled = ALWAYS_DROP; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_NOT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_false("Sampled should be set to false", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_true("Priority should not be overwritten", + 2.0 != txn.distributed_trace->priority, + "priority is 2.0"); + + // 2: upstream not sampled, agent keep + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_not_sampled = ALWAYS_KEEP; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_NOT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_NOT_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_true("Sampled should be set to true", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_double_equal("Priority should be set to max", 2.0, + txn.distributed_trace->priority); + + // 3: upstream not sampled, agent default (keep) + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_not_sampled = DEFAULT; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_NOT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_true("Sampled should be set to true", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_true("Priority should not be overwritten", + 2.0 != txn.distributed_trace->priority, + "priority is 2.0"); + + // 4: upstream not sampled, agent default (toss) + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_not_sampled = DEFAULT; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_NOT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_NOT_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_false("Sampled should be set to false", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_true("Priority should not be overwritten", + 2.0 != txn.distributed_trace->priority, + "priority is 2.0"); + + // 5: upstream sampled, agent discard + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_sampled = ALWAYS_DROP; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_false("Sampled should be set to false", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_true("Priority should not be overwritten", + 2.0 != txn.distributed_trace->priority, + "priority is 2.0"); + + // 6: upstream sampled, agent keep + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_sampled = ALWAYS_KEEP; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_NOT_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_true("Sampled should be set to true", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_double_equal("Priority should be set to max", 2.0, + txn.distributed_trace->priority); + + // 7: upstream sampled, agent default (keep) + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_sampled = DEFAULT; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_true("Sampled should be set to true", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_true("Priority should not be overwritten", + 2.0 != txn.distributed_trace->priority, + "priority is 2.0"); + + // 8: upstream sampled, agent default (toss) + TEST_TXN_ACCEPT_DT_PAYLOAD_RESET + txn.options.dt_sampler_parent_sampled = DEFAULT; + nr_distributed_trace_destroy(&txn.distributed_trace); + txn.distributed_trace = nr_distributed_trace_create(); + nr_hashmap_update(headers, NR_PSTR("traceparent"), TRACEPARENT_SAMPLED); + nr_hashmap_update(headers, NR_PSTR("tracestate"), TRACESTATE_NOT_SAMPLED); + rv = nr_txn_accept_distributed_trace_payload(&txn, headers, "HTTP"); + tlib_pass_if_true("The header should be accepted", rv, "Return value = %d", + (int)rv); + tlib_pass_if_false("Sampled should be set to false", + txn.distributed_trace->sampled, "sampled flag = %d", + (int)txn.distributed_trace->sampled); + tlib_pass_if_true("Priority should not be overwritten", + 2.0 != txn.distributed_trace->priority, + "priority is 2.0"); + + nr_txn_destroy_fields(&txn); + nr_hashmap_destroy(&headers); +#undef TEST_TXN_ACCEPT_DT_PAYLOAD_RESET +} + static void test_txn_accept_distributed_trace_payload_w3c(void) { nrtxn_t txn = {0}; nr_hashmap_t* headers; @@ -6780,6 +6955,7 @@ static void test_txn_accept_distributed_trace_payload_w3c(void) { nr_txn_destroy_fields(&txn); nr_hashmap_destroy(&headers); +#undef TEST_TXN_ACCEPT_DT_PAYLOAD_RESET } static void test_txn_accept_distributed_trace_payload_w3c_and_nr(void) { @@ -8912,6 +9088,7 @@ void test_main(void* p NRUNUSED) { test_create_w3c_traceparent_header(); test_create_w3c_tracestate_header(); test_txn_accept_distributed_trace_payload_w3c(); + test_txn_accept_distributed_trace_payload_w3c_sample_flags(); test_txn_accept_distributed_trace_payload_w3c_and_nr(); test_span_queue(); test_segment_record_error(); diff --git a/tests/integration/distributed_tracing/w3c/test_force_keep_headers_not_sampled.php b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_not_sampled.php new file mode 100644 index 000000000..073195757 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_not_sampled.php @@ -0,0 +1,76 @@ + "00-74be672b84ddc4e4b28be285632bbc0a-27ddd2d8890283b4-00", + 'tracestate' => "123@nr=0-0-1349956-41346604-27ddd2d8890283b4-b28be285632bbc0a-0-1.1273-1569367663277" +); + +newrelic_accept_distributed_trace_headers($payload); + +$outbound_headers = array('Accept-Language' => 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '01', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '1', 'tracestate sampled flag ok'); +tap_equal($tracestate[7], '2.000000', 'tracestate priority ok'); diff --git a/tests/integration/distributed_tracing/w3c/test_force_keep_headers_not_sampled_non_newrelic.php b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_not_sampled_non_newrelic.php new file mode 100644 index 000000000..f70d0ec10 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_not_sampled_non_newrelic.php @@ -0,0 +1,84 @@ + 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '01', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '1', 'tracestate sampled flag ok'); +tap_equal($tracestate[7], '2.000000', 'tracestate priority ok'); diff --git a/tests/integration/distributed_tracing/w3c/test_force_keep_headers_sampled.php b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_sampled.php new file mode 100644 index 000000000..9ca578f80 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_sampled.php @@ -0,0 +1,78 @@ + "00-74be672b84ddc4e4b28be285632bbc0a-27ddd2d8890283b4-01", + 'tracestate' => "123@nr=0-0-1349956-41346604-27ddd2d8890283b4-b28be285632bbc0a-0-1.1273-1569367663277" +); + +newrelic_accept_distributed_trace_headers($payload); + +$outbound_headers = array('Accept-Language' => 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '01', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '1', 'tracestate sampled flag ok'); +tap_equal($tracestate[7], '2.000000', 'tracestate priority ok'); + diff --git a/tests/integration/distributed_tracing/w3c/test_force_keep_headers_sampled_non_newrelic.php b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_sampled_non_newrelic.php new file mode 100644 index 000000000..a5057abd5 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_keep_headers_sampled_non_newrelic.php @@ -0,0 +1,84 @@ + 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '01', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '1', 'tracestate sampled flag ok'); +tap_equal($tracestate[7], '2.000000', 'tracestate priority ok'); diff --git a/tests/integration/distributed_tracing/w3c/test_force_toss_headers_not_sampled.php b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_not_sampled.php new file mode 100644 index 000000000..7506e964d --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_not_sampled.php @@ -0,0 +1,47 @@ + "00-74be672b84ddc4e4b28be285632bbc0a-27ddd2d8890283b4-00", + 'tracestate' => "123@nr=0-0-1349956-41346604-27ddd2d8890283b4-b28be285632bbc0a-1-1.1273-1569367663277" +); + +newrelic_accept_distributed_trace_headers($payload); + +$outbound_headers = array('Accept-Language' => 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '00', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '0', 'tracestate sampled flag ok'); +tap_not_equal($tracestate[7], '2.000000', 'tracestate priority ok'); diff --git a/tests/integration/distributed_tracing/w3c/test_force_toss_headers_not_sampled_non_newrelic.php b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_not_sampled_non_newrelic.php new file mode 100644 index 000000000..5f591c647 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_not_sampled_non_newrelic.php @@ -0,0 +1,46 @@ + 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '00', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '0', 'tracestate sampled flag ok'); +tap_not_equal($tracestate[7], '2.000000', 'tracestate priority ok'); diff --git a/tests/integration/distributed_tracing/w3c/test_force_toss_headers_sampled.php b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_sampled.php new file mode 100644 index 000000000..e77487fe5 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_sampled.php @@ -0,0 +1,46 @@ + "00-74be672b84ddc4e4b28be285632bbc0a-27ddd2d8890283b4-01", + 'tracestate' => "123@nr=0-0-1349956-41346604-27ddd2d8890283b4-b28be285632bbc0a-1-1.1273-1569367663277" +); + +newrelic_accept_distributed_trace_headers($payload); + +$outbound_headers = array('Accept-Language' => 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '00', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '0', 'tracestate sampled flag ok'); +tap_not_equal($tracestate[7], '2.000000', 'tracestate priority ok'); diff --git a/tests/integration/distributed_tracing/w3c/test_force_toss_headers_sampled_non_newrelic.php b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_sampled_non_newrelic.php new file mode 100644 index 000000000..eaf95b690 --- /dev/null +++ b/tests/integration/distributed_tracing/w3c/test_force_toss_headers_sampled_non_newrelic.php @@ -0,0 +1,46 @@ + 'en-US,en;q=0.5'); +tap_assert(newrelic_insert_distributed_trace_headers($outbound_headers), 'insert function succeeded'); +$traceparent = explode('-', $outbound_headers['traceparent']); +$tracestate = explode('-', explode('=', $outbound_headers['tracestate'])[1]); + +tap_equal($traceparent[3], '00', 'traceparent sampled flag ok'); +tap_equal($tracestate[6], '0', 'tracestate sampled flag ok'); +tap_not_equal($tracestate[7], '2.000000', 'tracestate priority ok');