44package integration
55
66import (
7+ "encoding/json"
78 "fmt"
89 "net/http"
910 "path"
@@ -15,7 +16,9 @@ import (
1516 "github.com/stretchr/testify/require"
1617
1718 "go.opentelemetry.io/obi/internal/test/integration/components/docker"
19+ "go.opentelemetry.io/obi/internal/test/integration/components/jaeger"
1820 "go.opentelemetry.io/obi/internal/test/integration/components/promtest"
21+ ti "go.opentelemetry.io/obi/pkg/test/integration"
1922)
2023
2124func TestMultiProcess (t * testing.T ) {
@@ -226,3 +229,114 @@ func checkInstrumentedProcessesMetric(t *testing.T) {
226229 }
227230 }, testTimeout , 1000 * time .Millisecond )
228231}
232+
233+ // We are instrumenting only the Rust and Ruby services, all other server span queries should come empty
234+ func testPartialLanguageHTTPProbes (t * testing.T ) {
235+ waitForTestComponentsSub (t , "http://localhost:8091" , "/dist" ) // rust
236+
237+ for i := 0 ; i < 100 ; i ++ {
238+ ti .DoHTTPGet (t , "http://localhost:8091/dist" , 200 )
239+ }
240+
241+ // check the rust service, it will not have any nested spans
242+ require .EventuallyWithT (t , func (ct * assert.CollectT ) {
243+ resp , err := http .Get (jaegerQueryURL + "?service=greetings&operation=GET%20%2Fdist" )
244+ require .NoError (ct , err )
245+ if resp == nil {
246+ return
247+ }
248+ require .Equal (ct , http .StatusOK , resp .StatusCode )
249+ var tq jaeger.TracesQuery
250+ require .NoError (ct , json .NewDecoder (resp .Body ).Decode (& tq ))
251+ traces := tq .FindBySpan (jaeger.Tag {Key : "url.path" , Type : "string" , Value : "/dist" })
252+ require .LessOrEqual (ct , 5 , len (traces ))
253+ for _ , trace := range traces {
254+ // Check the information of the rust parent span
255+ res := trace .FindByOperationName ("GET /dist" , "server" )
256+ require .Len (ct , res , 1 )
257+ parent := res [0 ]
258+ require .NotEmpty (ct , parent .TraceID )
259+ require .NotEmpty (ct , parent .SpanID )
260+ // check duration is at least 2us
261+ assert .Less (ct , (2 * time .Microsecond ).Microseconds (), parent .Duration )
262+ // check span attributes
263+ sd := parent .Diff (
264+ jaeger.Tag {Key : "http.request.method" , Type : "string" , Value : "GET" },
265+ jaeger.Tag {Key : "http.response.status_code" , Type : "int64" , Value : float64 (200 )},
266+ jaeger.Tag {Key : "url.path" , Type : "string" , Value : "/dist" },
267+ jaeger.Tag {Key : "server.port" , Type : "int64" , Value : float64 (8090 )},
268+ jaeger.Tag {Key : "http.route" , Type : "string" , Value : "/dist" },
269+ jaeger.Tag {Key : "span.kind" , Type : "string" , Value : "server" },
270+ )
271+ assert .Empty (ct , sd , sd .String ())
272+
273+ // Check the information of the java parent span
274+ res = trace .FindByOperationName ("GET /jtrace" , "server" )
275+ require .Empty (ct , res )
276+
277+ // Check the information of the nodejs parent span
278+ res = trace .FindByOperationName ("GET /traceme" , "server" )
279+ require .Empty (ct , res )
280+
281+ // Check the information of the go parent span
282+ res = trace .FindByOperationName ("GET /gotracemetoo" , "server" )
283+ require .Empty (ct , res )
284+
285+ // Check the information of the python parent span
286+ res = trace .FindByOperationName ("GET /tracemetoo" , "server" )
287+ require .Empty (t , res )
288+
289+ // Check the information of the rails parent span
290+ res = trace .FindByOperationName ("GET /users" , "server" )
291+ require .Empty (t , res )
292+ }
293+ }, testTimeout , 100 * time .Millisecond )
294+
295+ require .EventuallyWithT (t , func (ct * assert.CollectT ) {
296+ resp , err := http .Get (jaegerQueryURL + "?service=ruby&operation=GET%20%2Fusers" )
297+ require .NoError (ct , err )
298+ if resp == nil {
299+ return
300+ }
301+ require .Equal (ct , http .StatusOK , resp .StatusCode )
302+ var tq jaeger.TracesQuery
303+ require .NoError (ct , json .NewDecoder (resp .Body ).Decode (& tq ))
304+ traces := tq .FindBySpan (jaeger.Tag {Key : "url.path" , Type : "string" , Value : "/users" })
305+ require .LessOrEqual (ct , 5 , len (traces ))
306+ for _ , trace := range traces {
307+ // Check the information of the rust parent span
308+ res := trace .FindByOperationName ("GET /users" , "server" )
309+ require .Len (ct , res , 1 )
310+ }
311+ }, testTimeout , 100 * time .Millisecond )
312+
313+ require .EventuallyWithT (t , func (ct * assert.CollectT ) {
314+ resp , err := http .Get (jaegerQueryURL + "?service=testserver&operation=GET%20%2Fgotracemetoo" )
315+ require .NoError (ct , err )
316+ if resp == nil {
317+ return
318+ }
319+ require .Equal (ct , http .StatusOK , resp .StatusCode )
320+ var tq jaeger.TracesQuery
321+ require .NoError (ct , json .NewDecoder (resp .Body ).Decode (& tq ))
322+ traces := tq .FindBySpan (jaeger.Tag {Key : "url.path" , Type : "string" , Value : "/gotracemetoo" })
323+ require .Empty (ct , traces )
324+ }, testTimeout , 100 * time .Millisecond )
325+ }
326+
327+ func TestLanguageSelectors (t * testing.T ) {
328+ compose , err := docker .ComposeSuite ("docker-compose-multiexec.yml" , path .Join (pathOutput , "test-suite-multiexec-lang.log" ))
329+ require .NoError (t , err )
330+
331+ // we are going to setup discovery directly in the configuration file, choose the lang config file
332+ compose .Env = append (compose .Env , `OTEL_EBPF_EXECUTABLE_PATH=` , `OTEL_EBPF_OPEN_PORT=` , `MULTI_TEST_MODE=-lang` )
333+ require .NoError (t , compose .Up ())
334+
335+ // We are testing with instrumenting only Ruby and Rust services, so from our call chain we should only see
336+ // traces for the two services written in the correct language
337+ t .Run ("Partial traces: rust (OK) -> java (NO) -> node (NO) -> go (NO) -> python (NO) -> rails (OK)" , func (t * testing.T ) {
338+ testPartialLanguageHTTPProbes (t )
339+ })
340+
341+ require .NoError (t , compose .Close ())
342+ }
0 commit comments