@@ -5,6 +5,7 @@ import datadog.trace.agent.test.base.HttpServer
55import datadog.trace.agent.test.base.HttpServerTest
66import datadog.trace.api.DDSpanTypes
77import datadog.trace.api.DDTags
8+ import datadog.trace.api.config.TracerConfig
89import datadog.trace.api.iast.IastContext
910import datadog.trace.api.iast.InstrumentationBridge
1011import datadog.trace.api.iast.SourceTypes
@@ -61,6 +62,7 @@ class SpringBootBasedTest extends HttpServerTest<ConfigurableApplicationContext>
6162 protected void configurePreAgent () {
6263 super . configurePreAgent()
6364 injectSysConfig(' dd.iast.enabled' , ' true' )
65+ injectSysConfig(TracerConfig . TRACE_INFERRED_PROXY_SERVICES_ENABLED , ' true' )
6466 }
6567
6668 @Override
@@ -479,4 +481,121 @@ class SpringBootBasedTest extends HttpServerTest<ConfigurableApplicationContext>
479481 }
480482 }
481483 }
484+
485+ def " test inferred proxy span is finished" () {
486+ setup :
487+ def request = request(SUCCESS , " GET" , null )
488+ .header(" x-dd-proxy" , " aws-apigateway" )
489+ .header(" x-dd-proxy-request-time-ms" , " 12345" )
490+ .header(" x-dd-proxy-path" , " /success" )
491+ .header(" x-dd-proxy-httpmethod" , " GET" )
492+ .header(" x-dd-proxy-domain-name" , " api.example.com" )
493+ .header(" x-dd-proxy-stage" , " test" )
494+ .build()
495+
496+ when :
497+ def response = client. newCall(request). execute()
498+
499+ then :
500+ response. code() == SUCCESS . status
501+
502+ and :
503+ // Verify that inferred proxy span was created and finished
504+ // It should appear in the trace as an additional span
505+ assertTraces(1 ) {
506+ trace(spanCount(SUCCESS ) + 1 ) {
507+ sortSpansByStart()
508+ // The inferred proxy span should be the first span (earliest start time)
509+ // Verify it exists and was finished (appears in trace)
510+ // Operation name is the proxy system name (aws.apigateway), not inferred_proxy
511+ span {
512+ operationName " aws.apigateway"
513+ serviceName " api.example.com"
514+ // Resource Name: httpmethod + " " + path
515+ resourceName " GET /success"
516+ spanType " web"
517+ parent()
518+ tags {
519+ " $Tags . COMPONENT " " aws-apigateway"
520+ " $Tags . HTTP_METHOD " " GET"
521+ " $Tags . HTTP_URL " " api.example.com/success"
522+ " $Tags . HTTP_ROUTE " " /success"
523+ " stage" " test"
524+ " _dd.inferred_span" 1
525+ // Standard tags that are automatically added
526+ " _dd.agent_psr" Number
527+ " _dd.base_service" String
528+ " _dd.dsm.enabled" Number
529+ " _dd.profiling.ctx" String
530+ " _dd.profiling.enabled" Number
531+ " _dd.trace_span_attribute_schema" Number
532+ " _dd.tracer_host" String
533+ " _sample_rate" Number
534+ " language" " jvm"
535+ " process_id" Number
536+ " runtime-id" String
537+ " thread.id" Number
538+ " thread.name" String
539+ }
540+ }
541+ // Server span should be a child of the inferred proxy span
542+ // When there's an inferred proxy span parent, the server span inherits the parent's service name
543+ span {
544+ // Service name is inherited from the inferred proxy span parent
545+ serviceName " api.example.com"
546+ operationName operation()
547+ resourceName expectedResourceName(SUCCESS , " GET" , address)
548+ spanType DDSpanTypes . HTTP_SERVER
549+ errored false
550+ childOfPrevious()
551+ tags {
552+ " $Tags . COMPONENT " component
553+ " $Tags . SPAN_KIND " Tags . SPAN_KIND_SERVER
554+ " $Tags . PEER_HOST_IPV4 " " 127.0.0.1"
555+ " $Tags . PEER_PORT " Integer
556+ " $Tags . HTTP_CLIENT_IP " " 127.0.0.1"
557+ " $Tags . HTTP_HOSTNAME " address. host
558+ " $Tags . HTTP_URL " String
559+ " $Tags . HTTP_METHOD " " GET"
560+ " $Tags . HTTP_STATUS " SUCCESS . status
561+ " $Tags . HTTP_USER_AGENT " String
562+ " $Tags . HTTP_ROUTE " " /success"
563+ " servlet.context" " /boot-context"
564+ " servlet.path" " /success"
565+ defaultTags()
566+ }
567+ }
568+ if (hasHandlerSpan()) {
569+ // Handler span inherits service name from inferred proxy span parent
570+ it. span {
571+ serviceName " api.example.com"
572+ operationName " spring.handler"
573+ resourceName " TestController.success"
574+ spanType DDSpanTypes . HTTP_SERVER
575+ errored false
576+ childOfPrevious()
577+ tags {
578+ " $Tags . COMPONENT " SpringWebHttpServerDecorator . DECORATE . component()
579+ " $Tags . SPAN_KIND " Tags . SPAN_KIND_SERVER
580+ defaultTags()
581+ }
582+ }
583+ }
584+ // Controller span also inherits service name
585+ it. span {
586+ serviceName " api.example.com"
587+ operationName " controller"
588+ resourceName " controller"
589+ errored false
590+ childOfPrevious()
591+ tags {
592+ defaultTags()
593+ }
594+ }
595+ if (hasResponseSpan(SUCCESS )) {
596+ responseSpan(it, SUCCESS )
597+ }
598+ }
599+ }
600+ }
482601}
0 commit comments