|
16 | 16 | package com.uber.cadence.internal.compatibility.proto.serviceclient;
|
17 | 17 |
|
18 | 18 | import com.google.common.base.Strings;
|
| 19 | +import com.google.protobuf.ByteString; |
| 20 | +import com.uber.cadence.api.v1.*; |
19 | 21 | import com.uber.cadence.api.v1.DomainAPIGrpc;
|
20 | 22 | import com.uber.cadence.api.v1.MetaAPIGrpc;
|
21 | 23 | import com.uber.cadence.api.v1.MetaAPIGrpc.MetaAPIBlockingStub;
|
|
30 | 32 | import com.uber.cadence.api.v1.WorkflowAPIGrpc.WorkflowAPIBlockingStub;
|
31 | 33 | import com.uber.cadence.api.v1.WorkflowAPIGrpc.WorkflowAPIFutureStub;
|
32 | 34 | import com.uber.cadence.internal.Version;
|
| 35 | +import com.uber.cadence.internal.tracing.TracingPropagator; |
33 | 36 | import com.uber.cadence.serviceclient.ClientOptions;
|
34 | 37 | import io.grpc.CallOptions;
|
35 | 38 | import io.grpc.Channel;
|
|
48 | 51 | import io.opentelemetry.context.Context;
|
49 | 52 | import io.opentelemetry.context.propagation.TextMapPropagator;
|
50 | 53 | import io.opentelemetry.context.propagation.TextMapSetter;
|
| 54 | +import io.opentracing.Span; |
| 55 | +import io.opentracing.Tracer; |
| 56 | +import java.util.HashMap; |
| 57 | +import java.util.Map; |
| 58 | +import java.util.Objects; |
51 | 59 | import java.util.concurrent.TimeUnit;
|
52 | 60 | import java.util.concurrent.atomic.AtomicBoolean;
|
53 | 61 | import org.slf4j.Logger;
|
@@ -116,7 +124,8 @@ final class GrpcServiceStubs implements IGrpcServiceStubs {
|
116 | 124 | channel,
|
117 | 125 | deadlineInterceptor,
|
118 | 126 | MetadataUtils.newAttachHeadersInterceptor(headers),
|
119 |
| - newOpenTelemetryInterceptor()); |
| 127 | + newOpenTelemetryInterceptor(), |
| 128 | + newOpenTracingInterceptor(options.getTracer())); |
120 | 129 | if (log.isTraceEnabled()) {
|
121 | 130 | interceptedChannel = ClientInterceptors.intercept(interceptedChannel, tracingInterceptor);
|
122 | 131 | }
|
@@ -162,6 +171,80 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
|
162 | 171 | };
|
163 | 172 | }
|
164 | 173 |
|
| 174 | + private ClientInterceptor newOpenTracingInterceptor(Tracer tracer) { |
| 175 | + return new ClientInterceptor() { |
| 176 | + private final TracingPropagator tracingPropagator = new TracingPropagator(tracer); |
| 177 | + private final String OPERATIONFORMAT = "cadence-%s"; |
| 178 | + |
| 179 | + @Override |
| 180 | + public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall( |
| 181 | + MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { |
| 182 | + return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>( |
| 183 | + next.newCall(method, callOptions)) { |
| 184 | + |
| 185 | + @Override |
| 186 | + public void start(Listener<RespT> responseListener, Metadata headers) { |
| 187 | + Span span = |
| 188 | + tracingPropagator.activateSpanByServiceMethod( |
| 189 | + String.format(OPERATIONFORMAT, method.getBareMethodName())); |
| 190 | + super.start(responseListener, headers); |
| 191 | + span.finish(); |
| 192 | + } |
| 193 | + |
| 194 | + @Override |
| 195 | + public void sendMessage(ReqT message) { |
| 196 | + if (Objects.equals(method.getBareMethodName(), "StartWorkflowExecution") |
| 197 | + && message instanceof StartWorkflowExecutionRequest) { |
| 198 | + StartWorkflowExecutionRequest request = (StartWorkflowExecutionRequest) message; |
| 199 | + Map<String, byte[]> headers = new HashMap<>(); |
| 200 | + tracingPropagator.inject(headers); |
| 201 | + Header.Builder headerBuilder = request.getHeader().toBuilder(); |
| 202 | + headers.forEach( |
| 203 | + (k, v) -> { |
| 204 | + headerBuilder.putFields( |
| 205 | + k, Payload.newBuilder().setData(ByteString.copyFrom(v)).build()); |
| 206 | + }); |
| 207 | + |
| 208 | + // cast should not throw error as we are using the builder |
| 209 | + message = |
| 210 | + (ReqT) |
| 211 | + ((StartWorkflowExecutionRequest) message) |
| 212 | + .toBuilder() |
| 213 | + .setHeader(headerBuilder.build()) |
| 214 | + .build(); |
| 215 | + } |
| 216 | + if (Objects.equals(method.getBareMethodName(), "SignalWithStartWorkflowExecution") |
| 217 | + && message instanceof SignalWithStartWorkflowExecutionRequest) { |
| 218 | + SignalWithStartWorkflowExecutionRequest request = |
| 219 | + (SignalWithStartWorkflowExecutionRequest) message; |
| 220 | + Map<String, byte[]> headers = new HashMap<>(); |
| 221 | + tracingPropagator.inject(headers); |
| 222 | + Header.Builder headerBuilder = request.getStartRequest().getHeader().toBuilder(); |
| 223 | + headers.forEach( |
| 224 | + (k, v) -> { |
| 225 | + headerBuilder.putFields( |
| 226 | + k, Payload.newBuilder().setData(ByteString.copyFrom(v)).build()); |
| 227 | + }); |
| 228 | + |
| 229 | + // cast should not throw error as we are using the builder |
| 230 | + message = |
| 231 | + (ReqT) |
| 232 | + ((SignalWithStartWorkflowExecutionRequest) message) |
| 233 | + .toBuilder() |
| 234 | + .setStartRequest( |
| 235 | + request |
| 236 | + .getStartRequest() |
| 237 | + .toBuilder() |
| 238 | + .setHeader(headerBuilder.build())) |
| 239 | + .build(); |
| 240 | + } |
| 241 | + super.sendMessage(message); |
| 242 | + } |
| 243 | + }; |
| 244 | + } |
| 245 | + }; |
| 246 | + } |
| 247 | + |
165 | 248 | private ClientInterceptor newTracingInterceptor() {
|
166 | 249 | return new ClientInterceptor() {
|
167 | 250 |
|
|
0 commit comments