From 78717ade1d45902c13e77e84bc201338e159c3c4 Mon Sep 17 00:00:00 2001 From: Antoine Toulme Date: Sun, 26 Jun 2022 16:01:06 -0700 Subject: [PATCH] Upgrade OpenTelemetry (#3675) * Upgrade OpenTelemetry Signed-off-by: Antoine Toulme * remove a single sleep, poll with a for loop instead Signed-off-by: Antoine Toulme * use the new approach to send trace requests Signed-off-by: Antoine Toulme Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + .../tests/acceptance/dsl/node/BesuNode.java | 10 ++- .../dsl/node/ProcessBesuNodeRunner.java | 2 + .../configuration/BesuNodeConfiguration.java | 10 ++- .../BesuNodeConfigurationBuilder.java | 11 ++- .../node/configuration/BesuNodeFactory.java | 3 +- .../node/configuration/NodeConfiguration.java | 3 + .../acceptance/dsl/privacy/PrivacyNode.java | 3 +- acceptance-tests/tests/build.gradle | 7 +- .../OpenTelemetryAcceptanceTest.java | 90 ++++++++++++------- gradle/versions.gradle | 29 +++--- metrics/core/build.gradle | 4 +- .../besu/metrics/MetricsService.java | 6 +- .../besu/metrics/MetricsSystemFactory.java | 3 +- .../opentelemetry/DebugMetricReader.java | 57 ++++++++++++ .../MetricsOtelGrpcPushService.java | 88 ------------------ .../opentelemetry/MetricsOtelPushService.java | 48 ++++++++++ .../opentelemetry/OpenTelemetryCounter.java | 16 ++-- .../opentelemetry/OpenTelemetryGauge.java | 2 +- .../opentelemetry/OpenTelemetrySystem.java | 79 +++++++++------- .../opentelemetry/OpenTelemetryTimer.java | 2 +- .../OpenTelemetryMetricsSystemTest.java | 66 ++++++++------ 22 files changed, 320 insertions(+), 220 deletions(-) create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/DebugMetricReader.java delete mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelGrpcPushService.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelPushService.java diff --git a/CHANGELOG.md b/CHANGELOG.md index cf7158e911..8a2af55ad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Bug Fixes - Fixed a snapsync issue that can sometimes block the healing step [#3920](https://github.com/hyperledger/besu/pull/3920) +- Upgrade OpenTelemetry to version 1.15.0 [#3675](https://github.com/hyperledger/besu/pull/3675) ## 22.4.3 diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java index 52e767b189..4f2e8e3526 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java @@ -127,6 +127,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable private Optional exitCode = Optional.empty(); private Optional pkiKeyStoreConfiguration = Optional.empty(); private final boolean isStrictTxReplayProtectionEnabled; + private final Map environment; public BesuNode( final String name, @@ -159,7 +160,8 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable final List runCommand, final Optional keyPair, final Optional pkiKeyStoreConfiguration, - final boolean isStrictTxReplayProtectionEnabled) + final boolean isStrictTxReplayProtectionEnabled, + final Map environment) throws IOException { this.homeDirectory = dataPath.orElseGet(BesuNode::createTmpDataDirectory); this.isStrictTxReplayProtectionEnabled = isStrictTxReplayProtectionEnabled; @@ -216,6 +218,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable this.isDnsEnabled = isDnsEnabled; privacyParameters.ifPresent(this::setPrivacyParameters); this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration; + this.environment = environment; LOG.info("Created BesuNode {}", this); } @@ -794,4 +797,9 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable public void setExitCode(final int exitValue) { this.exitCode = Optional.of(exitValue); } + + @Override + public Map getEnvironment() { + return environment; + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index 133bb9e688..5a43cb417d 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -419,6 +419,8 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner { "JAVA_OPTS", "-Djava.security.properties=" + "acceptance-tests/tests/build/resources/test/acceptanceTesting.security"); + // add additional environment variables + processBuilder.environment().putAll(node.getEnvironment()); try { checkState( isNotAliveOrphan(node.getName()), diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java index 4d02e0ea4d..91d9e24e48 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java @@ -30,6 +30,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.Gene import java.nio.file.Path; import java.util.List; +import java.util.Map; import java.util.Optional; public class BesuNodeConfiguration { @@ -65,6 +66,7 @@ public class BesuNodeConfiguration { private final Optional keyPair; private final Optional pkiKeyStoreConfiguration; private final boolean strictTxReplayProtectionEnabled; + private final Map environment; BesuNodeConfiguration( final String name, @@ -97,7 +99,8 @@ public class BesuNodeConfiguration { final List runCommand, final Optional keyPair, final Optional pkiKeyStoreConfiguration, - final boolean strictTxReplayProtectionEnabled) { + final boolean strictTxReplayProtectionEnabled, + final Map environment) { this.name = name; this.miningParameters = miningParameters; this.jsonRpcConfiguration = jsonRpcConfiguration; @@ -129,6 +132,7 @@ public class BesuNodeConfiguration { this.keyPair = keyPair; this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration; this.strictTxReplayProtectionEnabled = strictTxReplayProtectionEnabled; + this.environment = environment; } public String getName() { @@ -254,4 +258,8 @@ public class BesuNodeConfiguration { public boolean isStrictTxReplayProtectionEnabled() { return strictTxReplayProtectionEnabled; } + + public Map getEnvironment() { + return environment; + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java index e5bd18fcad..2c3fd606cf 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java @@ -44,7 +44,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; public class BesuNodeConfigurationBuilder { @@ -85,6 +87,7 @@ public class BesuNodeConfigurationBuilder { private Optional keyPair = Optional.empty(); private Optional pkiKeyStoreConfiguration = Optional.empty(); private Boolean strictTxReplayProtectionEnabled = false; + private Map environment = new HashMap<>(); public BesuNodeConfigurationBuilder() { // Check connections more frequently during acceptance tests to cut down on @@ -478,6 +481,11 @@ public class BesuNodeConfigurationBuilder { return this; } + public BesuNodeConfigurationBuilder environment(final Map environment) { + this.environment = environment; + return this; + } + public BesuNodeConfiguration build() { return new BesuNodeConfiguration( name, @@ -510,6 +518,7 @@ public class BesuNodeConfigurationBuilder { runCommand, keyPair, pkiKeyStoreConfiguration, - strictTxReplayProtectionEnabled); + strictTxReplayProtectionEnabled, + environment); } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index 651c1fcd59..27b0903e96 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -88,7 +88,8 @@ public class BesuNodeFactory { config.getRunCommand(), config.getKeyPair(), config.getPkiKeyStoreConfiguration(), - config.isStrictTxReplayProtectionEnabled()); + config.isStrictTxReplayProtectionEnabled(), + config.getEnvironment()); } public BesuNode createMinerNode( diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java index b1566d5544..ce2d53cdf3 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfiguration.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.Gene import java.net.URI; import java.util.List; +import java.util.Map; import java.util.Optional; public interface NodeConfiguration { @@ -59,4 +60,6 @@ public interface NodeConfiguration { boolean isRevertReasonEnabled(); List getStaticNodes(); + + Map getEnvironment(); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java index fb14adb0e3..1974db8112 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java @@ -127,7 +127,8 @@ public class PrivacyNode implements AutoCloseable { List.of(), Optional.empty(), Optional.empty(), - besuConfig.isStrictTxReplayProtectionEnabled()); + besuConfig.isStrictTxReplayProtectionEnabled(), + besuConfig.getEnvironment()); } public void testEnclaveConnection(final List otherNodes) { diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index 8c9657b4d6..5427067c03 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -46,15 +46,16 @@ dependencies { testImplementation 'com.github.tomakehurst:wiremock-jre8-standalone' testImplementation 'commons-io:commons-io' + testImplementation 'io.grpc:grpc-all' testImplementation 'io.grpc:grpc-core' testImplementation 'io.grpc:grpc-netty' testImplementation 'io.grpc:grpc-stub' - testImplementation 'io.jaegertracing:jaeger-client' - testImplementation 'io.jaegertracing:jaeger-proto' + testImplementation 'io.opentelemetry:opentelemetry-extension-trace-propagators' + testImplementation 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0' testImplementation 'io.netty:netty-all' - testImplementation 'io.opentelemetry.proto:opentelemetry-proto' testImplementation 'io.opentelemetry:opentelemetry-api' testImplementation 'io.opentelemetry:opentelemetry-exporter-otlp' + testImplementation 'io.opentelemetry.proto:opentelemetry-proto' testImplementation 'io.opentelemetry:opentelemetry-sdk' testImplementation 'io.opentelemetry:opentelemetry-sdk-trace' testImplementation 'io.opentracing.contrib:opentracing-okhttp3' diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java index 17b503f491..481798feba 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/OpenTelemetryAcceptanceTest.java @@ -26,7 +26,9 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConf import java.time.Duration; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.google.common.io.Closer; import com.google.protobuf.ByteString; @@ -34,7 +36,11 @@ import io.grpc.Server; import io.grpc.Status; import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; -import io.jaegertracing.Configuration; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.extension.trace.propagation.B3Propagator; +import io.opentelemetry.instrumentation.okhttp.v3_0.OkHttpTelemetry; import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest; import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse; import io.opentelemetry.proto.collector.metrics.v1.MetricsServiceGrpc; @@ -44,8 +50,9 @@ import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc; import io.opentelemetry.proto.metrics.v1.ResourceMetrics; import io.opentelemetry.proto.trace.v1.ResourceSpans; import io.opentelemetry.proto.trace.v1.Span; -import io.opentracing.Tracer; -import io.opentracing.contrib.okhttp3.TracingCallFactory; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.samplers.Sampler; import okhttp3.Call; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -120,6 +127,7 @@ public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase { @Before public void setUp() throws Exception { + System.setProperty("root.log.level", "DEBUG"); Server server = NettyServerBuilder.forPort(4317) .addService(fakeTracesCollector) @@ -131,16 +139,26 @@ public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase { MetricsConfiguration configuration = MetricsConfiguration.builder() .protocol(MetricsProtocol.OPENTELEMETRY) - .enabled(true) + .pushEnabled(true) .port(0) .hostsAllowlist(singletonList("*")) .build(); + Map env = new HashMap<>(); + env.put("OTEL_METRIC_EXPORT_INTERVAL", "1000"); + env.put("OTEL_TRACES_SAMPLER", "always_on"); + env.put("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"); + env.put("OTEL_EXPORTER_OTLP_INSECURE", "true"); + env.put("OTEL_EXPORTER_OTLP_PROTOCOL", "grpc"); + env.put("OTEL_BSP_SCHEDULE_DELAY", "1000"); + env.put("OTEL_BSP_EXPORT_TIMEOUT", "3000"); + metricsNode = besu.create( new BesuNodeConfigurationBuilder() .name("metrics-node") .jsonRpcEnabled() .metricsConfiguration(configuration) + .environment(env) .build()); cluster.start(metricsNode); } @@ -170,11 +188,11 @@ public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase { net.netVersion().verify(metricsNode); List spans = fakeTracesCollector.getReceivedSpans(); assertThat(spans.isEmpty()).isFalse(); - Span internalSpan = spans.get(0).getInstrumentationLibrarySpans(0).getSpans(0); + Span internalSpan = spans.get(0).getScopeSpans(0).getSpans(0); assertThat(internalSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_INTERNAL); ByteString parent = internalSpan.getParentSpanId(); assertThat(parent.isEmpty()).isFalse(); - Span serverSpan = spans.get(0).getInstrumentationLibrarySpans(0).getSpans(1); + Span serverSpan = spans.get(0).getScopeSpans(0).getSpans(1); assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER); ByteString rootSpanId = serverSpan.getParentSpanId(); assertThat(rootSpanId.isEmpty()).isTrue(); @@ -184,23 +202,26 @@ public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase { @Test public void traceReportingWithTraceId() { Duration timeout = Duration.ofSeconds(1); - OkHttpClient okClient = - new OkHttpClient.Builder() - .connectTimeout(timeout) - .readTimeout(timeout) - .writeTimeout(timeout) - .build(); WaitUtils.waitFor( 30, () -> { - // call the json RPC endpoint to generate a trace - with trace metadata of our own - Configuration config = - new Configuration("okhttp") - .withSampler( - Configuration.SamplerConfiguration.fromEnv().withType("const").withParam(1)); - - Tracer tracer = config.getTracer(); - Call.Factory client = new TracingCallFactory(okClient, tracer); + OpenTelemetry openTelemetry = + OpenTelemetrySdk.builder() + .setPropagators( + ContextPropagators.create( + TextMapPropagator.composite(B3Propagator.injectingSingleHeader()))) + .setTracerProvider( + SdkTracerProvider.builder().setSampler(Sampler.alwaysOn()).build()) + .build(); + Call.Factory client = + OkHttpTelemetry.builder(openTelemetry) + .build() + .newCallFactory( + new OkHttpClient.Builder() + .connectTimeout(timeout) + .readTimeout(timeout) + .writeTimeout(timeout) + .build()); Request request = new Request.Builder() .url("http://localhost:" + metricsNode.getJsonRpcPort().get()) @@ -210,19 +231,22 @@ public class OpenTelemetryAcceptanceTest extends AcceptanceTestBase { MediaType.get("application/json"))) .build(); Response response = client.newCall(request).execute(); - assertThat(response.code()).isEqualTo(200); - response.close(); - List spans = new ArrayList<>(fakeTracesCollector.getReceivedSpans()); - fakeTracesCollector.getReceivedSpans().clear(); - assertThat(spans.isEmpty()).isFalse(); - Span internalSpan = spans.get(0).getInstrumentationLibrarySpans(0).getSpans(0); - assertThat(internalSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_INTERNAL); - ByteString parent = internalSpan.getParentSpanId(); - assertThat(parent.isEmpty()).isFalse(); - Span serverSpan = spans.get(0).getInstrumentationLibrarySpans(0).getSpans(1); - assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER); - ByteString rootSpanId = serverSpan.getParentSpanId(); - assertThat(rootSpanId.isEmpty()).isFalse(); + try { + assertThat(response.code()).isEqualTo(200); + List spans = new ArrayList<>(fakeTracesCollector.getReceivedSpans()); + assertThat(spans.isEmpty()).isFalse(); + Span internalSpan = spans.get(0).getScopeSpans(0).getSpans(0); + assertThat(internalSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_INTERNAL); + ByteString parent = internalSpan.getParentSpanId(); + assertThat(parent.isEmpty()).isFalse(); + Span serverSpan = spans.get(0).getScopeSpans(0).getSpans(1); + assertThat(serverSpan.getKind()).isEqualTo(Span.SpanKind.SPAN_KIND_SERVER); + ByteString rootSpanId = serverSpan.getParentSpanId(); + assertThat(rootSpanId.isEmpty()).isFalse(); + } finally { + response.close(); + fakeTracesCollector.getReceivedSpans().clear(); + } }); } } diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 0ce45ae403..d469e9707b 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -60,14 +60,12 @@ dependencyManagement { dependency 'info.picocli:picocli:4.6.3' dependencySet(group: 'io.grpc', version: '1.47.0') { - entry'grpc-core' - entry'grpc-netty' - entry'grpc-stub' + entry 'grpc-all' + entry 'grpc-core' + entry 'grpc-netty' + entry 'grpc-stub' } - dependency 'io.jaegertracing:jaeger-client:1.8.0' - dependency 'io.jaegertracing:jaeger-proto:0.7.0' - dependency 'io.kubernetes:client-java:15.0.1' dependency 'io.netty:netty-all:4.1.78.Final' @@ -76,14 +74,17 @@ dependencyManagement { dependency group: 'io.netty', name: 'netty-transport-native-kqueue', version:'4.1.78.Final', classifier: 'osx-x86_64' dependency 'io.netty:netty-transport-native-unix-common:4.1.78.Final' - dependency 'io.opentelemetry:opentelemetry-api:1.6.0' - dependency 'io.opentelemetry:opentelemetry-exporter-otlp-metrics:1.6.0-alpha' - dependency 'io.opentelemetry:opentelemetry-exporter-otlp:1.6.0' - dependency 'io.opentelemetry:opentelemetry-extension-trace-propagators:1.6.0' - dependency 'io.opentelemetry:opentelemetry-sdk-trace:1.6.0' - dependency 'io.opentelemetry:opentelemetry-sdk:1.6.0' - dependency 'io.opentelemetry:opentelemetry-semconv:1.6.0-alpha' - dependency 'io.opentelemetry.proto:opentelemetry-proto:0.13.0-alpha' + dependency 'io.opentelemetry:opentelemetry-api:1.15.0' + dependency 'io.opentelemetry:opentelemetry-exporter-otlp-metrics:1.14.0' + dependency 'io.opentelemetry:opentelemetry-exporter-otlp:1.15.0' + dependency 'io.opentelemetry:opentelemetry-extension-trace-propagators:1.15.0' + dependency 'io.opentelemetry.proto:opentelemetry-proto:0.16.0-alpha' + dependency 'io.opentelemetry:opentelemetry-sdk-metrics:1.15.0' + dependency 'io.opentelemetry:opentelemetry-sdk-trace:1.15.0' + dependency 'io.opentelemetry:opentelemetry-sdk:1.15.0' + dependency 'io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.15.0-alpha' + dependency 'io.opentelemetry:opentelemetry-semconv:1.15.0-alpha' + dependency 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0:1.15.0-alpha' dependency 'io.opentracing.contrib:opentracing-okhttp3:3.0.0' dependency 'io.opentracing:opentracing-api:0.33.0' diff --git a/metrics/core/build.gradle b/metrics/core/build.gradle index 4349d3abbf..8133f040a8 100644 --- a/metrics/core/build.gradle +++ b/metrics/core/build.gradle @@ -41,7 +41,6 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.grpc:grpc-netty' implementation 'io.grpc:grpc-core' - implementation 'io.jaegertracing:jaeger-proto' implementation 'io.netty:netty-tcnative-boringssl-static' implementation 'io.netty:netty-transport-native-epoll' implementation 'io.netty:netty-all' @@ -49,9 +48,10 @@ dependencies { implementation 'io.opentelemetry:opentelemetry-sdk' implementation 'io.opentelemetry:opentelemetry-semconv' implementation 'io.opentelemetry:opentelemetry-sdk-trace' + implementation 'io.opentelemetry:opentelemetry-sdk-metrics' implementation 'io.opentelemetry:opentelemetry-exporter-otlp' implementation 'io.opentelemetry:opentelemetry-exporter-otlp-metrics' - implementation 'io.opentelemetry.proto:opentelemetry-proto' + implementation 'io.opentelemetry:opentelemetry-sdk-extension-autoconfigure' implementation 'io.prometheus:simpleclient' implementation 'io.prometheus:simpleclient_common' diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsService.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsService.java index 625fc323a8..25ad5fcc5b 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsService.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsService.java @@ -14,8 +14,7 @@ */ package org.hyperledger.besu.metrics; -import org.hyperledger.besu.metrics.opentelemetry.MetricsOtelGrpcPushService; -import org.hyperledger.besu.metrics.opentelemetry.OpenTelemetrySystem; +import org.hyperledger.besu.metrics.opentelemetry.MetricsOtelPushService; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsHttpService; import org.hyperledger.besu.metrics.prometheus.MetricsPushGatewayService; @@ -49,8 +48,7 @@ public interface MetricsService { } } else if (configuration.getProtocol() == MetricsProtocol.OPENTELEMETRY) { if (configuration.isEnabled()) { - return Optional.of( - new MetricsOtelGrpcPushService(configuration, (OpenTelemetrySystem) metricsSystem)); + return Optional.of(new MetricsOtelPushService()); } else { return Optional.empty(); } diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsSystemFactory.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsSystemFactory.java index f8449c497b..4145c41c9d 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsSystemFactory.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/MetricsSystemFactory.java @@ -54,7 +54,8 @@ public class MetricsSystemFactory { new OpenTelemetrySystem( metricsConfiguration.getMetricCategories(), metricsConfiguration.isTimersEnabled(), - metricsConfiguration.getPrometheusJob()); + metricsConfiguration.getPrometheusJob(), + true); metricsSystem.initDefaults(); return metricsSystem; } else { diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/DebugMetricReader.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/DebugMetricReader.java new file mode 100644 index 0000000000..ea81e91aff --- /dev/null +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/DebugMetricReader.java @@ -0,0 +1,57 @@ +/* + * Copyright Besu Contributors + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.metrics.opentelemetry; + +import java.util.Collection; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.metrics.InstrumentType; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.export.CollectionRegistration; +import io.opentelemetry.sdk.metrics.export.MetricReader; +import io.opentelemetry.sdk.metrics.internal.export.MetricProducer; +import org.jetbrains.annotations.NotNull; + +class DebugMetricReader implements MetricReader { + private CollectionRegistration registration; + + public DebugMetricReader() {} + + public Collection getAllMetrics() { + return MetricProducer.asMetricProducer(this.registration).collectAllMetrics(); + } + + @Override + public void register(final @NotNull CollectionRegistration registration) { + this.registration = registration; + } + + @Override + public CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + return CompletableResultCode.ofSuccess(); + } + + @Override + public AggregationTemporality getAggregationTemporality( + final @NotNull InstrumentType instrumentType) { + return AggregationTemporality.CUMULATIVE; + } +} diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelGrpcPushService.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelGrpcPushService.java deleted file mode 100644 index 75487d639f..0000000000 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelGrpcPushService.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - * - */ -package org.hyperledger.besu.metrics.opentelemetry; - -import org.hyperledger.besu.metrics.MetricsService; -import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; - -import java.util.Collections; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - -import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReaderBuilder; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MetricsOtelGrpcPushService implements MetricsService { - - private static final Logger LOG = LoggerFactory.getLogger(MetricsOtelGrpcPushService.class); - - private final MetricsConfiguration configuration; - private final OpenTelemetrySystem metricsSystem; - private IntervalMetricReader periodicReader; - private SpanProcessor spanProcessor; - - public MetricsOtelGrpcPushService( - final MetricsConfiguration configuration, final OpenTelemetrySystem metricsSystem) { - - this.configuration = configuration; - this.metricsSystem = metricsSystem; - } - - @Override - public CompletableFuture start() { - LOG.info("Starting OpenTelemetry push service"); - OtlpGrpcMetricExporter exporter = OtlpGrpcMetricExporter.getDefault(); - IntervalMetricReaderBuilder builder = - IntervalMetricReader.builder() - .setExportIntervalMillis(configuration.getPushInterval() * 1000L) - .setMetricProducers(Collections.singleton(metricsSystem.getMeterSdkProvider())) - .setMetricExporter(exporter); - this.periodicReader = builder.buildAndStart(); - this.spanProcessor = BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build(); - OpenTelemetrySdk.builder() - .setTracerProvider(SdkTracerProvider.builder().addSpanProcessor(spanProcessor).build()) - .buildAndRegisterGlobal(); - return CompletableFuture.completedFuture(null); - } - - @Override - public CompletableFuture stop() { - if (periodicReader != null) { - periodicReader.shutdown(); - } - if (spanProcessor != null) { - CompletableResultCode result = spanProcessor.shutdown(); - CompletableFuture future = new CompletableFuture<>(); - result.whenComplete(() -> future.complete(null)); - return future; - } - return CompletableFuture.completedFuture(null); - } - - @Override - public Optional getPort() { - return Optional.empty(); - } -} diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelPushService.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelPushService.java new file mode 100644 index 0000000000..d6c0f7e6f6 --- /dev/null +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/MetricsOtelPushService.java @@ -0,0 +1,48 @@ +/* + * Copyright Hyperledger Besu Contributors + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ +package org.hyperledger.besu.metrics.opentelemetry; + +import org.hyperledger.besu.metrics.MetricsService; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MetricsOtelPushService implements MetricsService { + + private static final Logger LOG = LoggerFactory.getLogger(MetricsOtelPushService.class); + + public MetricsOtelPushService() {} + + @Override + public CompletableFuture start() { + LOG.info("Starting OpenTelemetry push service"); + + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture stop() { + return CompletableFuture.completedFuture(null); + } + + @Override + public Optional getPort() { + return Optional.empty(); + } +} diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryCounter.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryCounter.java index 088abf26cf..fe39ae7ed5 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryCounter.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryCounter.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; -import io.opentelemetry.api.metrics.BoundLongCounter; import io.opentelemetry.api.metrics.LongCounter; public class OpenTelemetryCounter implements LabelledMetric { @@ -39,25 +38,26 @@ public class OpenTelemetryCounter implements LabelledMetric { builder.put(labelNames[i], labelValues[i]); } final Attributes labels = builder.build(); - BoundLongCounter boundLongCounter = counter.bind(labels); - return new OpenTelemetryCounter.UnlabelledCounter(boundLongCounter); + return new BoundLongCounter(counter, labels); } - private static class UnlabelledCounter implements Counter { - private final BoundLongCounter counter; + private static class BoundLongCounter implements Counter { + private final LongCounter counter; + private final Attributes labels; - private UnlabelledCounter(final BoundLongCounter counter) { + private BoundLongCounter(final LongCounter counter, final Attributes labels) { this.counter = counter; + this.labels = labels; } @Override public void inc() { - counter.add(1); + counter.add(1, labels); } @Override public void inc(final long amount) { - counter.add(amount); + counter.add(amount, labels); } } } diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryGauge.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryGauge.java index 871e4e5c95..bd6c340f27 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryGauge.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryGauge.java @@ -64,6 +64,6 @@ public class OpenTelemetryGauge implements LabelledGauge { private void updater(final ObservableDoubleMeasurement measurement) { observationsMap.forEach( - (labels, valueSupplier) -> measurement.observe(valueSupplier.getAsDouble(), labels)); + (labels, valueSupplier) -> measurement.record(valueSupplier.getAsDouble(), labels)); } } diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetrySystem.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetrySystem.java index 78f7290259..70a7256fa2 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetrySystem.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetrySystem.java @@ -45,14 +45,16 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.LongCounter; import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.data.DoubleHistogramPointData; import io.opentelemetry.sdk.metrics.data.DoublePointData; -import io.opentelemetry.sdk.metrics.data.DoubleSummaryPointData; +import io.opentelemetry.sdk.metrics.data.HistogramPointData; import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.MetricDataType; import io.opentelemetry.sdk.metrics.data.PointData; +import io.opentelemetry.sdk.metrics.data.SummaryPointData; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; import org.slf4j.Logger; @@ -77,25 +79,33 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { private final Map> cachedCounters = new ConcurrentHashMap<>(); private final Map> cachedTimers = new ConcurrentHashMap<>(); - private final SdkMeterProvider meterSdkProvider; + private final SdkMeterProvider sdkMeterProvider; + private final DebugMetricReader debugMetricReader; public OpenTelemetrySystem( final Set enabledCategories, final boolean timersEnabled, - final String jobName) { + final String jobName, + final boolean setAsGlobal) { LOG.info("Starting OpenTelemetry metrics system"); this.enabledCategories = ImmutableSet.copyOf(enabledCategories); this.timersEnabled = timersEnabled; + this.debugMetricReader = new DebugMetricReader(); Resource resource = Resource.getDefault() .merge( Resource.create( Attributes.builder().put(ResourceAttributes.SERVICE_NAME, jobName).build())); - this.meterSdkProvider = SdkMeterProvider.builder().setResource(resource).build(); - } - - SdkMeterProvider getMeterSdkProvider() { - return meterSdkProvider; + AutoConfiguredOpenTelemetrySdk autoSdk = + AutoConfiguredOpenTelemetrySdk.builder() + .addMeterProviderCustomizer( + (provider, config) -> + provider.setResource(resource).registerMetricReader(debugMetricReader)) + .addTracerProviderCustomizer((provider, config) -> provider.setResource(resource)) + .setResultAsGlobal(setAsGlobal) + .build(); + OpenTelemetrySdk sdk = autoSdk.getOpenTelemetrySdk(); + this.sdkMeterProvider = sdk.getSdkMeterProvider(); } @Override @@ -105,14 +115,17 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { @Override public Stream streamObservations() { - Collection metricsList = meterSdkProvider.collectAllMetrics(); - return metricsList.stream().map(this::convertToObservations).flatMap(stream -> stream); + Collection metricsList = this.debugMetricReader.getAllMetrics(); + return metricsList.stream().flatMap(this::convertToObservations); } private Stream convertToObservations(final MetricData metricData) { List observations = new ArrayList<>(); MetricCategory category = - categoryNameToMetricCategory(metricData.getInstrumentationLibraryInfo().getName()); + categoryNameToMetricCategory(metricData.getInstrumentationScopeInfo().getName()); + if (category == null) { + return Stream.empty(); + } Collection points; switch (metricData.getType()) { case DOUBLE_GAUGE: @@ -122,13 +135,13 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { points = metricData.getDoubleSumData().getPoints(); break; case SUMMARY: - points = metricData.getDoubleSummaryData().getPoints(); + points = metricData.getData().getPoints(); break; case LONG_SUM: points = metricData.getLongSumData().getPoints(); break; case HISTOGRAM: - points = metricData.getDoubleHistogramData().getPoints(); + points = metricData.getData().getPoints(); break; case LONG_GAUGE: points = metricData.getLongGaugeData().getPoints(); @@ -159,7 +172,7 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { return category; } } - throw new IllegalArgumentException("Invalid metric category: " + name); + return null; } private Object extractValue(final MetricDataType type, final PointData point) { @@ -170,9 +183,9 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { case DOUBLE_GAUGE: return ((DoublePointData) point).getValue(); case SUMMARY: - return ((DoubleSummaryPointData) point).getPercentileValues(); + return ((SummaryPointData) point).getValues(); case HISTOGRAM: - return ((DoubleHistogramPointData) point).getCounts(); + return ((HistogramPointData) point).getCounts(); default: throw new UnsupportedOperationException("Unsupported type " + type); } @@ -189,7 +202,7 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { name, (k) -> { if (isCategoryEnabled(category)) { - final Meter meter = meterSdkProvider.get(category.getName()); + final Meter meter = sdkMeterProvider.get(category.getName()); final LongCounter counter = meter.counterBuilder(name).setDescription(help).build(); return new OpenTelemetryCounter(counter, labelNames); @@ -210,7 +223,7 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { name, (k) -> { if (timersEnabled && isCategoryEnabled(category)) { - final Meter meter = meterSdkProvider.get(category.getName()); + final Meter meter = sdkMeterProvider.get(category.getName()); return new OpenTelemetryTimer(name, help, meter, labelNames); } else { return NoOpMetricsSystem.getOperationTimerLabelledMetric(labelNames.length); @@ -226,11 +239,11 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { final DoubleSupplier valueSupplier) { LOG.trace("Creating a gauge {}", name); if (isCategoryEnabled(category)) { - final Meter meter = meterSdkProvider.get(category.getName()); + final Meter meter = sdkMeterProvider.get(category.getName()); meter .gaugeBuilder(name) .setDescription(help) - .buildWithCallback(res -> res.observe(valueSupplier.getAsDouble(), Attributes.empty())); + .buildWithCallback(res -> res.record(valueSupplier.getAsDouble(), Attributes.empty())); } } @@ -243,7 +256,7 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { LOG.trace("Creating a labelled gauge {}", name); if (isCategoryEnabled(category)) { return new OpenTelemetryGauge( - name, help, meterSdkProvider.get(category.getName()), List.of(labelNames)); + name, help, sdkMeterProvider.get(category.getName()), List.of(labelNames)); } return NoOpMetricsSystem.getLabelledGauge(labelNames.length); } @@ -264,7 +277,7 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { ManagementFactory.getGarbageCollectorMXBeans(); final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); final List poolBeans = ManagementFactory.getMemoryPoolMXBeans(); - final Meter meter = meterSdkProvider.get(StandardMetricCategory.JVM.getName()); + final Meter meter = sdkMeterProvider.get(StandardMetricCategory.JVM.getName()); final List labelSets = new ArrayList<>(garbageCollectors.size()); for (final GarbageCollectorMXBean gc : garbageCollectors) { labelSets.add(Attributes.of(AttributeKey.stringKey("gc"), gc.getName())); @@ -276,7 +289,7 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { .buildWithCallback( resultLongObserver -> { for (int i = 0; i < garbageCollectors.size(); i++) { - resultLongObserver.observe( + resultLongObserver.record( (double) garbageCollectors.get(i).getCollectionTime(), labelSets.get(i)); } }); @@ -297,12 +310,12 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { resultLongObserver -> { MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage(); MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage(); - resultLongObserver.observe(heapUsage.getUsed(), usedHeap); - resultLongObserver.observe(nonHeapUsage.getUsed(), usedNonHeap); - resultLongObserver.observe(heapUsage.getUsed(), committedHeap); - resultLongObserver.observe(nonHeapUsage.getUsed(), committedNonHeap); - resultLongObserver.observe(heapUsage.getUsed(), maxHeap); - resultLongObserver.observe(nonHeapUsage.getUsed(), maxNonHeap); + resultLongObserver.record(heapUsage.getUsed(), usedHeap); + resultLongObserver.record(nonHeapUsage.getUsed(), usedNonHeap); + resultLongObserver.record(heapUsage.getUsed(), committedHeap); + resultLongObserver.record(nonHeapUsage.getUsed(), committedNonHeap); + resultLongObserver.record(heapUsage.getUsed(), maxHeap); + resultLongObserver.record(nonHeapUsage.getUsed(), maxNonHeap); }); final List usedLabelSets = new ArrayList<>(poolBeans.size()); final List committedLabelSets = new ArrayList<>(poolBeans.size()); @@ -322,11 +335,11 @@ public class OpenTelemetrySystem implements ObservableMetricsSystem { resultLongObserver -> { for (int i = 0; i < poolBeans.size(); i++) { MemoryUsage poolUsage = poolBeans.get(i).getUsage(); - resultLongObserver.observe(poolUsage.getUsed(), usedLabelSets.get(i)); - resultLongObserver.observe(poolUsage.getCommitted(), committedLabelSets.get(i)); + resultLongObserver.record(poolUsage.getUsed(), usedLabelSets.get(i)); + resultLongObserver.record(poolUsage.getCommitted(), committedLabelSets.get(i)); // TODO: Decide if max is needed or not. May be derived with some approximation from // max(used). - resultLongObserver.observe(poolUsage.getMax(), maxLabelSets.get(i)); + resultLongObserver.record(poolUsage.getMax(), maxLabelSets.get(i)); } }); } diff --git a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryTimer.java b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryTimer.java index 47a26aacd9..9e33d7f696 100644 --- a/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryTimer.java +++ b/metrics/core/src/main/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryTimer.java @@ -51,7 +51,7 @@ public class OpenTelemetryTimer implements LabelledMetric { meter .gaugeBuilder(metricName) .setDescription(help) - .buildWithCallback((measurement) -> measurement.observe((double) elapsed, labels)); + .buildWithCallback((measurement) -> measurement.record((double) elapsed, labels)); return elapsed / 1e9; }; }; diff --git a/metrics/core/src/test/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryMetricsSystemTest.java b/metrics/core/src/test/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryMetricsSystemTest.java index 3226ce859f..d83d348a8d 100644 --- a/metrics/core/src/test/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryMetricsSystemTest.java +++ b/metrics/core/src/test/java/org/hyperledger/besu/metrics/opentelemetry/OpenTelemetryMetricsSystemTest.java @@ -38,6 +38,8 @@ import org.hyperledger.besu.plugin.services.metrics.OperationTimer; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import com.google.common.collect.ImmutableSet; import org.junit.Test; @@ -50,10 +52,23 @@ public class OpenTelemetryMetricsSystemTest { .thenComparing((o1, o2) -> o1.getLabels().equals(o2.getLabels()) ? 0 : 1); private final ObservableMetricsSystem metricsSystem = - new OpenTelemetrySystem(DEFAULT_METRIC_CATEGORIES, true, "job"); + new OpenTelemetrySystem(DEFAULT_METRIC_CATEGORIES, true, "job", false); + + private List getObservation(final ObservableMetricsSystem metricsSystem) + throws InterruptedException { + for (int i = 0; i < 20; i++) { + Stream observations = metricsSystem.streamObservations(); + List result = observations.collect(Collectors.toList()); + if (!result.isEmpty()) { + return result; + } + Thread.sleep(100); + } + return null; + } @Test - public void shouldCreateObservationFromCounter() { + public void shouldCreateObservationFromCounter() throws InterruptedException { final Counter counter = metricsSystem.createCounter(PEERS, "connected", "Some help string"); counter.inc(); @@ -61,12 +76,12 @@ public class OpenTelemetryMetricsSystemTest { .containsExactly(new Observation(PEERS, "connected", 1L, emptyList())); counter.inc(); - assertThat(metricsSystem.streamObservations()) + assertThat(getObservation(metricsSystem)) .containsExactly(new Observation(PEERS, "connected", 2L, emptyList())); } @Test - public void shouldHandleDuplicateCounterCreation() { + public void shouldHandleDuplicateCounterCreation() throws InterruptedException { final LabelledMetric counter1 = metricsSystem.createLabelledCounter(PEERS, "connected", "Some help string"); final LabelledMetric counter2 = @@ -78,7 +93,7 @@ public class OpenTelemetryMetricsSystemTest { .containsExactly(new Observation(PEERS, "connected", 1L, emptyList())); counter2.labels().inc(); - assertThat(metricsSystem.streamObservations()) + assertThat(getObservation(metricsSystem)) .containsExactly(new Observation(PEERS, "connected", 2L, emptyList())); } @@ -98,7 +113,7 @@ public class OpenTelemetryMetricsSystemTest { } @Test - public void shouldIncrementCounterBySpecifiedAmount() { + public void shouldIncrementCounterBySpecifiedAmount() throws InterruptedException { final Counter counter = metricsSystem.createCounter(PEERS, "connected", "Some help string"); counter.inc(5); @@ -106,7 +121,7 @@ public class OpenTelemetryMetricsSystemTest { .containsExactly(new Observation(PEERS, "connected", 5L, emptyList())); counter.inc(6); - assertThat(metricsSystem.streamObservations()) + assertThat(getObservation(metricsSystem)) .containsExactly(new Observation(PEERS, "connected", 11L, emptyList())); } @@ -153,7 +168,7 @@ public class OpenTelemetryMetricsSystemTest { @Test public void shouldNotCreateObservationsFromTimerWhenTimersDisabled() { final ObservableMetricsSystem metricsSystem = - new OpenTelemetrySystem(DEFAULT_METRIC_CATEGORIES, false, "job"); + new OpenTelemetrySystem(DEFAULT_METRIC_CATEGORIES, false, "job", false); final LabelledMetric timer = metricsSystem.createLabelledTimer(RPC, "request", "Some help", "methodName"); @@ -171,8 +186,13 @@ public class OpenTelemetryMetricsSystemTest { .enabled(true) .protocol(OPENTELEMETRY) .build(); - final ObservableMetricsSystem localMetricSystem = - MetricsSystemFactory.create(metricsConfiguration); + final OpenTelemetrySystem localMetricSystem = + new OpenTelemetrySystem( + metricsConfiguration.getMetricCategories(), + metricsConfiguration.isTimersEnabled(), + metricsConfiguration.getPrometheusJob(), + false); + localMetricSystem.initDefaults(); localMetricSystem.createGauge(RPC, "myValue", "Help", () -> 7.0); assertThat(localMetricSystem.streamObservations()) @@ -195,15 +215,20 @@ public class OpenTelemetryMetricsSystemTest { } @Test - public void shouldOnlyObserveEnabledMetrics() { + public void shouldOnlyObserveEnabledMetrics() throws InterruptedException { final MetricsConfiguration metricsConfiguration = MetricsConfiguration.builder() .metricCategories(ImmutableSet.of(BesuMetricCategory.RPC)) .enabled(true) .protocol(OPENTELEMETRY) .build(); - final ObservableMetricsSystem localMetricSystem = - MetricsSystemFactory.create(metricsConfiguration); + final OpenTelemetrySystem localMetricSystem = + new OpenTelemetrySystem( + metricsConfiguration.getMetricCategories(), + metricsConfiguration.isTimersEnabled(), + metricsConfiguration.getPrometheusJob(), + false); + localMetricSystem.initDefaults(); // do a category we are not watching final LabelledMetric counterN = @@ -219,7 +244,7 @@ public class OpenTelemetryMetricsSystemTest { assertThat(counterR).isNotSameAs(NoOpMetricsSystem.NO_OP_LABELLED_1_COUNTER); counterR.labels("op").inc(); - assertThat(localMetricSystem.streamObservations()) + assertThat(getObservation(localMetricSystem)) .containsExactly(new Observation(RPC, "name", (long) 1, singletonList("op"))); } @@ -248,17 +273,4 @@ public class OpenTelemetryMetricsSystemTest { assertThat(localMetricSystem).isInstanceOf(OpenTelemetrySystem.class); } - - @Test - public void returnsNoOpMetricsWhenPushEnabled() { - final MetricsConfiguration metricsConfiguration = - MetricsConfiguration.builder() - .enabled(false) - .pushEnabled(true) - .protocol(OPENTELEMETRY) - .build(); - final MetricsSystem localMetricSystem = MetricsSystemFactory.create(metricsConfiguration); - - assertThat(localMetricSystem).isInstanceOf(OpenTelemetrySystem.class); - } }