From 4b0ccf9bb5f2da43f558bc2491a18a341679b040 Mon Sep 17 00:00:00 2001 From: KirillPamPam Date: Tue, 21 Nov 2023 12:38:07 +0400 Subject: [PATCH] Add client version to labels (#346) --- .../subscribe/EthereumLabelsDetector.kt | 45 +++++++++++++------ .../EthereumLabelsDetectorSpec.groovy | 11 ++--- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt index 29067ced..f0e885c3 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt @@ -9,6 +9,7 @@ import io.emeraldpay.dshackle.upstream.LabelsDetector import io.emeraldpay.dshackle.upstream.ethereum.EthereumArchiveBlockNumberReader import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import org.slf4j.LoggerFactory import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -18,6 +19,10 @@ class EthereumLabelsDetector( ) : LabelsDetector { private val blockNumberReader = EthereumArchiveBlockNumberReader(reader) + companion object { + private val log = LoggerFactory.getLogger(EthereumLabelsDetector::class.java) + } + override fun detectLabels(): Flux> { return Flux.merge( detectNodeType(), @@ -25,21 +30,25 @@ class EthereumLabelsDetector( ) } - private fun detectNodeType(): Mono?> { + private fun detectNodeType(): Flux?> { return reader .read(JsonRpcRequest("web3_clientVersion", listOf())) .flatMap(JsonRpcResponse::requireResult) - .mapNotNull { - val node = objectMapper.readValue(it) + .map { objectMapper.readValue(it) } + .flatMapMany { node -> + val labels = mutableListOf>() if (node.isTextual) { - nodeType(node.textValue())?.run { - "client_type" to this + clientType(node.textValue())?.let { + labels.add("client_type" to it) + } + clientVersion(node.textValue())?.let { + labels.add("client_version" to it) } - } else { - null } + + Flux.fromIterable(labels) } - .onErrorResume { Mono.empty() } + .onErrorResume { Flux.empty() } } private fun detectArchiveNode(): Mono> { @@ -60,16 +69,26 @@ class EthereumLabelsDetector( ).flatMap(JsonRpcResponse::requireResult) } - private fun nodeType(nodeType: String): String? { - return if (nodeType.contains("erigon", true)) { + private fun clientVersion(client: String): String? { + val firstSlash = client.indexOf("/") + val secondSlash = client.indexOf("/", firstSlash + 1) + if (firstSlash == -1 || secondSlash == -1 || secondSlash < firstSlash) { + return null + } + return client.substring(firstSlash + 1, secondSlash) + } + + private fun clientType(client: String): String? { + return if (client.contains("erigon", true)) { "erigon" - } else if (nodeType.contains("geth", true)) { + } else if (client.contains("geth", true)) { "geth" - } else if (nodeType.contains("bor", true)) { + } else if (client.contains("bor", true)) { "bor" - } else if (nodeType.contains("nethermind", true)) { + } else if (client.contains("nethermind", true)) { "nethermind" } else { + log.debug("Unknown client type: {}", client) null } } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy index 728366f4..48983254 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy @@ -35,16 +35,17 @@ class EthereumLabelsDetectorSpec extends Specification { StepVerifier.create(act) .expectNext( new Pair("client_type", clientType), + new Pair("client_version", version), new Pair("archive", "true") ) .expectComplete() .verify(Duration.ofSeconds(1)) where: - response | clientType - "Nethermind/v1.19.3+e8ac1da4/linux-x64/dotnet7.0.8" | "nethermind" - "Geth/v1.12.0-stable-e501b3b0/linux-amd64/go1.20.3" | "geth" - "Erigon/v1.12.0-stable-e501b3b0/linux-amd64/go1.20.3" | "erigon" - "Bor/v0.4.0/linux-amd64/go1.19.10" | "bor" + response | clientType | version + "Nethermind/v1.19.3+e8ac1da4/linux-x64/dotnet7.0.8" | "nethermind" | "v1.19.3+e8ac1da4" + "Geth/v1.12.0-stable-e501b3b0/linux-amd64/go1.20.3" | "geth" | "v1.12.0-stable-e501b3b0" + "Erigon/v1.12.0-stable-e501b3b0/linux-amd64/go1.20.3" | "erigon" | "v1.12.0-stable-e501b3b0" + "Bor/v0.4.0/linux-amd64/go1.19.10" | "bor" | "v0.4.0" } def "No any label"() {