@@ -1815,5 +1815,135 @@ SENTRY_TEST(propagation_context_init)
18151815 sentry_close ();
18161816}
18171817
1818+ typedef struct {
1819+ int sentry_trace_found ;
1820+ int traceparent_found ;
1821+ char sentry_trace_value [64 ];
1822+ char traceparent_value [64 ];
1823+ } traceparent_header_collector_t ;
1824+
1825+ static void
1826+ collect_traceparent_headers (const char * key , const char * value , void * userdata )
1827+ {
1828+ traceparent_header_collector_t * collector
1829+ = (traceparent_header_collector_t * )userdata ;
1830+ if (strcmp (key , "sentry-trace" ) == 0 ) {
1831+ collector -> sentry_trace_found = 1 ;
1832+ const size_t value_len = sizeof (collector -> sentry_trace_value ) - 1 ;
1833+ strncpy (collector -> sentry_trace_value , value , value_len );
1834+ collector -> sentry_trace_value [value_len ] = '\0' ;
1835+ } else if (strcmp (key , "traceparent" ) == 0 ) {
1836+ collector -> traceparent_found = 1 ;
1837+ const size_t value_len = sizeof (collector -> traceparent_value ) - 1 ;
1838+ strncpy (collector -> traceparent_value , value , value_len );
1839+ collector -> traceparent_value [value_len ] = '\0' ;
1840+ }
1841+ }
1842+
1843+ SENTRY_TEST (traceparent_header_disabled_by_default )
1844+ {
1845+ SENTRY_TEST_OPTIONS_NEW (options );
1846+ sentry_options_set_dsn (
options ,
"https://[email protected] /42" );
1847+ sentry_options_set_traces_sample_rate (options , 1.0 );
1848+ // Note: not enabling traceparent propagation
1849+ sentry_init (options );
1850+
1851+ sentry_transaction_context_t * tx_ctx
1852+ = sentry_transaction_context_new ("test" , "test" );
1853+ sentry_transaction_t * tx
1854+ = sentry_transaction_start (tx_ctx , sentry_value_new_null ());
1855+
1856+ traceparent_header_collector_t collector = { 0 };
1857+ sentry_transaction_iter_headers (
1858+ tx , collect_traceparent_headers , & collector );
1859+
1860+ // Should have sentry-trace but not traceparent
1861+ TEST_CHECK (collector .sentry_trace_found );
1862+ TEST_CHECK (!collector .traceparent_found );
1863+
1864+ TEST_CHECK_INT_EQUAL (
1865+ strlen (collector .sentry_trace_value ), SENTRY_TRACE_LEN );
1866+
1867+ sentry_transaction_finish (tx );
1868+ sentry_close ();
1869+ }
1870+
1871+ SENTRY_TEST (traceparent_header_generation )
1872+ {
1873+ SENTRY_TEST_OPTIONS_NEW (options );
1874+ sentry_options_set_dsn (
options ,
"https://[email protected] /42" );
1875+ sentry_options_set_traces_sample_rate (options , 1.0 );
1876+ sentry_options_set_propagate_traceparent (options , 1 );
1877+ sentry_init (options );
1878+
1879+ sentry_transaction_context_t * tx_ctx
1880+ = sentry_transaction_context_new ("test" , "test" );
1881+ sentry_transaction_t * tx
1882+ = sentry_transaction_start (tx_ctx , sentry_value_new_null ());
1883+
1884+ // Test transaction header generation
1885+ traceparent_header_collector_t collector = { 0 };
1886+ sentry_transaction_iter_headers (
1887+ tx , collect_traceparent_headers , & collector );
1888+
1889+ // Should have both headers
1890+ TEST_CHECK (collector .sentry_trace_found );
1891+ TEST_CHECK (collector .traceparent_found );
1892+
1893+ // Verify expected traceparent length
1894+ TEST_CHECK_INT_EQUAL (
1895+ strlen (collector .traceparent_value ), SENTRY_W3C_TRACEPARENT_LEN );
1896+ // Verify traceparent format: starts with "00-"
1897+ TEST_CHECK (strncmp (collector .traceparent_value , "00-" , 3 ) == 0 );
1898+
1899+ // Extract components from both headers to verify consistency
1900+ const char * trace_id = sentry_value_as_string (
1901+ sentry_value_get_by_key (tx -> inner , "trace_id" ));
1902+ const char * tx_span_id
1903+ = sentry_value_as_string (sentry_value_get_by_key (tx -> inner , "span_id" ));
1904+
1905+ // Verify sentry-trace contains the correct trace and span IDs
1906+ TEST_CHECK (strstr (collector .sentry_trace_value , trace_id ) != NULL );
1907+ TEST_CHECK (strstr (collector .sentry_trace_value , tx_span_id ) != NULL );
1908+
1909+ // Verify traceparent contains the correct trace and span IDs
1910+ TEST_CHECK (strstr (collector .traceparent_value , trace_id ) != NULL );
1911+ TEST_CHECK (strstr (collector .traceparent_value , tx_span_id ) != NULL );
1912+
1913+ // Test span header generation
1914+ sentry_span_t * span
1915+ = sentry_transaction_start_child (tx , "child" , "child-span" );
1916+
1917+ traceparent_header_collector_t span_collector = { 0 };
1918+ sentry_span_iter_headers (
1919+ span , collect_traceparent_headers , & span_collector );
1920+
1921+ // Should have both headers for spans too
1922+ TEST_CHECK (span_collector .sentry_trace_found );
1923+ TEST_CHECK (span_collector .traceparent_found );
1924+
1925+ // Verify traceparent format for spans
1926+ TEST_CHECK (strncmp (span_collector .traceparent_value , "00-" , 3 ) == 0 );
1927+
1928+ // Extract components from both headers to verify consistency
1929+ const char * span_trace_id = sentry_value_as_string (
1930+ sentry_value_get_by_key (span -> inner , "trace_id" ));
1931+ const char * span_id = sentry_value_as_string (
1932+ sentry_value_get_by_key (span -> inner , "span_id" ));
1933+
1934+ // Verify sentry-trace contains the correct trace and span IDs
1935+ TEST_CHECK (
1936+ strstr (span_collector .sentry_trace_value , span_trace_id ) != NULL );
1937+ TEST_CHECK (strstr (span_collector .sentry_trace_value , span_id ) != NULL );
1938+
1939+ // Verify traceparent contains the correct trace and span IDs
1940+ TEST_CHECK (strstr (span_collector .traceparent_value , span_trace_id ) != NULL );
1941+ TEST_CHECK (strstr (span_collector .traceparent_value , span_id ) != NULL );
1942+
1943+ sentry_span_finish (span );
1944+ sentry_transaction_finish (tx );
1945+ sentry_close ();
1946+ }
1947+
18181948#undef IS_NULL
18191949#undef CHECK_STRING_PROPERTY
0 commit comments