@@ -30,10 +30,30 @@ type JaegerServicesResponse struct {
3030 Errors []any `json:"errors"`
3131}
3232
33+ // JaegerTrace represents a single trace from Jaeger
34+ type JaegerTrace struct {
35+ TraceID string `json:"traceID"`
36+ Spans []JaegerSpan `json:"spans"`
37+ Processes map [string ]JaegerProcess `json:"processes"`
38+ }
39+
40+ // JaegerSpan represents a span within a trace
41+ type JaegerSpan struct {
42+ TraceID string `json:"traceID"`
43+ SpanID string `json:"spanID"`
44+ OperationName string `json:"operationName"`
45+ ProcessID string `json:"processID"`
46+ }
47+
48+ // JaegerProcess represents a process (service) in the trace
49+ type JaegerProcess struct {
50+ ServiceName string `json:"serviceName"`
51+ }
52+
3353// JaegerTracesResponse represents the response from Jaeger's /api/traces endpoint
3454type JaegerTracesResponse struct {
35- Data []any `json:"data"`
36- Errors []any `json:"errors"`
55+ Data []JaegerTrace `json:"data"`
56+ Errors []any `json:"errors"`
3757}
3858
3959func TestMain (m * testing.M ) {
@@ -139,3 +159,101 @@ func TestJaeger2TracesHaveSpans(t *testing.T) {
139159 t .Logf ("Found %d traces for service alpha1 in Jaeger 2.x" , len (traces .Data ))
140160 require .NotEmpty (t , traces .Data , "Should have traces for alpha1 service in Jaeger 2.x" )
141161}
162+
163+ // TestCrossServiceTraceContext verifies that traces propagate correctly between alpha and zero.
164+ // A mutation triggers alpha->zero communication (for timestamps/commit), and both services
165+ // should appear in the same trace with the same trace ID.
166+ func TestCrossServiceTraceContext (t * testing.T ) {
167+ jaegerAddr := testutil .ContainerAddr ("jaeger" , 16686 )
168+ alphaAddr := testutil .ContainerAddr ("alpha1" , 9080 )
169+
170+ dg , err := testutil .DgraphClient (alphaAddr )
171+ require .NoError (t , err )
172+
173+ ctx , cancel := context .WithTimeout (context .Background (), 60 * time .Second )
174+ defer cancel ()
175+
176+ // Run a mutation - this triggers alpha->zero communication for timestamps and commit
177+ _ , err = dg .NewTxn ().Mutate (ctx , & api.Mutation {
178+ SetNquads : []byte (`_:cross <name> "cross-service-trace-test-v2" .` ),
179+ CommitNow : true ,
180+ })
181+ require .NoError (t , err )
182+
183+ // Give Jaeger time to process traces
184+ time .Sleep (5 * time .Second )
185+
186+ // Verify both services are registered
187+ servicesURL := fmt .Sprintf ("http://%s/api/services" , jaegerAddr )
188+ resp , err := http .Get (servicesURL )
189+ require .NoError (t , err )
190+ defer resp .Body .Close ()
191+
192+ body , err := io .ReadAll (resp .Body )
193+ require .NoError (t , err )
194+
195+ var services JaegerServicesResponse
196+ err = json .Unmarshal (body , & services )
197+ require .NoError (t , err )
198+
199+ t .Logf ("Registered services: %v" , services .Data )
200+
201+ // Check both alpha1 and zero1 are registered
202+ foundAlpha := false
203+ foundZero := false
204+ for _ , svc := range services .Data {
205+ if svc == "alpha1" {
206+ foundAlpha = true
207+ }
208+ if svc == "zero1" {
209+ foundZero = true
210+ }
211+ }
212+ require .True (t , foundAlpha , "Service 'alpha1' should be registered" )
213+ require .True (t , foundZero , "Service 'zero1' should be registered" )
214+
215+ // Query for traces from alpha1
216+ tracesURL := fmt .Sprintf ("http://%s/api/traces?service=alpha1&limit=50" , jaegerAddr )
217+ resp , err = http .Get (tracesURL )
218+ require .NoError (t , err )
219+ defer resp .Body .Close ()
220+
221+ body , err = io .ReadAll (resp .Body )
222+ require .NoError (t , err )
223+
224+ var traces JaegerTracesResponse
225+ err = json .Unmarshal (body , & traces )
226+ require .NoError (t , err )
227+
228+ require .NotEmpty (t , traces .Data , "Should have traces for alpha1" )
229+
230+ // Look for traces that contain both alpha1 and zero1 spans
231+ // This proves cross-service trace context propagation is working
232+ multiServiceTraceFound := false
233+ for _ , trace := range traces .Data {
234+ servicesInTrace := make (map [string ]bool )
235+ for _ , span := range trace .Spans {
236+ if proc , ok := trace .Processes [span .ProcessID ]; ok {
237+ servicesInTrace [proc .ServiceName ] = true
238+ }
239+ }
240+
241+ hasAlpha := servicesInTrace ["alpha1" ]
242+ hasZero := servicesInTrace ["zero1" ]
243+
244+ if hasAlpha && hasZero {
245+ multiServiceTraceFound = true
246+ t .Logf ("Found cross-service trace %s with services: %v" , trace .TraceID , servicesInTrace )
247+
248+ // Verify all spans share the same trace ID - this proves context propagation
249+ for _ , span := range trace .Spans {
250+ require .Equal (t , trace .TraceID , span .TraceID ,
251+ "All spans in cross-service trace must share the same trace ID" )
252+ }
253+ break
254+ }
255+ }
256+
257+ require .True (t , multiServiceTraceFound ,
258+ "Should find at least one trace containing both alpha1 and zero1 spans (proves context propagation)" )
259+ }
0 commit comments