• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.internal;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.VisibleForTesting;
22 import io.grpc.Attributes;
23 import io.grpc.ClientStreamTracer;
24 import io.grpc.Context;
25 import io.grpc.Metadata;
26 import io.grpc.ServerStreamTracer;
27 import io.grpc.ServerStreamTracer.ServerCallInfo;
28 import io.grpc.Status;
29 import io.grpc.StreamTracer;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.concurrent.atomic.AtomicBoolean;
34 import javax.annotation.concurrent.ThreadSafe;
35 
36 /**
37  * The stats and tracing information for a stream.
38  */
39 @ThreadSafe
40 public final class StatsTraceContext {
41   public static final StatsTraceContext NOOP = new StatsTraceContext(new StreamTracer[0]);
42 
43   private final StreamTracer[] tracers;
44   private final AtomicBoolean closed = new AtomicBoolean(false);
45 
46   /**
47    * Factory method for the client-side.
48    */
newClientContext( ClientStreamTracer[] tracers, Attributes transportAtts, Metadata headers)49   public static StatsTraceContext newClientContext(
50       ClientStreamTracer[] tracers, Attributes transportAtts, Metadata headers) {
51     StatsTraceContext ctx = new StatsTraceContext(tracers);
52     for (ClientStreamTracer tracer : tracers) {
53       tracer.streamCreated(transportAtts, headers);
54     }
55     return ctx;
56   }
57 
58   /**
59    * Factory method for the server-side.
60    */
newServerContext( List<? extends ServerStreamTracer.Factory> factories, String fullMethodName, Metadata headers)61   public static StatsTraceContext newServerContext(
62       List<? extends ServerStreamTracer.Factory> factories,
63       String fullMethodName,
64       Metadata headers) {
65     if (factories.isEmpty()) {
66       return NOOP;
67     }
68     StreamTracer[] tracers = new StreamTracer[factories.size()];
69     for (int i = 0; i < tracers.length; i++) {
70       tracers[i] = factories.get(i).newServerStreamTracer(fullMethodName, headers);
71     }
72     return new StatsTraceContext(tracers);
73   }
74 
75   @VisibleForTesting
StatsTraceContext(StreamTracer[] tracers)76   StatsTraceContext(StreamTracer[] tracers) {
77     this.tracers = tracers;
78   }
79 
80   /**
81    * Returns a copy of the tracer list.
82    */
83   @VisibleForTesting
getTracersForTest()84   public List<StreamTracer> getTracersForTest() {
85     return new ArrayList<>(Arrays.asList(tracers));
86   }
87 
88   /**
89    * See {@link ClientStreamTracer#outboundHeaders}.  For client-side only.
90    *
91    * <p>Transport-specific, thus should be called by transport implementations.
92    */
clientOutboundHeaders()93   public void clientOutboundHeaders() {
94     for (StreamTracer tracer : tracers) {
95       ((ClientStreamTracer) tracer).outboundHeaders();
96     }
97   }
98 
99   /**
100    * See {@link ClientStreamTracer#inboundHeaders}.  For client-side only.
101    *
102    * <p>Called from abstract stream implementations.
103    */
clientInboundHeaders()104   public void clientInboundHeaders() {
105     for (StreamTracer tracer : tracers) {
106       ((ClientStreamTracer) tracer).inboundHeaders();
107     }
108   }
109 
110   /**
111    * See {@link ClientStreamTracer#inboundTrailers}.  For client-side only.
112    *
113    * <p>Called from abstract stream implementations.
114    */
clientInboundTrailers(Metadata trailers)115   public void clientInboundTrailers(Metadata trailers) {
116     for (StreamTracer tracer : tracers) {
117       ((ClientStreamTracer) tracer).inboundTrailers(trailers);
118     }
119   }
120 
121   /**
122    * See {@link ServerStreamTracer#filterContext}. For server-side only.
123    *
124    * <p>Called from {@link io.grpc.internal.ServerImpl}.
125    */
126   @SuppressWarnings("UnusedTypeParameter")
serverFilterContext(Context context)127   public <ReqT, RespT> Context serverFilterContext(Context context) {
128     Context ctx = checkNotNull(context, "context");
129     for (StreamTracer tracer : tracers) {
130       ctx = ((ServerStreamTracer) tracer).filterContext(ctx);
131       checkNotNull(ctx, "%s returns null context", tracer);
132     }
133     return ctx;
134   }
135 
136   /**
137    * See {@link ServerStreamTracer#serverCallStarted}.  For server-side only.
138    *
139    * <p>Called from {@link io.grpc.internal.ServerImpl}.
140    */
serverCallStarted(ServerCallInfo<?, ?> callInfo)141   public void serverCallStarted(ServerCallInfo<?, ?> callInfo) {
142     for (StreamTracer tracer : tracers) {
143       ((ServerStreamTracer) tracer).serverCallStarted(callInfo);
144     }
145   }
146 
147   /**
148    * See {@link StreamTracer#streamClosed}. This may be called multiple times, and only the first
149    * value will be taken.
150    *
151    * <p>Called from abstract stream implementations.
152    */
streamClosed(Status status)153   public void streamClosed(Status status) {
154     if (closed.compareAndSet(false, true)) {
155       for (StreamTracer tracer : tracers) {
156         tracer.streamClosed(status);
157       }
158     }
159   }
160 
161   /**
162    * See {@link StreamTracer#outboundMessage(int)}.
163    *
164    * <p>Called from {@link io.grpc.internal.Framer}.
165    */
outboundMessage(int seqNo)166   public void outboundMessage(int seqNo) {
167     for (StreamTracer tracer : tracers) {
168       tracer.outboundMessage(seqNo);
169     }
170   }
171 
172   /**
173    * See {@link StreamTracer#inboundMessage(int)}.
174    *
175    * <p>Called from {@link io.grpc.internal.MessageDeframer}.
176    */
inboundMessage(int seqNo)177   public void inboundMessage(int seqNo) {
178     for (StreamTracer tracer : tracers) {
179       tracer.inboundMessage(seqNo);
180     }
181   }
182 
183   /**
184    * See {@link StreamTracer#outboundMessageSent}.
185    *
186    * <p>Called from {@link io.grpc.internal.Framer}.
187    */
outboundMessageSent(int seqNo, long optionalWireSize, long optionalUncompressedSize)188   public void outboundMessageSent(int seqNo, long optionalWireSize, long optionalUncompressedSize) {
189     for (StreamTracer tracer : tracers) {
190       tracer.outboundMessageSent(seqNo, optionalWireSize, optionalUncompressedSize);
191     }
192   }
193 
194   /**
195    * See {@link StreamTracer#inboundMessageRead}.
196    *
197    * <p>Called from {@link io.grpc.internal.MessageDeframer}.
198    */
inboundMessageRead(int seqNo, long optionalWireSize, long optionalUncompressedSize)199   public void inboundMessageRead(int seqNo, long optionalWireSize, long optionalUncompressedSize) {
200     for (StreamTracer tracer : tracers) {
201       tracer.inboundMessageRead(seqNo, optionalWireSize, optionalUncompressedSize);
202     }
203   }
204 
205   /**
206    * See {@link StreamTracer#outboundUncompressedSize}.
207    *
208    * <p>Called from {@link io.grpc.internal.Framer}.
209    */
outboundUncompressedSize(long bytes)210   public void outboundUncompressedSize(long bytes) {
211     for (StreamTracer tracer : tracers) {
212       tracer.outboundUncompressedSize(bytes);
213     }
214   }
215 
216   /**
217    * See {@link StreamTracer#outboundWireSize}.
218    *
219    * <p>Called from {@link io.grpc.internal.Framer}.
220    */
outboundWireSize(long bytes)221   public void outboundWireSize(long bytes) {
222     for (StreamTracer tracer : tracers) {
223       tracer.outboundWireSize(bytes);
224     }
225   }
226 
227   /**
228    * See {@link StreamTracer#inboundUncompressedSize}.
229    *
230    * <p>Called from {@link io.grpc.internal.MessageDeframer}.
231    */
inboundUncompressedSize(long bytes)232   public void inboundUncompressedSize(long bytes) {
233     for (StreamTracer tracer : tracers) {
234       tracer.inboundUncompressedSize(bytes);
235     }
236   }
237 
238   /**
239    * See {@link StreamTracer#inboundWireSize}.
240    *
241    * <p>Called from {@link io.grpc.internal.MessageDeframer}.
242    */
inboundWireSize(long bytes)243   public void inboundWireSize(long bytes) {
244     for (StreamTracer tracer : tracers) {
245       tracer.inboundWireSize(bytes);
246     }
247   }
248 }
249