This is an automated email from the ASF dual-hosted git repository. toulmean pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git
The following commit(s) were added to refs/heads/main by this push: new 2365caa initial sample new 511c591 Merge pull request #337 from atoulme/jsonrpc_example 2365caa is described below commit 2365caa3a978c163b04c7990d2601070e7df8975 Author: Antoine Toulme <anto...@lunar-ocean.com> AuthorDate: Mon Aug 9 23:44:34 2021 -0700 initial sample --- examples/jsonrpc/README.md | 65 ++++++++++++++++++++++ examples/jsonrpc/config.toml | 25 +++++++++ examples/jsonrpc/docker-compose.yml | 45 +++++++++++++++ .../resources => examples/jsonrpc}/logback.xml | 3 + examples/jsonrpc/otel-collector-config.yml | 53 ++++++++++++++++++ .../org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt | 4 +- .../org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt | 4 ++ jsonrpc-app/src/main/resources/logback.xml | 2 +- metrics/build.gradle | 1 + .../org/apache/tuweni/metrics/MetricsService.kt | 19 ++++++- 10 files changed, 216 insertions(+), 5 deletions(-) diff --git a/examples/jsonrpc/README.md b/examples/jsonrpc/README.md new file mode 100644 index 0000000..26112f7 --- /dev/null +++ b/examples/jsonrpc/README.md @@ -0,0 +1,65 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You 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. +--> +# JSON-RPC proxy + +The JSON-RPC proxy allows you to cache requests to a JSON-RPC endpoint. + +This example showcases how to use the proxy with a public service. + +## Requirements + +This example requires Docker, Docker Compose 1.25, Java 11 and Gradle > 6. + +## Steps + +### Check out this repository + +`$> git clone https://github.com/apache/incubator-tuweni` + +### Build the image + +You need to install the Gradle wrapper the first time you make a checkout: + +`$> gradle setup` + +You can now run gradle to build the docker image: + +`$> ./gradlew dist::buildBinImage` + +The build should end with similar lines: +```bash + ---> be57b46c612c +Successfully built be57b46c612c +Successfully tagged apache-tuweni/tuweni:2.1.0-SNAPSHOT +Created image with ID 'be57b46c612c'. + +BUILD SUCCESSFUL in 1m 13s +256 actionable tasks: 2 executed, 254 up-to-date +``` + +### Run the example + +Make sure the image you just tagged matches the one in the `docker_compose.yml` file. + +Run Docker: + +```bash +docker-compose up +``` + + + diff --git a/examples/jsonrpc/config.toml b/examples/jsonrpc/config.toml new file mode 100644 index 0000000..fcc57c6 --- /dev/null +++ b/examples/jsonrpc/config.toml @@ -0,0 +1,25 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +endpointUrl="https://rpc.xdaichain.com/" # service URL +port=8545 +networkInterface="0.0.0.0" +cacheEnabled=true +cachedMethods=[""] # All methods are cached +cacheStoragePath="/var/jsonrpccache" # Cache location +allowedMethods=[""] # All methods are enabled +metricsGrpcPushEnabled=true +metricsPrometheusEnabled=false +metricsGrpcTimeout=2000 +metricsGrpcEndpoint="http://otelcollector:4317" \ No newline at end of file diff --git a/examples/jsonrpc/docker-compose.yml b/examples/jsonrpc/docker-compose.yml new file mode 100644 index 0000000..70b3837 --- /dev/null +++ b/examples/jsonrpc/docker-compose.yml @@ -0,0 +1,45 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +version: "3" +services: + jsonrpc: + container_name: jsonrpc + image: apache-tuweni/tuweni:2.1.0-SNAPSHOT + volumes: + - ./config.toml:/etc/config.toml + - ./logback.xml:/usr/tuweni/bin/logback.xml + entrypoint: /usr/tuweni/bin/jsonrpc + command: /etc/config.toml + environment: + - JAVA_OPTS="-Dlogback.configurationFile=/usr/tuweni/bin/logback.xml" + ports: + - 8545:8545 + otelcollector: + container_name: otelcollector + image: otel/opentelemetry-collector-contrib:0.31.0 + command: ["--config=/etc/otel-collector-config.yml", "--log-level=DEBUG"] + volumes: + - ./otel-collector-config.yml:/etc/otel-collector-config.yml + metricsviewer: + image: docker.io/tmio/metrics-ui + container_name: metricsviewer + ports: + - 8080:8080 + # Zipkin + zipkin: + container_name: zipkin + image: openzipkin/zipkin + ports: + - 9411:9411 \ No newline at end of file diff --git a/jsonrpc-app/src/main/resources/logback.xml b/examples/jsonrpc/logback.xml similarity index 90% copy from jsonrpc-app/src/main/resources/logback.xml copy to examples/jsonrpc/logback.xml index a13e46b..411f33b 100644 --- a/jsonrpc-app/src/main/resources/logback.xml +++ b/examples/jsonrpc/logback.xml @@ -20,6 +20,9 @@ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> + <logger name="io.opentelemetry" level="trace" additivity="true"> + <appender-ref ref="STDOUT" /> + </logger> <root level="trace"> <appender-ref ref="STDOUT" /> diff --git a/examples/jsonrpc/otel-collector-config.yml b/examples/jsonrpc/otel-collector-config.yml new file mode 100644 index 0000000..e5fc7d6 --- /dev/null +++ b/examples/jsonrpc/otel-collector-config.yml @@ -0,0 +1,53 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + +exporters: + otlp: + endpoint: "metricsviewer:4317" + insecure: true + zipkin: + endpoint: "http://zipkin:9411/api/v2/spans" + logging: + loglevel: debug + sampling_initial: 5 + sampling_thereafter: 200 +processors: + batch: + +extensions: + health_check: + endpoint: 0.0.0.0:13133 + pprof: + endpoint: :1888 + zpages: + endpoint: :55679 + +service: + extensions: [pprof, zpages, health_check] + pipelines: + metrics: + receivers: [otlp] + processors: [batch] + exporters: [otlp, logging] + traces: + receivers: [ otlp ] + processors: [ batch ] + exporters: [ zipkin, logging ] \ No newline at end of file diff --git a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt index 2edb44a..d285987 100644 --- a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt +++ b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt @@ -89,7 +89,9 @@ object JSONRPCApp { port = config.metricsPort(), networkInterface = config.metricsNetworkInterface(), enableGrpcPush = config.metricsGrpcPushEnabled(), - enablePrometheus = config.metricsPrometheusEnabled() + enablePrometheus = config.metricsPrometheusEnabled(), + grpcEndpoint = config.metricsGrpcEndpoint(), + grpcTimeout = config.metricsGrpcTimeout(), ) val vertx = Vertx.vertx(VertxOptions().setTracingOptions(OpenTelemetryOptions(metricsService.openTelemetry))) val app = JSONRPCApplication(vertx, config, metricsService) diff --git a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt index dea8476..62917f8 100644 --- a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt +++ b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt @@ -55,6 +55,8 @@ class JSONRPCConfig(val filePath: Path) { .addBoolean("cacheEnabled", false, "Enable caching", null) .addString("cacheStoragePath", "", "Location of cache storage", null) .addInteger("maxConcurrentRequests", 30, "Maximum concurrent requests", null) + .addString("metricsGrpcEndpoint", "http://localhost:4317", "Metrics GRPC push endpoint", null) + .addLong("metricsGrpcTimeout", 2000, "Metrics GRPC push timeout", null) .toSchema() } @@ -87,4 +89,6 @@ class JSONRPCConfig(val filePath: Path) { fun cacheEnabled() = config.getBoolean("cacheEnabled") fun cacheStoragePath() = config.getString("cacheStoragePath") fun maxConcurrentRequests() = config.getInteger("maxConcurrentRequests") + fun metricsGrpcEndpoint() = config.getString("metricsGrpcEndpoint") + fun metricsGrpcTimeout() = config.getLong("metricsGrpcTimeout") } diff --git a/jsonrpc-app/src/main/resources/logback.xml b/jsonrpc-app/src/main/resources/logback.xml index a13e46b..cb63fd5 100644 --- a/jsonrpc-app/src/main/resources/logback.xml +++ b/jsonrpc-app/src/main/resources/logback.xml @@ -21,7 +21,7 @@ </encoder> </appender> - <root level="trace"> + <root level="info"> <appender-ref ref="STDOUT" /> </root> </configuration> \ No newline at end of file diff --git a/metrics/build.gradle b/metrics/build.gradle index b5cf6ed..8353031 100644 --- a/metrics/build.gradle +++ b/metrics/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation 'io.prometheus:simpleclient_httpserver' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core' + implementation 'org.slf4j:slf4j-api' testImplementation project(':junit') testImplementation 'org.bouncycastle:bcprov-jdk15on' diff --git a/metrics/src/main/kotlin/org/apache/tuweni/metrics/MetricsService.kt b/metrics/src/main/kotlin/org/apache/tuweni/metrics/MetricsService.kt index 1fde892..e4507a2 100644 --- a/metrics/src/main/kotlin/org/apache/tuweni/metrics/MetricsService.kt +++ b/metrics/src/main/kotlin/org/apache/tuweni/metrics/MetricsService.kt @@ -29,7 +29,9 @@ import io.opentelemetry.sdk.trace.export.BatchSpanProcessor import io.opentelemetry.semconv.resource.attributes.ResourceAttributes import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.HTTPServer +import org.slf4j.LoggerFactory import java.net.InetSocketAddress +import java.util.concurrent.TimeUnit class MetricsService( jobName: String, @@ -38,8 +40,14 @@ class MetricsService( networkInterface: String = "0.0.0.0", enablePrometheus: Boolean = true, enableGrpcPush: Boolean = true, + grpcEndpoint: String = "localhost:4317", + grpcTimeout: Long = 2000, ) { + companion object { + private val logger = LoggerFactory.getLogger(MetricsService::class.java) + } + private val server: HTTPServer? val meterSdkProvider: SdkMeterProvider val openTelemetry: OpenTelemetrySdk @@ -47,7 +55,8 @@ class MetricsService( private val periodicReader: IntervalMetricReader? init { - val exporter = OtlpGrpcMetricExporter.getDefault() + val exporter = OtlpGrpcMetricExporter.builder().setEndpoint(grpcEndpoint).setTimeout(grpcTimeout, TimeUnit.MILLISECONDS).build() + logger.info("Starting metrics service") val resource = Resource.getDefault() .merge( Resource.create( @@ -56,21 +65,25 @@ class MetricsService( ) meterSdkProvider = SdkMeterProvider.builder().setResource(resource).build() if (enableGrpcPush) { + logger.info("Starting GRPC push metrics service") val builder = IntervalMetricReader.builder() .setExportIntervalMillis(reportingIntervalMillis) .setMetricProducers(setOf(meterSdkProvider)) .setMetricExporter(exporter) periodicReader = builder.buildAndStart() - periodicReader.start() } else { periodicReader = null } - spanProcessor = BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build() + spanProcessor = BatchSpanProcessor.builder( + OtlpGrpcSpanExporter.builder().setEndpoint(grpcEndpoint) + .setTimeout(grpcTimeout, TimeUnit.MILLISECONDS).build() + ).build() openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(SdkTracerProvider.builder().addSpanProcessor(spanProcessor).build()) .build() if (enablePrometheus) { + logger.info("Starting Prometheus metrics service") val prometheusRegistry = CollectorRegistry(true) PrometheusCollector.builder() .setMetricProducer(meterSdkProvider) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@tuweni.apache.org For additional commands, e-mail: commits-h...@tuweni.apache.org