-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add OpenTelemetry Traces to GRPC #2783
Changes from all commits
84722d1
d8f263d
e1e37ae
9ed9687
63157f8
171fdb5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,12 +16,7 @@ | |
|
||
package com.google.cloud.storage; | ||
|
||
import com.google.cloud.storage.TransportCompatibility.Transport; | ||
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.CrossRun; | ||
import com.google.cloud.storage.it.runner.annotations.Inject; | ||
import com.google.cloud.storage.it.runner.registry.Generator; | ||
import com.google.cloud.storage.testing.RemoteStorageHelper; | ||
import io.opentelemetry.api.common.AttributeKey; | ||
import io.opentelemetry.sdk.OpenTelemetrySdk; | ||
import io.opentelemetry.sdk.common.CompletableResultCode; | ||
|
@@ -33,16 +28,11 @@ | |
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.UUID; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
@RunWith(StorageITRunner.class) | ||
@CrossRun( | ||
backends = {Backend.PROD}, | ||
transports = {Transport.HTTP}) | ||
public final class ITOpenTelemetryTest { | ||
@Inject public Generator generator; | ||
|
||
@Test | ||
public void checkInstrumentation() { | ||
|
@@ -58,29 +48,80 @@ public void checkInstrumentation() { | |
StorageOptions storageOptions = | ||
StorageOptions.http().setOpenTelemetrySdk(openTelemetrySdk).build(); | ||
Storage storage = storageOptions.getService(); | ||
storage.create(BucketInfo.of(generator.randomBucketName())); | ||
String bucket = randomBucketName(); | ||
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")); | ||
|
||
// Cleanup | ||
RemoteStorageHelper.forceDelete(storage, bucket); | ||
} | ||
|
||
@Test | ||
public void noOpDoesNothing() { | ||
StorageOptions storageOptions = StorageOptions.http().build(); | ||
public void checkInstrumentationGrpc() { | ||
SpanExporter exporter = new TestExporter(); | ||
|
||
OpenTelemetrySdk openTelemetrySdk = | ||
OpenTelemetrySdk.builder() | ||
.setTracerProvider( | ||
SdkTracerProvider.builder() | ||
.addSpanProcessor(SimpleSpanProcessor.create(exporter)) | ||
.build()) | ||
.build(); | ||
StorageOptions storageOptions = | ||
StorageOptions.grpc().setOpenTelemetrySdk(openTelemetrySdk).build(); | ||
Storage storage = storageOptions.getService(); | ||
storage.create(BucketInfo.of(generator.randomBucketName())); | ||
String bucket = randomBucketName(); | ||
storage.create(BucketInfo.of(bucket)); | ||
TestExporter testExported = (TestExporter) exporter; | ||
SpanData spanData = testExported.getExportedSpans().get(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you plan on testing which spans are collected per operation in addition to Span attributes? I think this would be more useful for Upload and Download ops. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if i understand this question. what do you mean by which spans are collected There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh i meant; let's say you're uploading a large object to GCS. I would assume there's a span for CreateResumableUpload, then span for each WriteObject request. Wondering if there's a way to test that using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah I see, I haven't expanded this for that case yet but yeah we would want to test each span is generated. Maybe we could check for the size to make sure if we expect 3 writeObjectRequests we would have 3 spans There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a good start to assert span count; and expand from there. |
||
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("grpc", getAttributeValue(spanData, "rpc.system")); | ||
|
||
// Cleanup | ||
RemoteStorageHelper.forceDelete(storage, bucket); | ||
} | ||
|
||
@Test | ||
public void noOpDoesNothing() { | ||
String httpBucket = randomBucketName(); | ||
String grpcBucket = randomBucketName(); | ||
// NoOp for HTTP | ||
StorageOptions storageOptionsHttp = StorageOptions.http().build(); | ||
Storage storageHttp = storageOptionsHttp.getService(); | ||
storageHttp.create(BucketInfo.of(httpBucket)); | ||
|
||
// NoOp for Grpc | ||
StorageOptions storageOptionsGrpc = StorageOptions.grpc().build(); | ||
Storage storageGrpc = storageOptionsGrpc.getService(); | ||
storageGrpc.create(BucketInfo.of(grpcBucket)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is no-op testing and checking? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just checking to make sure that it still runs without issue and does nothing. basically just that it doesnt error out. |
||
|
||
// cleanup | ||
RemoteStorageHelper.forceDelete(storageHttp, httpBucket); | ||
RemoteStorageHelper.forceDelete(storageGrpc, grpcBucket); | ||
} | ||
|
||
private String getAttributeValue(SpanData spanData, String key) { | ||
return spanData.getAttributes().get(AttributeKey.stringKey(key)).toString(); | ||
} | ||
|
||
public String randomBucketName() { | ||
return "java-storage-grpc-rand-" + UUID.randomUUID(); | ||
} | ||
} | ||
|
||
class TestExporter implements SpanExporter { | ||
|
||
public final List<SpanData> exportedSpans = Collections.synchronizedList(new ArrayList<>()); | ||
|
||
@Override | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Kokoro need to be updated internally to watch this branch as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ill double check!