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