1616
1717package com .google .cloud .firestore ;
1818
19+ import static com .google .cloud .firestore .telemetry .TraceUtil .SPAN_NAME_RUN_AGGREGATION_QUERY ;
20+
1921import com .google .api .core .ApiFuture ;
2022import com .google .api .core .InternalExtensionOnly ;
2123import com .google .api .core .SettableApiFuture ;
2426import com .google .api .gax .rpc .StatusCode ;
2527import com .google .api .gax .rpc .StreamController ;
2628import com .google .cloud .Timestamp ;
29+ import com .google .cloud .firestore .telemetry .TraceUtil ;
30+ import com .google .cloud .firestore .telemetry .TraceUtil .Scope ;
2731import com .google .cloud .firestore .v1 .FirestoreSettings ;
32+ import com .google .common .collect .ImmutableMap ;
2833import com .google .firestore .v1 .RunAggregationQueryRequest ;
2934import com .google .firestore .v1 .RunAggregationQueryResponse ;
3035import com .google .firestore .v1 .RunQueryRequest ;
3439import com .google .firestore .v1 .Value ;
3540import com .google .protobuf .ByteString ;
3641import java .util .ArrayList ;
42+ import java .util .Collections ;
3743import java .util .HashMap ;
3844import java .util .HashSet ;
3945import java .util .List ;
@@ -59,6 +65,11 @@ public class AggregateQuery {
5965 this .aliasMap = new HashMap <>();
6066 }
6167
68+ @ Nonnull
69+ private TraceUtil getTraceUtil () {
70+ return query .getFirestore ().getOptions ().getTraceUtil ();
71+ }
72+
6273 /** Returns the query whose aggregations will be calculated by this object. */
6374 @ Nonnull
6475 public Query getQuery () {
@@ -77,17 +88,30 @@ public ApiFuture<AggregateQuerySnapshot> get() {
7788
7889 @ Nonnull
7990 ApiFuture <AggregateQuerySnapshot > get (@ Nullable final ByteString transactionId ) {
80- AggregateQueryResponseDeliverer responseDeliverer =
81- new AggregateQueryResponseDeliverer (
82- transactionId , /* startTimeNanos= */ query .rpcContext .getClock ().nanoTime ());
83- runQuery (responseDeliverer );
84- return responseDeliverer .getFuture ();
91+ TraceUtil .Span span =
92+ getTraceUtil ()
93+ .startSpan (
94+ transactionId == null
95+ ? TraceUtil .SPAN_NAME_AGGREGATION_QUERY_GET
96+ : TraceUtil .SPAN_NAME_TRANSACTION_GET_AGGREGATION_QUERY );
97+ try (Scope ignored = span .makeCurrent ()) {
98+ AggregateQueryResponseDeliverer responseDeliverer =
99+ new AggregateQueryResponseDeliverer (
100+ transactionId , /* startTimeNanos= */ query .rpcContext .getClock ().nanoTime ());
101+ runQuery (responseDeliverer , /* attempt= */ 0 );
102+ ApiFuture <AggregateQuerySnapshot > result = responseDeliverer .getFuture ();
103+ span .endAtFuture (result );
104+ return result ;
105+ } catch (Exception error ) {
106+ span .end (error );
107+ throw error ;
108+ }
85109 }
86110
87- private void runQuery (AggregateQueryResponseDeliverer responseDeliverer ) {
111+ private void runQuery (AggregateQueryResponseDeliverer responseDeliverer , int attempt ) {
88112 RunAggregationQueryRequest request = toProto (responseDeliverer .getTransactionId ());
89113 AggregateQueryResponseObserver responseObserver =
90- new AggregateQueryResponseObserver (responseDeliverer );
114+ new AggregateQueryResponseObserver (responseDeliverer , attempt );
91115 ServerStreamingCallable <RunAggregationQueryRequest , RunAggregationQueryResponse > callable =
92116 query .rpcContext .getClient ().runAggregationQueryCallable ();
93117 query .rpcContext .streamRequest (request , responseObserver , callable );
@@ -138,18 +162,36 @@ private final class AggregateQueryResponseObserver
138162
139163 private final AggregateQueryResponseDeliverer responseDeliverer ;
140164 private StreamController streamController ;
165+ private int attempt ;
141166
142- AggregateQueryResponseObserver (AggregateQueryResponseDeliverer responseDeliverer ) {
167+ AggregateQueryResponseObserver (AggregateQueryResponseDeliverer responseDeliverer , int attempt ) {
143168 this .responseDeliverer = responseDeliverer ;
169+ this .attempt = attempt ;
170+ }
171+
172+ Map <String , Object > getAttemptAttributes () {
173+ ImmutableMap .Builder <String , Object > builder =
174+ new ImmutableMap .Builder <String , Object >().put ("isRetryAttempt" , attempt > 0 );
175+ if (attempt > 0 ) {
176+ builder .put ("attemptNumber" , attempt );
177+ }
178+ return builder .build ();
144179 }
145180
146181 @ Override
147182 public void onStart (StreamController streamController ) {
183+ getTraceUtil ()
184+ .currentSpan ()
185+ .addEvent (SPAN_NAME_RUN_AGGREGATION_QUERY + " Stream started." , getAttemptAttributes ());
148186 this .streamController = streamController ;
149187 }
150188
151189 @ Override
152190 public void onResponse (RunAggregationQueryResponse response ) {
191+ getTraceUtil ()
192+ .currentSpan ()
193+ .addEvent (
194+ SPAN_NAME_RUN_AGGREGATION_QUERY + " Response Received." , getAttemptAttributes ());
153195 // Close the stream to avoid it dangling, since we're not expecting any more responses.
154196 streamController .cancel ();
155197
@@ -165,8 +207,19 @@ public void onResponse(RunAggregationQueryResponse response) {
165207 @ Override
166208 public void onError (Throwable throwable ) {
167209 if (shouldRetry (throwable )) {
168- runQuery (responseDeliverer );
210+ getTraceUtil ()
211+ .currentSpan ()
212+ .addEvent (
213+ SPAN_NAME_RUN_AGGREGATION_QUERY + ": Retryable Error" ,
214+ Collections .singletonMap ("error.message" , throwable .getMessage ()));
215+
216+ runQuery (responseDeliverer , attempt + 1 );
169217 } else {
218+ getTraceUtil ()
219+ .currentSpan ()
220+ .addEvent (
221+ SPAN_NAME_RUN_AGGREGATION_QUERY + ": Error" ,
222+ Collections .singletonMap ("error.message" , throwable .getMessage ()));
170223 responseDeliverer .deliverError (throwable );
171224 }
172225 }
0 commit comments