Skip to content

Commit 87dec37

Browse files
google-genai-botcopybara-github
authored andcommitted
test: Adding a test for telemetry in RunnerTest
PiperOrigin-RevId: 823192673
1 parent 4689ed0 commit 87dec37

File tree

6 files changed

+63
-201
lines changed

6 files changed

+63
-201
lines changed

core/src/main/java/com/google/adk/Telemetry.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,17 @@
5050
public class Telemetry {
5151

5252
private static final Logger log = LoggerFactory.getLogger(Telemetry.class);
53-
private static final Tracer tracer = GlobalOpenTelemetry.getTracer("gcp.vertex.agent");
53+
54+
@SuppressWarnings("NonFinalStaticField")
55+
private static Tracer tracer = GlobalOpenTelemetry.getTracer("gcp.vertex.agent");
5456

5557
private Telemetry() {}
5658

59+
/** Sets the OpenTelemetry instance to be used for tracing. This is for testing purposes only. */
60+
public static void setTracerForTesting(Tracer tracer) {
61+
Telemetry.tracer = tracer;
62+
}
63+
5764
/**
5865
* Traces tool call arguments.
5966
*

core/src/main/java/com/google/adk/events/EventActions.java

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import com.fasterxml.jackson.annotation.JsonProperty;
1919
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
20-
import com.google.adk.tools.ToolConfirmation;
2120
import com.google.errorprone.annotations.CanIgnoreReturnValue;
2221
import com.google.genai.types.Part;
2322
import java.util.Objects;
@@ -38,8 +37,6 @@ public class EventActions {
3837
private Optional<Boolean> escalate = Optional.empty();
3938
private ConcurrentMap<String, ConcurrentMap<String, Object>> requestedAuthConfigs =
4039
new ConcurrentHashMap<>();
41-
private ConcurrentMap<String, ToolConfirmation> requestedToolConfirmations =
42-
new ConcurrentHashMap<>();
4340
private Optional<Boolean> endInvocation = Optional.empty();
4441

4542
/** Default constructor for Jackson. */
@@ -116,16 +113,6 @@ public void setRequestedAuthConfigs(
116113
this.requestedAuthConfigs = requestedAuthConfigs;
117114
}
118115

119-
@JsonProperty("requestedToolConfirmations")
120-
public ConcurrentMap<String, ToolConfirmation> requestedToolConfirmations() {
121-
return requestedToolConfirmations;
122-
}
123-
124-
public void setRequestedToolConfirmations(
125-
ConcurrentMap<String, ToolConfirmation> requestedToolConfirmations) {
126-
this.requestedToolConfirmations = requestedToolConfirmations;
127-
}
128-
129116
@JsonProperty("endInvocation")
130117
public Optional<Boolean> endInvocation() {
131118
return endInvocation;
@@ -161,7 +148,6 @@ public boolean equals(Object o) {
161148
&& Objects.equals(transferToAgent, that.transferToAgent)
162149
&& Objects.equals(escalate, that.escalate)
163150
&& Objects.equals(requestedAuthConfigs, that.requestedAuthConfigs)
164-
&& Objects.equals(requestedToolConfirmations, that.requestedToolConfirmations)
165151
&& Objects.equals(endInvocation, that.endInvocation);
166152
}
167153

@@ -174,7 +160,6 @@ public int hashCode() {
174160
transferToAgent,
175161
escalate,
176162
requestedAuthConfigs,
177-
requestedToolConfirmations,
178163
endInvocation);
179164
}
180165

@@ -187,8 +172,6 @@ public static class Builder {
187172
private Optional<Boolean> escalate = Optional.empty();
188173
private ConcurrentMap<String, ConcurrentMap<String, Object>> requestedAuthConfigs =
189174
new ConcurrentHashMap<>();
190-
private ConcurrentMap<String, ToolConfirmation> requestedToolConfirmations =
191-
new ConcurrentHashMap<>();
192175
private Optional<Boolean> endInvocation = Optional.empty();
193176

194177
public Builder() {}
@@ -200,8 +183,6 @@ private Builder(EventActions eventActions) {
200183
this.transferToAgent = eventActions.transferToAgent();
201184
this.escalate = eventActions.escalate();
202185
this.requestedAuthConfigs = new ConcurrentHashMap<>(eventActions.requestedAuthConfigs());
203-
this.requestedToolConfirmations =
204-
new ConcurrentHashMap<>(eventActions.requestedToolConfirmations());
205186
this.endInvocation = eventActions.endInvocation();
206187
}
207188

@@ -248,13 +229,6 @@ public Builder requestedAuthConfigs(
248229
return this;
249230
}
250231

251-
@CanIgnoreReturnValue
252-
@JsonProperty("requestedToolConfirmations")
253-
public Builder requestedToolConfirmations(ConcurrentMap<String, ToolConfirmation> value) {
254-
this.requestedToolConfirmations = value;
255-
return this;
256-
}
257-
258232
@CanIgnoreReturnValue
259233
@JsonProperty("endInvocation")
260234
public Builder endInvocation(boolean endInvocation) {
@@ -282,9 +256,6 @@ public Builder merge(EventActions other) {
282256
if (other.requestedAuthConfigs() != null) {
283257
this.requestedAuthConfigs.putAll(other.requestedAuthConfigs());
284258
}
285-
if (other.requestedToolConfirmations() != null) {
286-
this.requestedToolConfirmations.putAll(other.requestedToolConfirmations());
287-
}
288259
if (other.endInvocation().isPresent()) {
289260
this.endInvocation = other.endInvocation();
290261
}
@@ -299,7 +270,6 @@ public EventActions build() {
299270
eventActions.setTransferToAgent(this.transferToAgent);
300271
eventActions.setEscalate(this.escalate);
301272
eventActions.setRequestedAuthConfigs(this.requestedAuthConfigs);
302-
eventActions.setRequestedToolConfirmations(this.requestedToolConfirmations);
303273
eventActions.setEndInvocation(this.endInvocation);
304274
return eventActions;
305275
}

core/src/main/java/com/google/adk/tools/ToolConfirmation.java

Lines changed: 0 additions & 71 deletions
This file was deleted.

core/src/main/java/com/google/adk/tools/ToolContext.java

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,17 @@
2323
import com.google.errorprone.annotations.CanIgnoreReturnValue;
2424
import io.reactivex.rxjava3.core.Single;
2525
import java.util.Optional;
26-
import javax.annotation.Nullable;
2726

2827
/** ToolContext object provides a structured context for executing tools or functions. */
2928
public class ToolContext extends CallbackContext {
3029
private Optional<String> functionCallId = Optional.empty();
31-
private Optional<ToolConfirmation> toolConfirmation = Optional.empty();
3230

3331
private ToolContext(
3432
InvocationContext invocationContext,
3533
EventActions eventActions,
36-
Optional<String> functionCallId,
37-
Optional<ToolConfirmation> toolConfirmation) {
34+
Optional<String> functionCallId) {
3835
super(invocationContext, eventActions);
3936
this.functionCallId = functionCallId;
40-
this.toolConfirmation = toolConfirmation;
4137
}
4238

4339
public EventActions actions() {
@@ -56,14 +52,6 @@ public void functionCallId(String functionCallId) {
5652
this.functionCallId = Optional.ofNullable(functionCallId);
5753
}
5854

59-
public Optional<ToolConfirmation> toolConfirmation() {
60-
return toolConfirmation;
61-
}
62-
63-
public void toolConfirmation(ToolConfirmation toolConfirmation) {
64-
this.toolConfirmation = Optional.ofNullable(toolConfirmation);
65-
}
66-
6755
@SuppressWarnings("unused")
6856
private void requestCredential() {
6957
// TODO: b/414678311 - Implement credential request logic. Make this public.
@@ -76,35 +64,6 @@ private void getAuthResponse() {
7664
throw new UnsupportedOperationException("Auth response retrieval not implemented yet.");
7765
}
7866

79-
/**
80-
* Requests confirmation for the given function call.
81-
*
82-
* @param hint A hint to the user on how to confirm the tool call.
83-
* @param payload The payload used to confirm the tool call.
84-
*/
85-
public void requestConfirmation(@Nullable String hint, @Nullable Object payload) {
86-
if (functionCallId.isEmpty()) {
87-
throw new IllegalStateException("function_call_id is not set.");
88-
}
89-
this.eventActions
90-
.requestedToolConfirmations()
91-
.put(functionCallId.get(), ToolConfirmation.builder().hint(hint).payload(payload).build());
92-
}
93-
94-
/**
95-
* Requests confirmation for the given function call.
96-
*
97-
* @param hint A hint to the user on how to confirm the tool call.
98-
*/
99-
public void requestConfirmation(@Nullable String hint) {
100-
requestConfirmation(hint, null);
101-
}
102-
103-
/** Requests confirmation for the given function call. */
104-
public void requestConfirmation() {
105-
requestConfirmation(null, null);
106-
}
107-
10867
/** Searches the memory of the current user. */
10968
public Single<SearchMemoryResponse> searchMemory(String query) {
11069
if (invocationContext.memoryService() == null) {
@@ -123,16 +82,14 @@ public static Builder builder(InvocationContext invocationContext) {
12382
public Builder toBuilder() {
12483
return new Builder(invocationContext)
12584
.actions(eventActions)
126-
.functionCallId(functionCallId.orElse(null))
127-
.toolConfirmation(toolConfirmation.orElse(null));
85+
.functionCallId(functionCallId.orElse(null));
12886
}
12987

13088
/** Builder for {@link ToolContext}. */
13189
public static final class Builder {
13290
private final InvocationContext invocationContext;
13391
private EventActions eventActions = EventActions.builder().build(); // Default empty actions
13492
private Optional<String> functionCallId = Optional.empty();
135-
private Optional<ToolConfirmation> toolConfirmation = Optional.empty();
13693

13794
private Builder(InvocationContext invocationContext) {
13895
this.invocationContext = invocationContext;
@@ -150,14 +107,8 @@ public Builder functionCallId(String functionCallId) {
150107
return this;
151108
}
152109

153-
@CanIgnoreReturnValue
154-
public Builder toolConfirmation(ToolConfirmation toolConfirmation) {
155-
this.toolConfirmation = Optional.ofNullable(toolConfirmation);
156-
return this;
157-
}
158-
159110
public ToolContext build() {
160-
return new ToolContext(invocationContext, eventActions, functionCallId, toolConfirmation);
111+
return new ToolContext(invocationContext, eventActions, functionCallId);
161112
}
162113
}
163114
}

core/src/test/java/com/google/adk/runner/RunnerTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
import static org.mockito.Mockito.verify;
2929
import static org.mockito.Mockito.when;
3030

31+
import com.google.adk.Telemetry;
3132
import com.google.adk.agents.InvocationContext;
33+
import com.google.adk.agents.LiveRequestQueue;
3234
import com.google.adk.agents.LlmAgent;
3335
import com.google.adk.agents.RunConfig;
3436
import com.google.adk.events.Event;
@@ -44,19 +46,27 @@
4446
import com.google.genai.types.Content;
4547
import com.google.genai.types.FunctionCall;
4648
import 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;
4752
import io.reactivex.rxjava3.core.Completable;
4853
import io.reactivex.rxjava3.core.Flowable;
4954
import io.reactivex.rxjava3.core.Maybe;
5055
import java.util.List;
56+
import java.util.Objects;
5157
import java.util.Optional;
5258
import java.util.concurrent.ConcurrentHashMap;
59+
import org.junit.After;
60+
import org.junit.Before;
61+
import org.junit.Rule;
5362
import org.junit.Test;
5463
import org.junit.runner.RunWith;
5564
import org.junit.runners.JUnit4;
5665
import org.mockito.ArgumentCaptor;
5766

5867
@RunWith(JUnit4.class)
5968
public 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

Comments
 (0)