From 8163bb4e3ec97df73331ea472f6babfcdf868809 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Tue, 16 Jan 2024 15:11:43 -0800 Subject: [PATCH 1/2] feat: Add FirestoreOpenTelemetryOptions to FirestoreOptions. --- google-cloud-firestore/pom.xml | 8 +- .../FirestoreOpenTelemetryOptions.java | 97 ++++++++++++++++++ .../cloud/firestore/FirestoreOptions.java | 33 +++++++ .../firestore/OpenTelemetryOptionsTest.java | 99 +++++++++++++++++++ 4 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java create mode 100644 google-cloud-firestore/src/test/java/com/google/cloud/firestore/OpenTelemetryOptionsTest.java diff --git a/google-cloud-firestore/pom.xml b/google-cloud-firestore/pom.xml index 49617e17b..1cc16ad72 100644 --- a/google-cloud-firestore/pom.xml +++ b/google-cloud-firestore/pom.xml @@ -112,7 +112,13 @@ com.google.protobuf protobuf-java-util - + + + io.opentelemetry + opentelemetry-api + 1.29.0 + + diff --git a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java new file mode 100644 index 000000000..58c06a29f --- /dev/null +++ b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java @@ -0,0 +1,97 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.firestore; + +import io.opentelemetry.api.OpenTelemetry; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class FirestoreOpenTelemetryOptions { + private final boolean enabled; + + @Nullable private final OpenTelemetry openTelemetry; + + FirestoreOpenTelemetryOptions(Builder builder) { + this.enabled = builder.enabled; + this.openTelemetry = builder.openTelemetry; + } + + public boolean getEnabled() { + return enabled; + } + + public OpenTelemetry getOpenTelemetry() { + return openTelemetry; + } + + @Nonnull + public FirestoreOpenTelemetryOptions.Builder toBuilder() { + return new FirestoreOpenTelemetryOptions.Builder(this); + } + + @Nonnull + public static FirestoreOpenTelemetryOptions.Builder newBuilder() { + return new FirestoreOpenTelemetryOptions.Builder(); + } + + public static class Builder { + + private boolean enabled; + + @Nullable private OpenTelemetry openTelemetry; + + private Builder() { + enabled = false; + openTelemetry = null; + } + + private Builder(FirestoreOpenTelemetryOptions options) { + this.enabled = options.enabled; + this.openTelemetry = options.openTelemetry; + } + + @Nonnull + public FirestoreOpenTelemetryOptions build() { + return new FirestoreOpenTelemetryOptions(this); + } + + /** + * Sets whether tracing should be enabled. + * + * @param enable Whether tracing should be enabled. + */ + @Nonnull + public FirestoreOpenTelemetryOptions.Builder setTracingEnabled(boolean enable) { + this.enabled = enable; + return this; + } + + /** + * Sets the {@link OpenTelemetry} to use with this Firestore instance. If telemetry collection + * is enabled, but an `OpenTelemetry` is not provided, the Firestore SDK will attempt to use the + * `GlobalOpenTelemetry`. + * + * @param openTelemetry The OpenTelemetry that should be used by this Firestore instance. + */ + @Nonnull + public FirestoreOpenTelemetryOptions.Builder setOpenTelemetry( + @Nonnull OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + return this; + } + } +} diff --git a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java index 47de09d39..433f0eeb7 100644 --- a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java +++ b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java @@ -16,6 +16,7 @@ package com.google.cloud.firestore; +import com.google.api.core.BetaApi; import com.google.api.core.InternalApi; import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.FixedCredentialsProvider; @@ -60,6 +61,7 @@ public final class FirestoreOptions extends ServiceOptions { @Nullable private String databaseId = null; @Nullable private TransportChannelProvider channelProvider = null; @Nullable private CredentialsProvider credentialsProvider = null; @Nullable private String emulatorHost = null; + @Nullable private FirestoreOpenTelemetryOptions openTelemetryOptions = null; private Builder() {} @@ -133,6 +142,7 @@ private Builder(FirestoreOptions options) { this.channelProvider = options.channelProvider; this.credentialsProvider = options.credentialsProvider; this.emulatorHost = options.emulatorHost; + this.openTelemetryOptions = options.openTelemetryOptions; } /** @@ -201,6 +211,19 @@ public Builder setDatabaseId(@Nonnull String databaseId) { return this; } + /** + * Sets the {@link FirestoreOpenTelemetryOptions} to be used for this Firestore instance. + * + * @param openTelemetryOptions The `FirestoreOpenTelemetryOptions` to use. + */ + @BetaApi + @Nonnull + public Builder setOpenTelemetryOptions( + @Nonnull FirestoreOpenTelemetryOptions openTelemetryOptions) { + this.openTelemetryOptions = openTelemetryOptions; + return this; + } + @Override @Nonnull public FirestoreOptions build() { @@ -212,6 +235,10 @@ public FirestoreOptions build() { } } + if (this.openTelemetryOptions == null) { + this.setOpenTelemetryOptions(FirestoreOpenTelemetryOptions.newBuilder().build()); + } + // Override credentials and channel provider if we are using the emulator. if (emulatorHost == null) { emulatorHost = System.getenv(FIRESTORE_EMULATOR_SYSTEM_VARIABLE); @@ -278,6 +305,12 @@ public void refresh() {} protected FirestoreOptions(Builder builder) { super(FirestoreFactory.class, FirestoreRpcFactory.class, builder, new FirestoreDefaults()); + if (builder.openTelemetryOptions == null) { + this.openTelemetryOptions = FirestoreOpenTelemetryOptions.newBuilder().build(); + } else { + this.openTelemetryOptions = builder.openTelemetryOptions; + } + this.databaseId = builder.databaseId != null ? builder.databaseId diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/OpenTelemetryOptionsTest.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/OpenTelemetryOptionsTest.java new file mode 100644 index 000000000..42e69409c --- /dev/null +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/OpenTelemetryOptionsTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.firestore; + +import static com.google.common.truth.Truth.assertThat; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import javax.annotation.Nullable; +import org.junit.*; + +public class OpenTelemetryOptionsTest { + @Nullable private Firestore firestore; + + @Before + public void setUp() { + GlobalOpenTelemetry.resetForTest(); + } + + @After + public void tearDown() { + if (firestore != null) { + firestore.shutdown(); + firestore = null; + } + } + + FirestoreOptions.Builder getBaseOptions() { + return FirestoreOptions.newBuilder().setProjectId("test-project").setDatabaseId("(default)"); + } + + @Test + public void defaultOptionsDisablesTelemetryCollection() { + FirestoreOptions firestoreOptions = getBaseOptions().build(); + firestore = firestoreOptions.getService(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getEnabled()).isFalse(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getOpenTelemetry()).isNull(); + } + + @Test + public void canEnableTelemetryCollectionWithoutOpenTelemetryInstance() { + FirestoreOptions firestoreOptions = + getBaseOptions() + .setOpenTelemetryOptions( + FirestoreOpenTelemetryOptions.newBuilder().setTracingEnabled(true).build()) + .build(); + firestore = firestoreOptions.getService(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getEnabled()).isTrue(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getOpenTelemetry()).isNull(); + } + + @Test + public void canEnableTelemetryCollectionWithOpenTelemetryInstance() { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + FirestoreOptions firestoreOptions = + getBaseOptions() + .setOpenTelemetryOptions( + FirestoreOpenTelemetryOptions.newBuilder() + .setTracingEnabled(true) + .setOpenTelemetry(openTelemetry) + .build()) + .build(); + firestore = firestoreOptions.getService(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getEnabled()).isTrue(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getOpenTelemetry()) + .isEqualTo(openTelemetry); + } + + @Test + public void canDisableTelemetryCollectionWhileOpenTelemetryInstanceIsNotNull() { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + FirestoreOptions firestoreOptions = + getBaseOptions() + .setOpenTelemetryOptions( + FirestoreOpenTelemetryOptions.newBuilder() + .setTracingEnabled(false) + .setOpenTelemetry(openTelemetry) + .build()) + .build(); + firestore = firestoreOptions.getService(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getEnabled()).isFalse(); + assertThat(firestore.getOptions().getOpenTelemetryOptions().getOpenTelemetry()) + .isEqualTo(openTelemetry); + } +} From 5426257a6e45aaf58fc832ab580fa1b88b1ae797 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Wed, 28 Feb 2024 14:54:24 -0800 Subject: [PATCH 2/2] Address code review feedback. --- .../FirestoreOpenTelemetryOptions.java | 2 +- .../cloud/firestore/FirestoreOptions.java | 17 +++++++---------- .../firestore/OpenTelemetryOptionsTest.java | 4 +++- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java index 58c06a29f..b3d5bacf0 100644 --- a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java +++ b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOpenTelemetryOptions.java @@ -23,7 +23,7 @@ public class FirestoreOpenTelemetryOptions { private final boolean enabled; - @Nullable private final OpenTelemetry openTelemetry; + private final @Nullable OpenTelemetry openTelemetry; FirestoreOpenTelemetryOptions(Builder builder) { this.enabled = builder.enabled; diff --git a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java index 433f0eeb7..3cb67e5ec 100644 --- a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java +++ b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FirestoreOptions.java @@ -61,7 +61,7 @@ public final class FirestoreOptions extends ServiceOptions