diff --git a/CHANGELOG.md b/CHANGELOG.md index 9baca7c025..185c545f70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Users of Web3J should note that many calls will now return a result with the err ### Additions and Improvements * Added support for ECIP-1099: Calibrate Epoch Duration. [\#1421](https://github.com/hyperledger/besu/pull/1421) +* Added the Open Telemetry Java agent to report traces to a remote backend. Added an example to showcase the trace reporting capabilities. ## 20.10.0-RC1 diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthGetTransactionReceipt.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthGetTransactionReceipt.java index 9d6302bc91..efc02f73d4 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthGetTransactionReceipt.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/eth/ExpectSuccessfulEthGetTransactionReceipt.java @@ -32,6 +32,6 @@ public class ExpectSuccessfulEthGetTransactionReceipt implements Condition { @Override public void verify(final Node node) { - WaitUtils.waitFor(() -> assertThat(node.execute(transaction)).isPresent()); + WaitUtils.waitFor(60, () -> assertThat(node.execute(transaction)).isPresent()); } } diff --git a/build.gradle b/build.gradle index 49b5928feb..6f2c9ed6dc 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ import groovy.transform.Memoized import net.ltgt.gradle.errorprone.CheckSeverity +import java.nio.file.Paths import java.text.SimpleDateFormat plugins { @@ -126,6 +127,7 @@ allprojects { maven { url "https://hyperledger-org.bintray.com/besu-repo" } maven { url "https://consensys.bintray.com/pegasys-repo" } maven { url "https://repo.spring.io/libs-release" } + maven { url "https://dl.bintray.com/open-telemetry/maven" } } dependencies { errorprone "com.google.errorprone:error_prone_core" } @@ -484,6 +486,8 @@ applicationDefaultJvmArgs = [ run { args project.hasProperty("besu.run.args") ? project.property("besu.run.args").toString().split("\\s+") : [] doFirst { + applicationDefaultJvmArgs.add(0, "-Dotel.resource.attributes=service.name=besu-dev") + applicationDefaultJvmArgs.add(0, "-javaagent:"+ configurations.javaAgent.singleFile.toPath() + "") applicationDefaultJvmArgs = applicationDefaultJvmArgs.collect { it.replace('BESU_HOME', "$buildDir/besu") } @@ -499,6 +503,19 @@ startScripts { doLast { unixScript.text = unixScript.text.replace('BESU_HOME', '\$APP_HOME') windowsScript.text = windowsScript.text.replace('BESU_HOME', '%~dp0..') + // OpenTelemetry Wiring for unix scripts + def agentFileName = configurations.javaAgent.singleFile.toPath().getFileName() + def unixRegex = $/exec "$$JAVACMD" /$ + def forwardSlash = "/" + def unixReplacement = $/if [ -n "$$TRACING" ];then + TRACING_AGENT="-javaagent:$$APP_HOME/agent${forwardSlash}${agentFileName}" +fi +exec "$$JAVACMD" $$TRACING_AGENT /$ + unixScript.text = unixScript.text.replace(unixRegex, unixReplacement) + // OpenTelemetry Wiring for windows scripts + def windowsRegex = $/"%JAVA_EXE%" %DEFAULT_JVM_OPTS%/$ + def windowsReplacement = $/if Defined TRACING (TRACING_AGENT="-javaagent:"%APP_HOME%\agent\/$ + agentFileName + '")\r\n"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %TRACING_AGENT%' + windowsScript.text = windowsScript.text.replace(windowsRegex, windowsReplacement) // Prevent the error originating from the 8191 chars limit on Windows windowsScript.text = @@ -510,22 +527,6 @@ startScripts { } -dependencies { - implementation project(':besu') - errorprone 'com.google.errorprone:error_prone_core' -} - -distributions { - main { - contents { - from("./LICENSE") { into "." } - from("build/reports/license/license-dependency.html") { into "." } - from("./docs/GettingStartedBinaries.md") { into "." } - from("./docs/DocsArchive0.8.0.html") { into "." } - } - } -} - installDist { dependsOn checkLicenses } distTar { @@ -770,6 +771,28 @@ tasks.register("verifyDistributions") { } } +configurations { + javaAgent +} + +dependencies { + implementation project(':besu') + javaAgent group: 'io.opentelemetry.instrumentation.auto', name: 'opentelemetry-javaagent', classifier: 'all' + errorprone 'com.google.errorprone:error_prone_core' +} + +distributions { + main { + contents { + from("./LICENSE") { into "." } + from("build/reports/license/license-dependency.html") { into "." } + from("./docs/GettingStartedBinaries.md") { into "." } + from("./docs/DocsArchive0.8.0.html") { into "." } + from(configurations.javaAgent.singleFile.toPath()) { into "agent"} + } + } +} + bintray { user = bintrayUser key = bintrayKey diff --git a/docker/graalvm/Dockerfile b/docker/graalvm/Dockerfile index c12c259bbe..983e410adc 100644 --- a/docker/graalvm/Dockerfile +++ b/docker/graalvm/Dockerfile @@ -21,6 +21,12 @@ ENV BESU_RPC_HTTP_HOST 0.0.0.0 ENV BESU_RPC_WS_HOST 0.0.0.0 ENV BESU_GRAPHQL_HTTP_HOST 0.0.0.0 ENV BESU_PID_PATH "/tmp/pid" +# Tracing defaults +# To enable tracing, uncomment next line +#ENV TRACING=ENABLED +ENV OTEL_EXPORTER=otlp +ENV OTEL_OTLP_ENDPOINT="0.0.0.0:55680" +ENV OTEL_RESOURCE_ATTRIBUTES="service.name=besu-$VERSION" ENV PATH="/opt/besu/bin:${PATH}" ENTRYPOINT ["besu"] @@ -38,4 +44,4 @@ LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.vcs-url="https://github.com/hyperledger/besu.git" \ org.label-schema.vendor="Hyperledger" \ org.label-schema.version=$VERSION \ - org.label-schema.schema-version="1.0" \ No newline at end of file + org.label-schema.schema-version="1.0" diff --git a/docker/openjdk-11/Dockerfile b/docker/openjdk-11/Dockerfile index 09446ccf56..ada2e42d5f 100644 --- a/docker/openjdk-11/Dockerfile +++ b/docker/openjdk-11/Dockerfile @@ -21,6 +21,12 @@ ENV BESU_RPC_HTTP_HOST 0.0.0.0 ENV BESU_RPC_WS_HOST 0.0.0.0 ENV BESU_GRAPHQL_HTTP_HOST 0.0.0.0 ENV BESU_PID_PATH "/tmp/pid" +# Tracing defaults +# To enable tracing, uncomment next line +#ENV TRACING=ENABLED +ENV OTEL_EXPORTER=otlp +ENV OTEL_OTLP_ENDPOINT="0.0.0.0:55680" +ENV OTEL_RESOURCE_ATTRIBUTES="service.name=besu-$VERSION" ENV PATH="/opt/besu/bin:${PATH}" ENTRYPOINT ["besu"] @@ -38,4 +44,4 @@ LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.vcs-url="https://github.com/hyperledger/besu.git" \ org.label-schema.vendor="Hyperledger" \ org.label-schema.version=$VERSION \ - org.label-schema.schema-version="1.0" \ No newline at end of file + org.label-schema.schema-version="1.0" diff --git a/docker/openjdk-latest/Dockerfile b/docker/openjdk-latest/Dockerfile index 69f7ae0d6f..74b65721f9 100644 --- a/docker/openjdk-latest/Dockerfile +++ b/docker/openjdk-latest/Dockerfile @@ -21,6 +21,12 @@ ENV BESU_RPC_HTTP_HOST 0.0.0.0 ENV BESU_RPC_WS_HOST 0.0.0.0 ENV BESU_GRAPHQL_HTTP_HOST 0.0.0.0 ENV BESU_PID_PATH "/tmp/pid" +# Tracing defaults +# To enable tracing, uncomment next line +#ENV TRACING=ENABLED +ENV OTEL_EXPORTER=otlp +ENV OTEL_OTLP_ENDPOINT="0.0.0.0:55680" +ENV OTEL_RESOURCE_ATTRIBUTES="service.name=besu-$VERSION" ENV PATH="/opt/besu/bin:${PATH}" ENTRYPOINT ["besu"] @@ -38,4 +44,4 @@ LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.vcs-url="https://github.com/hyperledger/besu.git" \ org.label-schema.vendor="Hyperledger" \ org.label-schema.version=$VERSION \ - org.label-schema.schema-version="1.0" \ No newline at end of file + org.label-schema.schema-version="1.0" diff --git a/docs/tracing/README.md b/docs/tracing/README.md new file mode 100644 index 0000000000..bbf1249dc5 --- /dev/null +++ b/docs/tracing/README.md @@ -0,0 +1,21 @@ +# Tracing + +Hyperledger Besu integrates with the [open-telemetry](https://open-telemetry.io) project to integrate tracing reporting. + +This allows to report all JSON-RPC traffic as traces. + +To try out this example, start the Open Telemetry Collector and the Zipkin service with: + +`$> docker-compose up` + +Start besu with: + +`$> ./gradlew run --args="--network=dev --rpc-http-enabled"` + +Try interacting with the JSON-RPC API. Here is a simple example using cURL: + +`$> curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":53}' http://localhost:8545` + +Open the Zipkin UI by browsing to http://localhost:9411/ + +You will be able to see the detail of your traces. diff --git a/docs/tracing/docker-compose.yml b/docs/tracing/docker-compose.yml new file mode 100644 index 0000000000..79e1ecf533 --- /dev/null +++ b/docs/tracing/docker-compose.yml @@ -0,0 +1,22 @@ +version: "3" +services: + otel-collector: + image: otel/opentelemetry-collector-contrib:0.11.0 + command: ["--config=/etc/otel-collector-config.yml"] + volumes: + - ./otel-collector-config.yml:/etc/otel-collector-config.yml + ports: + - "1888:1888" # pprof extension + - "8888:8888" # Prometheus metrics exposed by the collector + - "8889:8889" # Prometheus exporter metrics + - "13133:13133" # health_check extension + - "55680:55680" # zpages extension + depends_on: + - zipkin + + #Zipkin + zipkin: + image: openzipkin/zipkin + container_name: zipkin + ports: + - 9411:9411 diff --git a/docs/tracing/otel-collector-config.yml b/docs/tracing/otel-collector-config.yml new file mode 100644 index 0000000000..2d8f2d9839 --- /dev/null +++ b/docs/tracing/otel-collector-config.yml @@ -0,0 +1,25 @@ +receivers: + otlp: + protocols: + grpc: + http: + +exporters: + zipkin: + endpoint: "http://zipkin:9411/api/v2/spans" + +processors: + batch: + +extensions: + health_check: + pprof: + zpages: + +service: + extensions: [pprof, zpages, health_check] + pipelines: + traces: + receivers: [otlp] + exporters: [zipkin] + processors: [batch] diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 2993c8f89f..ee7ea6595e 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -49,6 +49,8 @@ dependencyManagement { dependency 'io.pkts:pkts-core:3.0.7' + dependency group: 'io.opentelemetry.instrumentation.auto', name: 'opentelemetry-javaagent', version: '0.8.0', classifier: 'all' + dependency 'io.prometheus:simpleclient:0.9.0' dependency 'io.prometheus:simpleclient_common:0.9.0' dependency 'io.prometheus:simpleclient_hotspot:0.9.0'