Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit 7c524f5

Browse files
authored
Exporter/Stats/Stackdriver: Provide Deadline option and don't do retry by default. (#1883)
* Exporter/Stats/Stackdriver: Provide Deadline option and don't do retry by default. * Allow to configure a custom Stackdriver Monitoring client. * Small fix on javadoc. * Set default value of Deadline to 10s, similar to Trace.
1 parent 2e218f1 commit 7c524f5

5 files changed

Lines changed: 152 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
- Disable RunningSpanStore by default unless the z-pages contrib is linked and initialized. This may
33
break behaviors for applications that rely on this to be always enabled.
44
- Provide a `Deadline` option to Stackdriver Trace exporter. Default value is 10 seconds if it's not set.
5+
- Provide a `Deadline` option to Stackdriver Stats exporter. Default value is 10 seconds.
6+
Also provide a `MetricServiceStub` option so that advanced users can use a custom Stackdriver
7+
Monitoring client to make RPCs.
58

69
## 0.21.0 - 2019-04-30
710
- Add HTTP text format serializer to Tag propagation component.

exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsConfiguration.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import com.google.auth.Credentials;
2323
import com.google.auto.value.AutoValue;
2424
import com.google.cloud.ServiceOptions;
25+
import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
26+
import com.google.common.annotations.VisibleForTesting;
2527
import com.google.common.base.Preconditions;
2628
import com.google.common.base.Strings;
2729
import io.opencensus.common.Duration;
@@ -46,6 +48,7 @@ public abstract class StackdriverStatsConfiguration {
4648
static final MonitoredResource DEFAULT_RESOURCE = StackdriverExportUtils.getDefaultResource();
4749
static final String DEFAULT_PROJECT_ID =
4850
Strings.nullToEmpty(ServiceOptions.getDefaultProjectId());
51+
static final Duration DEFAULT_DEADLINE = Duration.create(10, 0);
4952

5053
StackdriverStatsConfiguration() {}
5154

@@ -99,6 +102,26 @@ public abstract class StackdriverStatsConfiguration {
99102
*/
100103
public abstract Map<LabelKey, LabelValue> getConstantLabels();
101104

105+
/**
106+
* Returns the deadline for exporting to Stackdriver Monitoring backend.
107+
*
108+
* <p>Default value is 10 seconds if not set.
109+
*
110+
* @return the export deadline.
111+
* @since 0.22
112+
*/
113+
public abstract Duration getDeadline();
114+
115+
/**
116+
* Returns the {@link MetricServiceStub} to be used to make calls to Stackdriver Monitoring v3
117+
* APIs. This is for for advanced usage.
118+
*
119+
* @return the {@code MetricServiceStub}.
120+
* @since 0.22
121+
*/
122+
@Nullable
123+
public abstract MetricServiceStub getMetricServiceStub();
124+
102125
/**
103126
* Returns a new {@link Builder}.
104127
*
@@ -110,7 +133,8 @@ public static Builder builder() {
110133
.setProjectId(DEFAULT_PROJECT_ID)
111134
.setConstantLabels(DEFAULT_CONSTANT_LABELS)
112135
.setExportInterval(DEFAULT_INTERVAL)
113-
.setMonitoredResource(DEFAULT_RESOURCE);
136+
.setMonitoredResource(DEFAULT_RESOURCE)
137+
.setDeadline(DEFAULT_DEADLINE);
114138
}
115139

116140
/**
@@ -121,6 +145,8 @@ public static Builder builder() {
121145
@AutoValue.Builder
122146
public abstract static class Builder {
123147

148+
@VisibleForTesting static final Duration ZERO = Duration.fromMillis(0);
149+
124150
Builder() {}
125151

126152
/**
@@ -192,10 +218,34 @@ public abstract static class Builder {
192218
*/
193219
public abstract Builder setConstantLabels(Map<LabelKey, LabelValue> constantLabels);
194220

221+
/**
222+
* Sets the deadline for exporting to Stackdriver Monitoring backend.
223+
*
224+
* <p>If both {@code MetricServiceStub} and {@code Deadline} are set, {@code MetricServiceStub}
225+
* takes precedence and {@code Deadline} will not be respected.
226+
*
227+
* @param deadline the export deadline.
228+
* @return this
229+
* @since 0.22
230+
*/
231+
public abstract Builder setDeadline(Duration deadline);
232+
233+
/**
234+
* Sets the {@link MetricServiceStub} to be used to make calls to Stackdriver Monitoring v3
235+
* APIs. This is for for advanced usage.
236+
*
237+
* @param stub the {@code MetricServiceStub}.
238+
* @return this
239+
* @since 0.22
240+
*/
241+
public abstract Builder setMetricServiceStub(MetricServiceStub stub);
242+
195243
abstract String getProjectId();
196244

197245
abstract Map<LabelKey, LabelValue> getConstantLabels();
198246

247+
abstract Duration getDeadline();
248+
199249
abstract StackdriverStatsConfiguration autoBuild();
200250

201251
/**
@@ -216,6 +266,7 @@ public StackdriverStatsConfiguration build() {
216266
Preconditions.checkNotNull(constantLabel.getKey(), "constant label key");
217267
Preconditions.checkNotNull(constantLabel.getValue(), "constant label value");
218268
}
269+
Preconditions.checkArgument(getDeadline().compareTo(ZERO) > 0, "Deadline must be positive.");
219270
return autoBuild();
220271
}
221272
}

exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsExporter.java

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static com.google.common.base.Preconditions.checkNotNull;
2121
import static com.google.common.base.Preconditions.checkState;
2222
import static io.opencensus.exporter.stats.stackdriver.StackdriverExportUtils.DEFAULT_CONSTANT_LABELS;
23+
import static io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration.DEFAULT_DEADLINE;
2324
import static io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration.DEFAULT_PROJECT_ID;
2425
import static io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration.DEFAULT_RESOURCE;
2526

@@ -33,6 +34,7 @@
3334
import com.google.cloud.ServiceOptions;
3435
import com.google.cloud.monitoring.v3.MetricServiceClient;
3536
import com.google.cloud.monitoring.v3.MetricServiceSettings;
37+
import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
3638
import com.google.common.annotations.VisibleForTesting;
3739
import io.opencensus.common.Duration;
3840
import io.opencensus.common.OpenCensusLibraryInformation;
@@ -136,7 +138,14 @@ public static void createAndRegisterWithCredentialsAndProjectId(
136138
checkNotNull(projectId, "projectId");
137139
checkNotNull(exportInterval, "exportInterval");
138140
createInternal(
139-
credentials, projectId, exportInterval, DEFAULT_RESOURCE, null, DEFAULT_CONSTANT_LABELS);
141+
credentials,
142+
projectId,
143+
exportInterval,
144+
DEFAULT_RESOURCE,
145+
null,
146+
DEFAULT_CONSTANT_LABELS,
147+
DEFAULT_DEADLINE,
148+
null);
140149
}
141150

142151
/**
@@ -167,7 +176,14 @@ public static void createAndRegisterWithProjectId(String projectId, Duration exp
167176
checkNotNull(projectId, "projectId");
168177
checkNotNull(exportInterval, "exportInterval");
169178
createInternal(
170-
null, projectId, exportInterval, DEFAULT_RESOURCE, null, DEFAULT_CONSTANT_LABELS);
179+
null,
180+
projectId,
181+
exportInterval,
182+
DEFAULT_RESOURCE,
183+
null,
184+
DEFAULT_CONSTANT_LABELS,
185+
DEFAULT_DEADLINE,
186+
null);
171187
}
172188

173189
/**
@@ -206,7 +222,9 @@ public static void createAndRegister(StackdriverStatsConfiguration configuration
206222
configuration.getExportInterval(),
207223
configuration.getMonitoredResource(),
208224
configuration.getMetricNamePrefix(),
209-
configuration.getConstantLabels());
225+
configuration.getConstantLabels(),
226+
configuration.getDeadline(),
227+
configuration.getMetricServiceStub());
210228
}
211229

212230
/**
@@ -266,7 +284,14 @@ public static void createAndRegister(Duration exportInterval) throws IOException
266284
checkArgument(
267285
!DEFAULT_PROJECT_ID.isEmpty(), "Cannot find a project ID from application default.");
268286
createInternal(
269-
null, DEFAULT_PROJECT_ID, exportInterval, DEFAULT_RESOURCE, null, DEFAULT_CONSTANT_LABELS);
287+
null,
288+
DEFAULT_PROJECT_ID,
289+
exportInterval,
290+
DEFAULT_RESOURCE,
291+
null,
292+
DEFAULT_CONSTANT_LABELS,
293+
DEFAULT_DEADLINE,
294+
null);
270295
}
271296

272297
/**
@@ -296,7 +321,14 @@ public static void createAndRegisterWithProjectIdAndMonitoredResource(
296321
checkNotNull(exportInterval, "exportInterval");
297322
checkNotNull(monitoredResource, "monitoredResource");
298323
createInternal(
299-
null, projectId, exportInterval, monitoredResource, null, DEFAULT_CONSTANT_LABELS);
324+
null,
325+
projectId,
326+
exportInterval,
327+
monitoredResource,
328+
null,
329+
DEFAULT_CONSTANT_LABELS,
330+
DEFAULT_DEADLINE,
331+
null);
300332
}
301333

302334
/**
@@ -326,7 +358,14 @@ public static void createAndRegisterWithMonitoredResource(
326358
checkArgument(
327359
!DEFAULT_PROJECT_ID.isEmpty(), "Cannot find a project ID from application default.");
328360
createInternal(
329-
null, DEFAULT_PROJECT_ID, exportInterval, monitoredResource, null, DEFAULT_CONSTANT_LABELS);
361+
null,
362+
DEFAULT_PROJECT_ID,
363+
exportInterval,
364+
monitoredResource,
365+
null,
366+
DEFAULT_CONSTANT_LABELS,
367+
DEFAULT_DEADLINE,
368+
null);
330369
}
331370

332371
// Use createInternal() (instead of constructor) to enforce singleton.
@@ -336,14 +375,20 @@ private static void createInternal(
336375
Duration exportInterval,
337376
MonitoredResource monitoredResource,
338377
@Nullable String metricNamePrefix,
339-
Map<LabelKey, LabelValue> constantLabels)
378+
Map<LabelKey, LabelValue> constantLabels,
379+
Duration deadline,
380+
@Nullable MetricServiceStub stub)
340381
throws IOException {
341382
synchronized (monitor) {
342383
checkState(instance == null, "Stackdriver stats exporter is already created.");
384+
MetricServiceClient client =
385+
stub == null
386+
? createMetricServiceClient(credentials, deadline)
387+
: MetricServiceClient.create(stub);
343388
instance =
344389
new StackdriverStatsExporter(
345390
projectId,
346-
createMetricServiceClient(credentials),
391+
client,
347392
exportInterval,
348393
monitoredResource,
349394
metricNamePrefix,
@@ -354,8 +399,8 @@ private static void createInternal(
354399
// Initialize MetricServiceClient inside lock to avoid creating multiple clients.
355400
@GuardedBy("monitor")
356401
@VisibleForTesting
357-
static MetricServiceClient createMetricServiceClient(@Nullable Credentials credentials)
358-
throws IOException {
402+
static MetricServiceClient createMetricServiceClient(
403+
@Nullable Credentials credentials, Duration deadline) throws IOException {
359404
MetricServiceSettings.Builder settingsBuilder =
360405
MetricServiceSettings.newBuilder()
361406
.setTransportChannelProvider(
@@ -365,6 +410,13 @@ static MetricServiceClient createMetricServiceClient(@Nullable Credentials crede
365410
if (credentials != null) {
366411
settingsBuilder.setCredentialsProvider(FixedCredentialsProvider.create(credentials));
367412
}
413+
414+
org.threeten.bp.Duration stackdriverDuration =
415+
org.threeten.bp.Duration.ofMillis(deadline.toMillis());
416+
// We use createMetricDescriptor and createTimeSeries APIs in this exporter.
417+
settingsBuilder.createMetricDescriptorSettings().setSimpleTimeoutNoRetries(stackdriverDuration);
418+
settingsBuilder.createTimeSeriesSettings().setSimpleTimeoutNoRetries(stackdriverDuration);
419+
368420
return MetricServiceClient.create(settingsBuilder.build());
369421
}
370422

exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsConfigurationTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818

1919
import static com.google.common.truth.Truth.assertThat;
2020
import static io.opencensus.exporter.stats.stackdriver.StackdriverExportUtils.DEFAULT_CONSTANT_LABELS;
21+
import static io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration.DEFAULT_DEADLINE;
2122
import static io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration.DEFAULT_INTERVAL;
2223

2324
import com.google.api.MonitoredResource;
2425
import com.google.auth.Credentials;
2526
import com.google.auth.oauth2.AccessToken;
2627
import com.google.auth.oauth2.GoogleCredentials;
2728
import com.google.cloud.ServiceOptions;
29+
import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
2830
import io.opencensus.common.Duration;
2931
import io.opencensus.metrics.LabelKey;
3032
import io.opencensus.metrics.LabelValue;
@@ -36,6 +38,8 @@
3638
import org.junit.rules.ExpectedException;
3739
import org.junit.runner.RunWith;
3840
import org.junit.runners.JUnit4;
41+
import org.mockito.Mock;
42+
import org.mockito.Mockito;
3943

4044
/** Unit tests for {@link StackdriverStatsConfiguration}. */
4145
@RunWith(JUnit4.class)
@@ -45,13 +49,16 @@ public class StackdriverStatsConfigurationTest {
4549
GoogleCredentials.newBuilder().setAccessToken(new AccessToken("fake", new Date(100))).build();
4650
private static final String PROJECT_ID = "project";
4751
private static final Duration DURATION = Duration.create(10, 0);
52+
private static final Duration NEG_ONE_SECOND = Duration.create(-1, 0);
4853
private static final MonitoredResource RESOURCE =
4954
MonitoredResource.newBuilder()
5055
.setType("gce-instance")
5156
.putLabels("instance-id", "instance")
5257
.build();
5358
private static final String CUSTOM_PREFIX = "myorg";
5459

60+
@Mock private final MetricServiceStub mockStub = Mockito.mock(MetricServiceStub.class);
61+
5562
@Rule public final ExpectedException thrown = ExpectedException.none();
5663

5764
@Test
@@ -69,13 +76,17 @@ public void testBuild() {
6976
.setMonitoredResource(RESOURCE)
7077
.setMetricNamePrefix(CUSTOM_PREFIX)
7178
.setConstantLabels(Collections.<LabelKey, LabelValue>emptyMap())
79+
.setDeadline(DURATION)
80+
.setMetricServiceStub(mockStub)
7281
.build();
7382
assertThat(configuration.getCredentials()).isEqualTo(FAKE_CREDENTIALS);
7483
assertThat(configuration.getProjectId()).isEqualTo(PROJECT_ID);
7584
assertThat(configuration.getExportInterval()).isEqualTo(DURATION);
7685
assertThat(configuration.getMonitoredResource()).isEqualTo(RESOURCE);
7786
assertThat(configuration.getMetricNamePrefix()).isEqualTo(CUSTOM_PREFIX);
7887
assertThat(configuration.getConstantLabels()).isEmpty();
88+
assertThat(configuration.getDeadline()).isEqualTo(DURATION);
89+
assertThat(configuration.getMetricServiceStub()).isEqualTo(mockStub);
7990
}
8091

8192
@Test
@@ -93,6 +104,8 @@ public void testBuild_Default() {
93104
assertThat(configuration.getMonitoredResource()).isNotNull();
94105
assertThat(configuration.getMetricNamePrefix()).isNull();
95106
assertThat(configuration.getConstantLabels()).isEqualTo(DEFAULT_CONSTANT_LABELS);
107+
assertThat(configuration.getDeadline()).isEqualTo(DEFAULT_DEADLINE);
108+
assertThat(configuration.getMetricServiceStub()).isNull();
96109
}
97110

98111
@Test
@@ -183,4 +196,22 @@ public void allowNullMetricPrefix() {
183196
.build();
184197
assertThat(configuration.getMetricNamePrefix()).isNull();
185198
}
199+
200+
@Test
201+
public void disallowZeroDuration() {
202+
StackdriverStatsConfiguration.Builder builder =
203+
StackdriverStatsConfiguration.builder().setProjectId("test");
204+
builder.setDeadline(StackdriverStatsConfiguration.Builder.ZERO);
205+
thrown.expect(IllegalArgumentException.class);
206+
builder.build();
207+
}
208+
209+
@Test
210+
public void disallowNegativeDuration() {
211+
StackdriverStatsConfiguration.Builder builder =
212+
StackdriverStatsConfiguration.builder().setProjectId("test");
213+
builder.setDeadline(NEG_ONE_SECOND);
214+
thrown.expect(IllegalArgumentException.class);
215+
builder.build();
216+
}
186217
}

exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsExporterTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.opencensus.exporter.stats.stackdriver;
1818

1919
import static com.google.common.truth.Truth.assertThat;
20+
import static io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration.DEFAULT_DEADLINE;
2021

2122
import com.google.api.gax.core.GoogleCredentialsProvider;
2223
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
@@ -130,7 +131,8 @@ public void createWithNullMonitoredResource() throws IOException {
130131
public void createMetricServiceClient() throws IOException {
131132
MetricServiceClient client;
132133
synchronized (StackdriverStatsExporter.monitor) {
133-
client = StackdriverStatsExporter.createMetricServiceClient(FAKE_CREDENTIALS);
134+
client =
135+
StackdriverStatsExporter.createMetricServiceClient(FAKE_CREDENTIALS, DEFAULT_DEADLINE);
134136
}
135137
assertThat(client.getSettings().getCredentialsProvider().getCredentials())
136138
.isEqualTo(FAKE_CREDENTIALS);
@@ -145,7 +147,7 @@ public void createMetricServiceClient_WithoutCredentials() {
145147
try {
146148
MetricServiceClient client;
147149
synchronized (StackdriverStatsExporter.monitor) {
148-
client = StackdriverStatsExporter.createMetricServiceClient(null);
150+
client = StackdriverStatsExporter.createMetricServiceClient(null, DEFAULT_DEADLINE);
149151
}
150152
assertThat(client.getSettings().getCredentialsProvider())
151153
.isInstanceOf(GoogleCredentialsProvider.class);

0 commit comments

Comments
 (0)