• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

uber / cadence-java-client / 2243

11 Apr 2024 07:03PM UTC coverage: 60.255% (-0.008%) from 60.263%
2243

push

buildkite

web-flow
Enable open tracing propagation in workflow lifecycles (#876)

How it works
Context Propagation in Cadence (Customer)

On start workflow API, trace span with context is written into workflow start event attributes, which is persisted in cadence server side.
On workflow-start in client, this span is referenced and activated on execute workflow.
On scheduling child workflows and activities (including local activities), the span is written into child workflow's workflow start event attributes and activity's schedule activity event attributes.
On processing activities/childworkflows, the persisted span is referenced and activated again.

Sample Spans

Notes: Poll + Respond apis spans are omitted here

{traceId:1, spanId:2, parentId:0, operationName:"cadence-RegisterDomain"}
{traceId:1, spanId:3, parentId:2, operationName:"Test Started"}
{traceId:1, spanId:18, parentId:3, operationName:"cadence-StartWorkflowExecution"}
{traceId:1, spanId:19, parentId:18, operationName:"cadence-GetWorkflowExecutionHistory"}
{traceId:1, spanId:21, parentId:18, operationName:"cadence-ExecuteWorkflow"}
{traceId:1, spanId:24, parentId:21, operationName:"cadence-ExecuteActivity"}
{traceId:1, spanId:25, parentId:24, operationName:"cadence-RespondActivityTaskCompleted"}
{traceId:1, spanId:31, parentId:21, operationName:"cadence-ExecuteWorkflow"}
{traceId:1, spanId:32, parentId:31, operationName:"cadence-ExecuteLocalActivity"}

What changed?

added an Propagator entity with tracing extract/inject logic
added trace activation logic in activity and workflow executors
added trace activation on service client (Tchannel + GRPC)
Why?

improve observability

How did you test it?

integration test

111 of 175 new or added lines in 13 files covered. (63.43%)

10 existing lines in 4 files now uncovered.

11449 of 19001 relevant lines covered (60.25%)

0.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.84
/src/main/java/com/uber/cadence/serviceclient/ClientOptions.java
1
/*
2
 *  Modifications Copyright (c) 2017-2020 Uber Technologies Inc.
3
 *  Portions of the Software are attributed to Copyright (c) 2020 Temporal Technologies Inc.
4
 *  Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
 *
6
 *  Licensed under the Apache License, Version 2.0 (the "License"). You may not
7
 *  use this file except in compliance with the License. A copy of the License is
8
 *  located at
9
 *
10
 *  http://aws.amazon.com/apache2.0
11
 *
12
 *  or in the "license" file accompanying this file. This file is distributed on
13
 *  an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14
 *  express or implied. See the License for the specific language governing
15
 *  permissions and limitations under the License.
16
 */
17

18
package com.uber.cadence.serviceclient;
19

20
import com.google.common.base.Strings;
21
import com.google.common.collect.ImmutableMap;
22
import com.uber.cadence.FeatureFlags;
23
import com.uber.cadence.internal.metrics.NoopScope;
24
import com.uber.cadence.serviceclient.auth.IAuthorizationProvider;
25
import com.uber.m3.tally.Scope;
26
import io.grpc.ManagedChannel;
27
import io.opentracing.Tracer;
28
import io.opentracing.noop.NoopTracerFactory;
29
import java.util.Map;
30

31
public class ClientOptions {
32

33
  private static final int DEFAULT_LOCAL_CADENCE_SERVER_PORT = 7933;
34

35
  private static final String LOCALHOST = "127.0.0.1";
36

37
  /** Default RPC timeout used for all non long poll calls. */
38
  private static final long DEFAULT_RPC_TIMEOUT_MILLIS = 3 * 1000;
39
  /** Default RPC timeout used for all long poll calls. */
40
  private static final long DEFAULT_POLL_RPC_TIMEOUT_MILLIS = 30 * 1000;
41

42
  /** Default RPC timeout for QueryWorkflow */
43
  private static final long DEFAULT_QUERY_RPC_TIMEOUT_MILLIS = 10 * 1000;
44

45
  /** Default RPC timeout for ListArchivedWorkflow */
46
  private static final long DEFAULT_LIST_ARCHIVED_WORKFLOW_TIMEOUT_MILLIS = 180 * 1000;
47

48
  private static final String DEFAULT_CLIENT_APP_NAME = "cadence-client";
49

50
  /** Name of the Cadence service front end as required by TChannel. */
51
  private static final String DEFAULT_SERVICE_NAME = "cadence-frontend";
52

53
  private static final ClientOptions DEFAULT_INSTANCE;
54

55
  static {
56
    DEFAULT_INSTANCE = new Builder().build();
1✔
57
  }
1✔
58

59
  private final String host;
60
  private final int port;
61
  private final ManagedChannel gRPCChannel;
62
  /** The tChannel timeout in milliseconds */
63
  private final long rpcTimeoutMillis;
64
  /** The tChannel timeout for long poll calls in milliseconds */
65
  private final long rpcLongPollTimeoutMillis;
66
  /** The tChannel timeout for query workflow call in milliseconds */
67
  private final long rpcQueryTimeoutMillis;
68
  /** The tChannel timeout for list archived workflow call in milliseconds */
69
  private final long rpcListArchivedWorkflowTimeoutMillis;
70
  /** TChannel service name that the Cadence service was started with. */
71
  private final String serviceName;
72
  /** Name of the service using the cadence-client. */
73
  private final String clientAppName;
74
  /** Client for metrics reporting. */
75
  private final Scope metricsScope;
76
  /** Optional TChannel transport headers */
77
  private final Map<String, String> transportHeaders;
78
  /** Optional TChannel headers */
79
  private final Map<String, String> headers;
80
  /** Optional authorization provider */
81
  private final IAuthorizationProvider authProvider;
82
  /** Optional Feature flags to turn on/off some Cadence features */
83
  private final FeatureFlags featureFlags;
84
  /** Optional isolation group of the service if tasklist isolation is enabled */
85
  private final String isolationGroup;
86
  /** Optional tracer for service client, default is GlobalTracer */
87
  private final Tracer tracer;
88

89
  private ClientOptions(Builder builder) {
1✔
90
    if (Strings.isNullOrEmpty(builder.host)) {
1✔
91
      host =
1✔
92
          Strings.isNullOrEmpty(System.getenv("CADENCE_SEEDS"))
1✔
93
              ? LOCALHOST
1✔
94
              : System.getenv("CADENCE_SEEDS");
1✔
95
    } else {
96
      host = builder.host;
×
97
    }
98
    this.port = builder.port;
1✔
99
    this.gRPCChannel = builder.gRPCChannel;
1✔
100
    this.rpcTimeoutMillis = builder.rpcTimeoutMillis;
1✔
101
    if (builder.clientAppName == null) {
1✔
102
      this.clientAppName = DEFAULT_CLIENT_APP_NAME;
×
103
    } else {
104
      this.clientAppName = builder.clientAppName;
1✔
105
    }
106
    if (builder.serviceName == null) {
1✔
107
      this.serviceName = DEFAULT_SERVICE_NAME;
1✔
108
    } else {
109
      this.serviceName = builder.serviceName;
×
110
    }
111
    this.rpcLongPollTimeoutMillis = builder.rpcLongPollTimeoutMillis;
1✔
112
    this.rpcQueryTimeoutMillis = builder.rpcQueryTimeoutMillis;
1✔
113
    this.rpcListArchivedWorkflowTimeoutMillis = builder.rpcListArchivedWorkflowTimeoutMillis;
1✔
114
    if (builder.metricsScope == null) {
1✔
115
      builder.metricsScope = NoopScope.getInstance();
1✔
116
    }
117
    this.metricsScope = builder.metricsScope;
1✔
118
    if (builder.transportHeaders != null) {
1✔
119
      this.transportHeaders = ImmutableMap.copyOf(builder.transportHeaders);
×
120
    } else {
121
      this.transportHeaders = ImmutableMap.of();
1✔
122
    }
123

124
    this.featureFlags = builder.featureFlags;
1✔
125

126
    if (builder.headers != null) {
1✔
127
      this.headers = ImmutableMap.copyOf(builder.headers);
×
128
    } else {
129
      this.headers = ImmutableMap.of();
1✔
130
    }
131
    this.authProvider = builder.authProvider;
1✔
132
    this.isolationGroup = builder.isolationGroup;
1✔
133
    this.tracer = builder.tracer;
1✔
134
  }
1✔
135

136
  public static ClientOptions defaultInstance() {
137
    return DEFAULT_INSTANCE;
×
138
  }
139

140
  public static Builder newBuilder() {
141
    return new Builder();
1✔
142
  }
143

144
  public String getHost() {
145
    return host;
1✔
146
  }
147

148
  public int getPort() {
149
    return port;
1✔
150
  }
151

152
  public ManagedChannel getGRPCChannel() {
153
    return gRPCChannel;
×
154
  }
155

156
  /** @return Returns the rpc timeout value in millis. */
157
  public long getRpcTimeoutMillis() {
158
    return rpcTimeoutMillis;
×
159
  }
160

161
  /** @return Returns the rpc timout for long poll requests in millis. */
162
  public long getRpcLongPollTimeoutMillis() {
163
    return rpcLongPollTimeoutMillis;
1✔
164
  }
165

166
  /** @return Returns the rpc timout for query workflow requests in millis. */
167
  public long getRpcQueryTimeoutMillis() {
168
    return rpcQueryTimeoutMillis;
×
169
  }
170

171
  /** @return Returns the rpc timout for list archived workflow requests in millis. */
172
  public long getRpcListArchivedWorkflowTimeoutMillis() {
173
    return rpcListArchivedWorkflowTimeoutMillis;
×
174
  }
175

176
  /** Returns the client application name. */
177
  public String getClientAppName() {
178
    return this.clientAppName;
1✔
179
  }
180

181
  public String getServiceName() {
182
    return serviceName;
1✔
183
  }
184

185
  public Scope getMetricsScope() {
186
    return metricsScope;
1✔
187
  }
188

189
  public Map<String, String> getTransportHeaders() {
190
    return transportHeaders;
1✔
191
  }
192

193
  public Map<String, String> getHeaders() {
194
    return headers;
1✔
195
  }
196

197
  public IAuthorizationProvider getAuthProvider() {
198
    return authProvider;
1✔
199
  }
200

201
  public FeatureFlags getFeatureFlags() {
202
    return this.featureFlags;
1✔
203
  }
204

205
  public String getIsolationGroup() {
206
    return this.isolationGroup;
1✔
207
  }
208

209
  public Tracer getTracer() {
210
    return this.tracer;
1✔
211
  }
212

213
  /**
214
   * Builder is the builder for ClientOptions.
215
   *
216
   * @author venkat
217
   */
218
  public static class Builder {
219

220
    private String host;
221
    private int port = DEFAULT_LOCAL_CADENCE_SERVER_PORT;
1✔
222
    private ManagedChannel gRPCChannel;
223
    private String clientAppName = DEFAULT_CLIENT_APP_NAME;
1✔
224
    private long rpcTimeoutMillis = DEFAULT_RPC_TIMEOUT_MILLIS;
1✔
225
    private long rpcLongPollTimeoutMillis = DEFAULT_POLL_RPC_TIMEOUT_MILLIS;
1✔
226
    private long rpcQueryTimeoutMillis = DEFAULT_QUERY_RPC_TIMEOUT_MILLIS;
1✔
227
    private long rpcListArchivedWorkflowTimeoutMillis =
1✔
228
        DEFAULT_LIST_ARCHIVED_WORKFLOW_TIMEOUT_MILLIS;
229
    private String serviceName;
230
    private Scope metricsScope;
231
    private Map<String, String> transportHeaders;
232
    private Map<String, String> headers;
233
    private IAuthorizationProvider authProvider;
234
    private FeatureFlags featureFlags;
235
    private String isolationGroup;
236
    // by default NoopTracer
237
    private Tracer tracer = NoopTracerFactory.create();
1✔
238

239
    private Builder() {}
1✔
240

241
    public Builder setHost(String host) {
242
      this.host = host;
×
243
      return this;
×
244
    }
245

246
    public Builder setAuthorizationProvider(IAuthorizationProvider provider) {
247
      this.authProvider = provider;
×
248
      return this;
×
249
    }
250

251
    public Builder setPort(int port) {
252
      this.port = port;
×
253
      return this;
×
254
    }
255

256
    /** Sets gRPC channel to use. Exclusive with host and port. */
257
    public Builder setGRPCChannel(ManagedChannel gRPCChannel) {
258
      this.gRPCChannel = gRPCChannel;
×
259
      return this;
×
260
    }
261

262
    /**
263
     * Sets the rpc timeout value for non query and non long poll calls. Default is 1000.
264
     *
265
     * @param timeoutMillis timeout, in millis.
266
     */
267
    public Builder setRpcTimeout(long timeoutMillis) {
268
      this.rpcTimeoutMillis = timeoutMillis;
×
269
      return this;
×
270
    }
271

272
    /**
273
     * Sets the rpc timeout value for the following long poll based operations: PollForDecisionTask,
274
     * PollForActivityTask, GetWorkflowExecutionHistory. Should never be below 60000 as this is
275
     * server side timeout for the long poll. Default is 61000.
276
     *
277
     * @param timeoutMillis timeout, in millis.
278
     */
279
    public Builder setRpcLongPollTimeout(long timeoutMillis) {
280
      this.rpcLongPollTimeoutMillis = timeoutMillis;
×
281
      return this;
×
282
    }
283

284
    /**
285
     * Sets the rpc timeout value for query calls. Default is 10000.
286
     *
287
     * @param timeoutMillis timeout, in millis.
288
     */
289
    public Builder setQueryRpcTimeout(long timeoutMillis) {
290
      this.rpcQueryTimeoutMillis = timeoutMillis;
×
291
      return this;
×
292
    }
293

294
    /**
295
     * Sets the rpc timeout value for query calls. Default is 180000.
296
     *
297
     * @param timeoutMillis timeout, in millis.
298
     */
299
    public Builder setListArchivedWorkflowRpcTimeout(long timeoutMillis) {
300
      this.rpcListArchivedWorkflowTimeoutMillis = timeoutMillis;
×
301
      return this;
×
302
    }
303

304
    /** Returns the feature flags defined in ClientOptions */
305
    public FeatureFlags getFeatureFlags() {
306
      return this.featureFlags;
×
307
    }
308

309
    /**
310
     * Sets the feature flags to turn on/off some Cadence features By default, all features under
311
     * FeatureFlags are turned off.
312
     *
313
     * @param featureFlags FeatureFlags
314
     */
315
    public Builder setFeatureFlags(FeatureFlags featureFlags) {
316
      this.featureFlags = featureFlags;
1✔
317
      return this;
1✔
318
    }
319

320
    /**
321
     * Sets the client application name.
322
     *
323
     * <p>This name will be used as the tchannel client service name. It will also be reported as a
324
     * tag along with metrics emitted to m3.
325
     *
326
     * @param clientAppName String representing the client application name.
327
     * @return Builder for ClentOptions
328
     */
329
    public Builder setClientAppName(String clientAppName) {
330
      this.clientAppName = clientAppName;
×
331
      return this;
×
332
    }
333

334
    /**
335
     * Sets the service name that Cadence service was started with.
336
     *
337
     * @param serviceName String representing the service name
338
     * @return Builder for ClentOptions
339
     */
340
    public Builder setServiceName(String serviceName) {
341
      this.serviceName = serviceName;
×
342
      return this;
×
343
    }
344

345
    /**
346
     * Sets the metrics scope to be used for metrics reporting.
347
     *
348
     * @param metricsScope
349
     * @return Builder for ClentOptions
350
     */
351
    public Builder setMetricsScope(Scope metricsScope) {
352
      this.metricsScope = metricsScope;
×
353
      return this;
×
354
    }
355

356
    /**
357
     * Sets additional transport headers for tchannel client.
358
     *
359
     * @param transportHeaders Map with additional transport headers
360
     * @return Builder for ClentOptions
361
     */
362
    public Builder setTransportHeaders(Map<String, String> transportHeaders) {
363
      this.transportHeaders = transportHeaders;
×
364
      return this;
×
365
    }
366

367
    public Builder setHeaders(Map<String, String> headers) {
368
      this.headers = headers;
×
369
      return this;
×
370
    }
371

372
    /**
373
     * Sets the isolation group to be used for matching.
374
     *
375
     * @param isolationGroup
376
     * @return Builder for ClentOptions
377
     */
378
    public Builder setIsolationGroup(String isolationGroup) {
379
      this.isolationGroup = isolationGroup;
×
380
      return this;
×
381
    }
382

383
    /**
384
     * Sets the tracer to be used for service client.
385
     *
386
     * @param tracer
387
     * @return Builder for ClentOptions
388
     */
389
    public Builder setTracer(Tracer tracer) {
NEW
390
      this.tracer = tracer;
×
NEW
391
      return this;
×
392
    }
393

394
    /**
395
     * Builds and returns a ClientOptions object.
396
     *
397
     * @return ClientOptions object with the specified params.
398
     */
399
    public ClientOptions build() {
400
      return new ClientOptions(this);
1✔
401
    }
402
  }
403
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc