2828import static org .mockito .Mockito .verify ;
2929import static org .mockito .Mockito .when ;
3030
31+ import com .google .adk .Telemetry ;
3132import com .google .adk .agents .InvocationContext ;
33+ import com .google .adk .agents .LiveRequestQueue ;
3234import com .google .adk .agents .LlmAgent ;
3335import com .google .adk .agents .RunConfig ;
3436import com .google .adk .events .Event ;
4446import com .google .genai .types .Content ;
4547import com .google .genai .types .FunctionCall ;
4648import com .google .genai .types .Part ;
49+ import io .opentelemetry .api .trace .Tracer ;
50+ import io .opentelemetry .sdk .testing .junit4 .OpenTelemetryRule ;
51+ import io .opentelemetry .sdk .trace .data .SpanData ;
4752import io .reactivex .rxjava3 .core .Completable ;
4853import io .reactivex .rxjava3 .core .Flowable ;
4954import io .reactivex .rxjava3 .core .Maybe ;
5055import java .util .List ;
56+ import java .util .Objects ;
5157import java .util .Optional ;
5258import java .util .concurrent .ConcurrentHashMap ;
59+ import org .junit .After ;
60+ import org .junit .Before ;
61+ import org .junit .Rule ;
5362import org .junit .Test ;
5463import org .junit .runner .RunWith ;
5564import org .junit .runners .JUnit4 ;
5665import org .mockito .ArgumentCaptor ;
5766
5867@ RunWith (JUnit4 .class )
5968public final class RunnerTest {
69+ @ Rule public final OpenTelemetryRule openTelemetryRule = OpenTelemetryRule .create ();
6070
6171 private final BasePlugin plugin = mockPlugin ("test" );
6272 private final Content pluginContent = createContent ("from plugin" );
@@ -65,6 +75,7 @@ public final class RunnerTest {
6575 private final Runner runner = new InMemoryRunner (agent , "test" , ImmutableList .of (plugin ));
6676 private final Session session =
6777 runner .sessionService ().createSession ("test" , "user" ).blockingGet ();
78+ private Tracer originalTracer ;
6879
6980 private final FailingEchoTool failingEchoTool = new FailingEchoTool ();
7081 private final EchoTool echoTool = new EchoTool ();
@@ -94,6 +105,17 @@ private BasePlugin mockPlugin(String name) {
94105 return plugin ;
95106 }
96107
108+ @ Before
109+ public void setUp () {
110+ this .originalTracer = Telemetry .getTracer ();
111+ Telemetry .setTracerForTesting (openTelemetryRule .getOpenTelemetry ().getTracer ("RunnerTest" ));
112+ }
113+
114+ @ After
115+ public void tearDown () {
116+ Telemetry .setTracerForTesting (originalTracer );
117+ }
118+
97119 @ Test
98120 public void pluginDoesNothing () {
99121 var events =
@@ -606,4 +628,34 @@ public void beforeRunCallback_withStateDelta_seesMergedState() {
606628 private Content createContent (String text ) {
607629 return Content .builder ().parts (Part .builder ().text (text ).build ()).build ();
608630 }
631+
632+ @ Test
633+ public void runAsync_createsInvocationSpan () {
634+ var unused =
635+ runner .runAsync ("user" , session .id (), createContent ("test message" )).toList ().blockingGet ();
636+
637+ List <SpanData > spans = openTelemetryRule .getSpans ();
638+ assertThat (spans ).isNotEmpty ();
639+
640+ Optional <SpanData > invocationSpan =
641+ spans .stream ().filter (span -> Objects .equals (span .getName (), "invocation" )).findFirst ();
642+
643+ assertThat (invocationSpan ).isPresent ();
644+ assertThat (invocationSpan .get ().hasEnded ()).isTrue ();
645+ }
646+
647+ @ Test
648+ public void runLive_createsInvocationSpan () {
649+ LiveRequestQueue liveRequestQueue = new LiveRequestQueue ();
650+ var unused = runner .runLive (session , liveRequestQueue , RunConfig .builder ().build ()).test ();
651+
652+ List <SpanData > spans = openTelemetryRule .getSpans ();
653+ assertThat (spans ).isNotEmpty ();
654+
655+ Optional <SpanData > invocationSpan =
656+ spans .stream ().filter (span -> Objects .equals (span .getName (), "invocation" )).findFirst ();
657+
658+ assertThat (invocationSpan ).isPresent ();
659+ assertThat (invocationSpan .get ().hasEnded ()).isTrue ();
660+ }
609661}
0 commit comments