From d9fd4bdc526ba9eb86e59596746a967b93daf07a Mon Sep 17 00:00:00 2001 From: Sydney Munro <97561403+sydney-munro@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:35:06 -0700 Subject: [PATCH] feat: Add CreateBlob for HTTP (#2803) --- .../cloud/storage/spi/v1/HttpStorageRpc.java | 8 +- .../storage/ITHttpOpenTelemetryTest.java | 103 ++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 google-cloud-storage/src/test/java/com/google/cloud/storage/ITHttpOpenTelemetryTest.java diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index fdfec4619..e244903d0 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -360,7 +360,7 @@ private Span startSpan(String spanName) { @Override public Bucket create(Bucket bucket, Map options) { - OpenTelemetryTraceUtil.Span otelSpan = openTelemetryTraceUtil.startSpan("create(Bucket,Map)"); + OpenTelemetryTraceUtil.Span otelSpan = openTelemetryTraceUtil.startSpan("create"); Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_CREATE_BUCKET); Scope scope = tracer.withSpan(span); try (OpenTelemetryTraceUtil.Scope unused = otelSpan.makeCurrent()) { @@ -388,9 +388,10 @@ public Bucket create(Bucket bucket, Map options) { @Override public StorageObject create( StorageObject storageObject, final InputStream content, Map options) { + OpenTelemetryTraceUtil.Span otelSpan = openTelemetryTraceUtil.startSpan("create"); Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_CREATE_OBJECT); Scope scope = tracer.withSpan(span); - try { + try (OpenTelemetryTraceUtil.Scope unused = otelSpan.makeCurrent()) { Storage.Objects.Insert insert = storage .objects() @@ -415,9 +416,12 @@ public StorageObject create( .setKmsKeyName(Option.KMS_KEY_NAME.getString(options)) .execute(); } catch (IOException ex) { + otelSpan.recordException(ex); + otelSpan.setStatus(StatusCode.ERROR, ex.getClass().getSimpleName()); span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage())); throw translate(ex); } finally { + otelSpan.end(); scope.close(); span.end(HttpStorageRpcSpans.END_SPAN_OPTIONS); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITHttpOpenTelemetryTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITHttpOpenTelemetryTest.java new file mode 100644 index 000000000..c4b43fd7a --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITHttpOpenTelemetryTest.java @@ -0,0 +1,103 @@ +/* + * 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.storage; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.cloud.NoCredentials; +import com.google.cloud.storage.it.runner.StorageITRunner; +import com.google.cloud.storage.it.runner.annotations.Backend; +import com.google.cloud.storage.it.runner.annotations.Inject; +import com.google.cloud.storage.it.runner.annotations.SingleBackend; +import com.google.cloud.storage.it.runner.registry.Generator; +import com.google.cloud.storage.it.runner.registry.TestBench; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import java.util.List; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(StorageITRunner.class) +@SingleBackend(Backend.TEST_BENCH) +public class ITHttpOpenTelemetryTest { + @Inject public TestBench testBench; + private StorageOptions options; + private SpanExporter exporter; + private Storage storage; + @Inject public Generator generator; + @Inject public BucketInfo testBucket; + + @Before + public void setUp() { + exporter = new TestExporter(); + OpenTelemetrySdk openTelemetrySdk = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.create(exporter)) + .build()) + .build(); + options = + StorageOptions.http() + .setHost(testBench.getBaseUri()) + .setProjectId("projectId") + .setCredentials(NoCredentials.getInstance()) + .setOpenTelemetrySdk(openTelemetrySdk) + .build(); + storage = options.getService(); + } + + @Test + public void runCreateBucket() { + String bucket = "random-bucket"; + storage.create(BucketInfo.of(bucket)); + TestExporter testExported = (TestExporter) exporter; + SpanData spanData = testExported.getExportedSpans().get(0); + Assert.assertEquals("Storage", getAttributeValue(spanData, "gcp.client.service")); + Assert.assertEquals("googleapis/java-storage", getAttributeValue(spanData, "gcp.client.repo")); + Assert.assertEquals( + "com.google.cloud.google-cloud-storage", + getAttributeValue(spanData, "gcp.client.artifact")); + Assert.assertEquals("http", getAttributeValue(spanData, "rpc.system")); + } + + @Test + public void runCreateBlob() { + byte[] content = "Hello, World!".getBytes(UTF_8); + BlobId toCreate = BlobId.of(testBucket.getName(), generator.randomObjectName()); + storage.create(BlobInfo.newBuilder(toCreate).build(), content); + TestExporter testExported = (TestExporter) exporter; + List spanData = testExported.getExportedSpans(); + for (SpanData span : spanData) { + Assert.assertEquals("Storage", getAttributeValue(span, "gcp.client.service")); + Assert.assertEquals("googleapis/java-storage", getAttributeValue(span, "gcp.client.repo")); + Assert.assertEquals( + "com.google.cloud.google-cloud-storage", getAttributeValue(span, "gcp.client.artifact")); + Assert.assertEquals("http", getAttributeValue(span, "rpc.system")); + } + } + + private String getAttributeValue(SpanData spanData, String key) { + return spanData.getAttributes().get(AttributeKey.stringKey(key)).toString(); + } +}