From 0a1eff249ab17c8fe5b83ae4d9467494634a1308 Mon Sep 17 00:00:00 2001 From: Mikhail Berezovskiy Date: Wed, 29 Jan 2025 21:11:57 -0800 Subject: [PATCH 1/4] wip --- gradle/verification-metadata.xml | 40 +++++++++++++++++ modules/repository-gcs/build.gradle | 7 +++ .../repositories/gcs/GcpTracer.java | 43 +++++++++++++++++++ .../gcs/GoogleCloudStorageBlobContainer.java | 20 ++++++++- .../gcs/GoogleCloudStorageService.java | 9 ++++ 5 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 2c46c4642e56e..c95aa33ab631c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -904,6 +904,11 @@ + + + + + @@ -1551,6 +1556,21 @@ + + + + + + + + + + + + + + + @@ -1561,6 +1581,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/modules/repository-gcs/build.gradle b/modules/repository-gcs/build.gradle index d23a0f4a7e44d..3083035410cb4 100644 --- a/modules/repository-gcs/build.gradle +++ b/modules/repository-gcs/build.gradle @@ -50,7 +50,14 @@ dependencies { api 'com.google.api:gax-httpjson:0.105.1' api 'io.grpc:grpc-context:1.49.2' api 'io.opencensus:opencensus-api:0.31.1' + api 'io.opencensus:opencensus-impl-core:0.31.1' + api 'io.opencensus:opencensus-impl-lite:0.31.1' + api 'io.opencensus:opencensus-contrib-http-util:0.31.1' +// api 'io.opentelemetry:opentelemetry-api:1.31.0' +// api 'io.opentelemetry:opentelemetry-context:1.41.0' +// api 'io.opentelemetry:opentelemetry-opencensus-shim:1.31.0-alpha' +// api 'io.opentelemetry:opentelemetry-extension-trace-propagators:1.41.0' api 'com.google.apis:google-api-services-storage:v1-rev20220705-2.0.0' testImplementation "org.apache.httpcomponents:httpclient:${versions.httpclient}" diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java new file mode 100644 index 0000000000000..caa0e2b0f20d4 --- /dev/null +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.repositories.gcs; + +import io.opencensus.trace.Tracing; +import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.SpanData; +import io.opencensus.trace.export.SpanExporter; +import io.opencensus.trace.samplers.Samplers; + +import java.util.Collection; + +public class GcpTracer extends SpanExporter.Handler { + + public static void createAndRegister() { + Tracing.getExportComponent().getSpanExporter().registerHandler("gcp-tracer", new GcpTracer()); + TraceConfig traceConfig = Tracing.getTraceConfig(); + traceConfig.updateActiveTraceParams(traceConfig.getActiveTraceParams().toBuilder().setSampler(Samplers.alwaysSample()).build()); + } + + @Override + public void export(Collection spanDataList) { + for (var sd : spanDataList) { + var parent = sd.getParentSpanId(); + + System.out.printf( + "trace=%s parent=%s span=%s name=%s\n", + sd.getContext().getTraceId().toLowerBase16(), + parent == null ? "null" : parent.toLowerBase16(), + sd.getContext().getSpanId().toLowerBase16(), + sd.getName() + ); + } + + } +} diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java index 3ed492881afa9..0ee60946d703d 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java @@ -9,6 +9,8 @@ package org.elasticsearch.repositories.gcs; +import io.opencensus.trace.Tracing; + import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.blobstore.BlobContainer; import org.elasticsearch.common.blobstore.BlobPath; @@ -76,12 +78,21 @@ public InputStream readBlob(OperationPurpose purpose, final String blobName, fin @Override public void writeBlob(OperationPurpose purpose, String blobName, InputStream inputStream, long blobSize, boolean failIfAlreadyExists) throws IOException { - blobStore.writeBlob(buildKey(blobName), inputStream, blobSize, failIfAlreadyExists); + withSpan(purpose, ()-> blobStore.writeBlob(buildKey(blobName), inputStream, blobSize, failIfAlreadyExists)); } @Override public void writeBlob(OperationPurpose purpose, String blobName, BytesReference bytes, boolean failIfAlreadyExists) throws IOException { - blobStore.writeBlob(buildKey(blobName), bytes, failIfAlreadyExists); + withSpan(purpose, () -> blobStore.writeBlob(buildKey(blobName), bytes, failIfAlreadyExists)); + } + + private void withSpan(OperationPurpose purpose, IOThrowing runnable) throws IOException { + var span = Tracing.getTracer().spanBuilder(purpose.name()).startSpan(); + try (var ignored = Tracing.getTracer().withSpan(span)) { + runnable.run(); + } finally { + span.end(); + } } @Override @@ -106,6 +117,11 @@ public void writeBlobAtomic( writeBlob(purpose, blobName, inputStream, blobSize, failIfAlreadyExists); } + interface IOThrowing { + void run() throws IOException; + } + + @Override public void writeBlobAtomic(OperationPurpose purpose, String blobName, BytesReference bytes, boolean failIfAlreadyExists) throws IOException { diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java index 6a4eeeeabbb6f..66e27fafc29a9 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java @@ -14,6 +14,7 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.util.SecurityUtils; +import com.google.api.gax.tracing.OpencensusTracer; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.ServiceOptions; @@ -22,6 +23,9 @@ import com.google.cloud.storage.StorageOptions; import com.google.cloud.storage.StorageRetryStrategy; +import io.opencensus.contrib.http.util.HttpViews; +import io.opencensus.trace.Tracer; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.common.Strings; @@ -47,6 +51,10 @@ public class GoogleCloudStorageService { + public GoogleCloudStorageService() { + GcpTracer.createAndRegister(); + } + private static final Logger logger = LogManager.getLogger(GoogleCloudStorageService.class); private volatile Map clientSettings = emptyMap(); @@ -85,6 +93,7 @@ public synchronized void refreshAndClearCache(Map Date: Wed, 29 Jan 2025 23:35:27 -0800 Subject: [PATCH 2/4] cleanup --- gradle/verification-metadata.xml | 30 ----------------------------- modules/repository-gcs/build.gradle | 4 ---- 2 files changed, 34 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c95aa33ab631c..db9b789c1179f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -904,11 +904,6 @@ - - - - - @@ -1556,11 +1551,6 @@ - - - - - @@ -1581,26 +1571,6 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/modules/repository-gcs/build.gradle b/modules/repository-gcs/build.gradle index 3083035410cb4..39e1b9efcaa23 100644 --- a/modules/repository-gcs/build.gradle +++ b/modules/repository-gcs/build.gradle @@ -54,10 +54,6 @@ dependencies { api 'io.opencensus:opencensus-impl-lite:0.31.1' api 'io.opencensus:opencensus-contrib-http-util:0.31.1' -// api 'io.opentelemetry:opentelemetry-api:1.31.0' -// api 'io.opentelemetry:opentelemetry-context:1.41.0' -// api 'io.opentelemetry:opentelemetry-opencensus-shim:1.31.0-alpha' -// api 'io.opentelemetry:opentelemetry-extension-trace-propagators:1.41.0' api 'com.google.apis:google-api-services-storage:v1-rev20220705-2.0.0' testImplementation "org.apache.httpcomponents:httpclient:${versions.httpclient}" From 33f16235ebc0e21cde2dcc7e0cab8b3720ff8077 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 30 Jan 2025 07:42:09 +0000 Subject: [PATCH 3/4] [CI] Auto commit changes from spotless --- .../repositories/gcs/GoogleCloudStorageBlobContainer.java | 3 +-- .../repositories/gcs/GoogleCloudStorageService.java | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java index 0ee60946d703d..0c36ca5bddd67 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java @@ -78,7 +78,7 @@ public InputStream readBlob(OperationPurpose purpose, final String blobName, fin @Override public void writeBlob(OperationPurpose purpose, String blobName, InputStream inputStream, long blobSize, boolean failIfAlreadyExists) throws IOException { - withSpan(purpose, ()-> blobStore.writeBlob(buildKey(blobName), inputStream, blobSize, failIfAlreadyExists)); + withSpan(purpose, () -> blobStore.writeBlob(buildKey(blobName), inputStream, blobSize, failIfAlreadyExists)); } @Override @@ -121,7 +121,6 @@ interface IOThrowing { void run() throws IOException; } - @Override public void writeBlobAtomic(OperationPurpose purpose, String blobName, BytesReference bytes, boolean failIfAlreadyExists) throws IOException { diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java index 66e27fafc29a9..ec821ed5e1e42 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java @@ -14,7 +14,6 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.util.SecurityUtils; -import com.google.api.gax.tracing.OpencensusTracer; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.ServiceOptions; @@ -23,9 +22,6 @@ import com.google.cloud.storage.StorageOptions; import com.google.cloud.storage.StorageRetryStrategy; -import io.opencensus.contrib.http.util.HttpViews; -import io.opencensus.trace.Tracer; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.common.Strings; From 8b798bd3ecb171e61a0e12ad1b864e661fadb402 Mon Sep 17 00:00:00 2001 From: Mikhail Berezovskiy Date: Thu, 30 Jan 2025 14:25:01 -0800 Subject: [PATCH 4/4] shutdown and pprint --- .../repositories/gcs/GcpTracer.java | 40 ++++++++++++++----- .../gcs/GoogleCloudStorageBlobContainer.java | 3 +- .../gcs/GoogleCloudStoragePlugin.java | 6 +++ .../gcs/GoogleCloudStorageService.java | 8 ++-- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java index caa0e2b0f20d4..f9165d500be85 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GcpTracer.java @@ -15,29 +15,47 @@ import io.opencensus.trace.export.SpanExporter; import io.opencensus.trace.samplers.Samplers; +import org.elasticsearch.logging.LogManager; +import org.elasticsearch.logging.Logger; + +import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; public class GcpTracer extends SpanExporter.Handler { + private static final Logger logger = LogManager.getLogger(GcpTracer.class); + public static void createAndRegister() { Tracing.getExportComponent().getSpanExporter().registerHandler("gcp-tracer", new GcpTracer()); TraceConfig traceConfig = Tracing.getTraceConfig(); traceConfig.updateActiveTraceParams(traceConfig.getActiveTraceParams().toBuilder().setSampler(Samplers.alwaysSample()).build()); } + public static void shutdown() { + Tracing.getExportComponent().shutdown(); + } + + static String parentSpanId(SpanData sd) { + var ps = sd.getParentSpanId(); + return ps == null ? ".null" : ps.toLowerBase16(); + } + + static String traceId(SpanData sd) { + return sd.getContext().getTraceId().toLowerBase16(); + } + @Override public void export(Collection spanDataList) { - for (var sd : spanDataList) { - var parent = sd.getParentSpanId(); - - System.out.printf( - "trace=%s parent=%s span=%s name=%s\n", - sd.getContext().getTraceId().toLowerBase16(), - parent == null ? "null" : parent.toLowerBase16(), - sd.getContext().getSpanId().toLowerBase16(), - sd.getName() - ); + var out = new ArrayList<>(spanDataList); + out.sort(Comparator.comparing(GcpTracer::traceId).thenComparing(GcpTracer::parentSpanId)); + var sb = new StringBuilder(); + var f = "%32s\t%16s\t%16s\t%s\n"; + sb.append('\n'); + sb.append(String.format(f, "trace", "parent", "span", "name")); + for (var sd : out) { + sb.append(String.format(f, traceId(sd), parentSpanId(sd), sd.getContext().getSpanId().toLowerBase16(), sd.getName())); } - + logger.info(sb.toString()); } } diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java index 0ee60946d703d..0c36ca5bddd67 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainer.java @@ -78,7 +78,7 @@ public InputStream readBlob(OperationPurpose purpose, final String blobName, fin @Override public void writeBlob(OperationPurpose purpose, String blobName, InputStream inputStream, long blobSize, boolean failIfAlreadyExists) throws IOException { - withSpan(purpose, ()-> blobStore.writeBlob(buildKey(blobName), inputStream, blobSize, failIfAlreadyExists)); + withSpan(purpose, () -> blobStore.writeBlob(buildKey(blobName), inputStream, blobSize, failIfAlreadyExists)); } @Override @@ -121,7 +121,6 @@ interface IOThrowing { void run() throws IOException; } - @Override public void writeBlobAtomic(OperationPurpose purpose, String blobName, BytesReference bytes, boolean failIfAlreadyExists) throws IOException { diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStoragePlugin.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStoragePlugin.java index 14281b7288067..1188ced760cb2 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStoragePlugin.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStoragePlugin.java @@ -22,6 +22,7 @@ import org.elasticsearch.repositories.Repository; import org.elasticsearch.xcontent.NamedXContentRegistry; +import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -92,4 +93,9 @@ public void reload(Settings settings) { final Map clientsSettings = GoogleCloudStorageClientSettings.load(settings); this.storageService.refreshAndClearCache(clientsSettings); } + + @Override + public void close() throws IOException { + this.storageService.shutdown(); + } } diff --git a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java index 66e27fafc29a9..56a3efc07f3e9 100644 --- a/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java +++ b/modules/repository-gcs/src/main/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageService.java @@ -14,7 +14,6 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.util.SecurityUtils; -import com.google.api.gax.tracing.OpencensusTracer; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.ServiceOptions; @@ -23,9 +22,6 @@ import com.google.cloud.storage.StorageOptions; import com.google.cloud.storage.StorageRetryStrategy; -import io.opencensus.contrib.http.util.HttpViews; -import io.opencensus.trace.Tracer; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.common.Strings; @@ -289,4 +285,8 @@ static Integer toTimeout(final TimeValue timeout) { // used for unit testing void notifyProxyIsSet(Proxy proxy) {} + + public void shutdown() { + GcpTracer.shutdown(); + } }