You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuweni.apache.org by to...@apache.org on 2021/08/04 18:10:52 UTC
[incubator-tuweni] branch main updated: Add configuration to
monitor different upgrades
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 0b3cb61 Add configuration to monitor different upgrades
new 7086a70 Merge pull request #335 from atoulme/add_multiple_upgrade_configs
0b3cb61 is described below
commit 0b3cb6186404e97a313b726cb4734072ba536739
Author: Antoine Toulme <an...@lunar-ocean.com>
AuthorDate: Tue Aug 3 22:44:09 2021 -0700
Add configuration to monitor different upgrades
---
.../apache/tuweni/config/PropertyValidator.java | 21 +++-
.../org/apache/tuweni/eth/crawler/CrawlerApp.kt | 2 +-
.../org/apache/tuweni/eth/crawler/CrawlerConfig.kt | 93 +++++++++++------
.../tuweni/eth/crawler/RelationalPeerRepository.kt | 116 ++++++++++++++-------
.../tuweni/eth/crawler/rest/ClientsService.kt | 9 +-
5 files changed, 162 insertions(+), 79 deletions(-)
diff --git a/config/src/main/java/org/apache/tuweni/config/PropertyValidator.java b/config/src/main/java/org/apache/tuweni/config/PropertyValidator.java
index 36606a5..c59c01d 100644
--- a/config/src/main/java/org/apache/tuweni/config/PropertyValidator.java
+++ b/config/src/main/java/org/apache/tuweni/config/PropertyValidator.java
@@ -24,6 +24,8 @@ import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
+import com.google.common.base.Strings;
+
/**
* A validator associated with a specific configuration property.
*/
@@ -208,9 +210,9 @@ public interface PropertyValidator<T> {
}
/**
- * A validator that ensures a property, if present, is a well-formed port number.
+ * A validator that ensures a property, if present, is a valid port number.
*
- * @return A validator that ensures a property, if present, is a well-formed number.
+ * @return A validator that ensures a property, if present, is a valid port number.
*/
static PropertyValidator<Integer> isValidPort() {
return (key, position, value) -> {
@@ -222,6 +224,21 @@ public interface PropertyValidator<T> {
}
/**
+ * A validator that ensures a property, if present, is not blank.
+ *
+ * @return A validator that ensures a property, if present, is not blank.
+ */
+ static PropertyValidator<String> isNotBlank() {
+ return (key, position, value) -> {
+ if (value != null && !Strings.isNullOrEmpty(value)) {
+ return singleError(position, "Value of property '" + key + "' is blank");
+ }
+ return noErrors();
+ };
+ }
+
+
+ /**
* Validate a configuration property.
*
* @param key The configuration property key.
diff --git a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerApp.kt b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerApp.kt
index a143225..e0ed78f 100644
--- a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerApp.kt
+++ b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerApp.kt
@@ -118,7 +118,7 @@ class CrawlerApplication(
.load()
flyway.migrate()
val crawlerMeter = metricsService.meterSdkProvider["crawler"]
- val repo = RelationalPeerRepository(ds, config.peerCacheExpiration(), config.clientIdsInterval(), config.clientsStatsDelay(), crawlerMeter, createCoroutineContext())
+ val repo = RelationalPeerRepository(ds, config.peerCacheExpiration(), config.clientIdsInterval(), config.clientsStatsDelay(), crawlerMeter, config.upgradesVersions(), createCoroutineContext())
logger.info("Initial bootnodes: ${config.bootNodes()}")
val scraper = Scraper(
diff --git a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerConfig.kt b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerConfig.kt
index 3be433d..18591bd 100644
--- a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerConfig.kt
+++ b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/CrawlerConfig.kt
@@ -18,6 +18,7 @@ package org.apache.tuweni.eth.crawler
import org.apache.tuweni.config.Configuration
import org.apache.tuweni.config.PropertyValidator
+import org.apache.tuweni.config.Schema
import org.apache.tuweni.config.SchemaBuilder
import java.net.URI
import java.nio.file.Path
@@ -48,38 +49,46 @@ class CrawlerConfig(val filePath: Path) {
val mainnetDiscoveryDNS = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net"
- fun schema() = SchemaBuilder.create()
- .addInteger("discoveryPort", 11000, "Discovery service port", PropertyValidator.isValidPort())
- .addString("discoveryNetworkInterface", "127.0.0.1", "Discovery network interface", null)
- .addInteger("rlpxPort", 11000, "RLPx service port", PropertyValidator.inRange(1, 65536))
- .addString("rlpxNetworkInterface", "127.0.0.1", "RLPx network interface", null)
- .addListOfString("bootnodes", mainnetEthereumBootnodes, "Bootnodes to discover other peers from", null)
- .addString("discoveryDNS", mainnetDiscoveryDNS, "DNS discovery crawler", null)
- .addLong("discoveryDNSPollingPeriod", 60 * 1000L, "DNS Discovery Polling Period in milliseconds", null)
- .addString(
- "jdbcUrl", System.getProperty("DATABASE_URL", System.getenv("DATABASE_URL")),
- "JDBC URL of the form jdbc:posgresql://localhost:5432", PropertyValidator.isPresent()
- )
- .addInteger("jdbcConnections", 25, "Number of JDBC connections for the connections pool", null)
- .addString("network", "mainnet", "Network to use instead of providing a genesis file.", null)
- .addString("genesisFile", "", "Genesis file to use in hello", null)
- .addInteger("restPort", 1337, "REST port", null)
- .addString("restNetworkInterface", "0.0.0.0", "REST network interface", null)
- .addString("ethstatsNetworkInterface", "0.0.0.0", "Ethstats network interface", null)
- .addInteger("ethstatsPort", 1338, "Ethstats port", null)
- .addString("ethstatsSecret", "changeme", "Ethstats shared secret", null)
- .addLong("peerCacheExpiration", 5 * 60 * 1000L, "Peer data cache expiration", null)
- .addLong("clientIdsInterval", 24 * 60 * 60 * 1000 * 2L, "Client IDs Interval - number of milliseconds to go back in time", null)
- .addLong("clientsStatsDelay", 30 * 1000, "Delay between client stats calculations", null)
- .addLong("rlpxDisconnectionDelay", 10 * 1000L, "RLPx connections disconnection delay", null)
- .addInteger("maxRequestsPerSec", 30, "Number of requests per second over HTTP", null)
- .addInteger("numberOfThreads", 10, "Number of Threads for each thread pool", null)
- .addInteger("metricsPort", 9090, "Metric service port", PropertyValidator.isValidPort())
- .addString("metricsNetworkInterface", "localhost", "Metric service network interface", null)
- .addBoolean("metricsGrpcPushEnabled", false, "Enable pushing metrics to gRPC service", null)
- .addBoolean("metricsPrometheusEnabled", false, "Enable exposing metrics on the Prometheus endpoint", null)
- .addString("corsAllowedOrigins", "*", "CORS allowed domains filter for REST service", null)
- .toSchema()
+ fun schema(): Schema {
+ val schema = SchemaBuilder.create()
+ .addInteger("discoveryPort", 11000, "Discovery service port", PropertyValidator.isValidPort())
+ .addString("discoveryNetworkInterface", "127.0.0.1", "Discovery network interface", null)
+ .addInteger("rlpxPort", 11000, "RLPx service port", PropertyValidator.inRange(1, 65536))
+ .addString("rlpxNetworkInterface", "127.0.0.1", "RLPx network interface", null)
+ .addListOfString("bootnodes", mainnetEthereumBootnodes, "Bootnodes to discover other peers from", null)
+ .addString("discoveryDNS", mainnetDiscoveryDNS, "DNS discovery crawler", null)
+ .addLong("discoveryDNSPollingPeriod", 60 * 1000L, "DNS Discovery Polling Period in milliseconds", null)
+ .addString(
+ "jdbcUrl", System.getProperty("DATABASE_URL", System.getenv("DATABASE_URL")),
+ "JDBC URL of the form jdbc:posgresql://localhost:5432", PropertyValidator.isPresent()
+ )
+ .addInteger("jdbcConnections", 25, "Number of JDBC connections for the connections pool", null)
+ .addString("network", "mainnet", "Network to use instead of providing a genesis file.", null)
+ .addString("genesisFile", "", "Genesis file to use in hello", null)
+ .addInteger("restPort", 1337, "REST port", null)
+ .addString("restNetworkInterface", "0.0.0.0", "REST network interface", null)
+ .addString("ethstatsNetworkInterface", "0.0.0.0", "Ethstats network interface", null)
+ .addInteger("ethstatsPort", 1338, "Ethstats port", null)
+ .addString("ethstatsSecret", "changeme", "Ethstats shared secret", null)
+ .addLong("peerCacheExpiration", 5 * 60 * 1000L, "Peer data cache expiration", null)
+ .addLong("clientIdsInterval", 24 * 60 * 60 * 1000 * 2L, "Client IDs Interval - number of milliseconds to go back in time", null)
+ .addLong("clientsStatsDelay", 30 * 1000, "Delay between client stats calculations", null)
+ .addLong("rlpxDisconnectionDelay", 10 * 1000L, "RLPx connections disconnection delay", null)
+ .addInteger("maxRequestsPerSec", 30, "Number of requests per second over HTTP", null)
+ .addInteger("numberOfThreads", 10, "Number of Threads for each thread pool", null)
+ .addInteger("metricsPort", 9090, "Metric service port", PropertyValidator.isValidPort())
+ .addString("metricsNetworkInterface", "localhost", "Metric service network interface", null)
+ .addBoolean("metricsGrpcPushEnabled", false, "Enable pushing metrics to gRPC service", null)
+ .addBoolean("metricsPrometheusEnabled", false, "Enable exposing metrics on the Prometheus endpoint", null)
+ .addString("corsAllowedOrigins", "*", "CORS allowed domains filter for REST service", null)
+
+ val upgradesSection = SchemaBuilder.create()
+ .addString("name", null, "Upgrade name, eg London or Magneto", PropertyValidator.isNotBlank())
+ .addListOfMap("versions", listOf(), "List of minimum version mappings for the upgrade", null)
+ .toSchema()
+ schema.addSection("upgrades", upgradesSection)
+ return schema.toSchema()
+ }
}
val config = Configuration.fromToml(filePath, schema())
@@ -118,4 +127,24 @@ class CrawlerConfig(val filePath: Path) {
fun metricsGrpcPushEnabled() = config.getBoolean("metricsGrpcPushEnabled")
fun metricsPrometheusEnabled() = config.getBoolean("metricsPrometheusEnabled")
fun corsAllowedOrigins() = config.getString("corsAllowedOrigins")
+
+ fun upgradesVersions(): List<UpgradeConfig> {
+ val upgrades = config.sections("upgrades")
+ val result = mutableListOf<UpgradeConfig>()
+ for (upgrade in upgrades) {
+ val section = config.getConfigurationSection(upgrade)
+ val versions = mutableMapOf<String, String>()
+ for (map in section.getListOfMap("versions")) {
+ for (entry in map.entries) {
+ versions.put(entry.key.toLowerCase(), entry.value.toString())
+ }
+ }
+
+ val upgradeConfig = UpgradeConfig(section.getString("name"), versions)
+ result.add(upgradeConfig)
+ }
+ return result
+ }
}
+
+data class UpgradeConfig(val name: String, val versions: Map<String, String>)
diff --git a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/RelationalPeerRepository.kt b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/RelationalPeerRepository.kt
index 1c769df..ed5b59b 100644
--- a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/RelationalPeerRepository.kt
+++ b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/RelationalPeerRepository.kt
@@ -48,28 +48,21 @@ open class RelationalPeerRepository(
private val clientIdsInterval: Long = 24 * 60 * 60 * 1000 * 2,
private val clientsStatsDelay: Long = 30 * 1000,
private val meter: Meter,
+ private val upgradeConfigs: List<UpgradeConfig> = listOf(),
override val coroutineContext: CoroutineContext = Dispatchers.Default,
) : CoroutineScope, PeerRepository {
companion object {
internal val logger = LoggerFactory.getLogger(RelationalPeerRepository::class.java)
-
- // TODO make this configurable
- val londonClientVersions = mutableMapOf(
- Pair("geth", "v1.10.4"),
- Pair("nethermind", "v1.10.73"),
- Pair("turbogeth", "v2021.06.04-alpha"),
- Pair("turbo-geth", "v2021.06.04-alpha"),
- Pair("erigon", "v2021.06.04-alpha"),
- Pair("besu", "v21.7.0-RC1"),
- Pair("openethereum", "v3.3.0-rc2"),
- Pair("ethereumjs", "v5.4.1")
- )
}
+
private val listeners = mutableListOf<(Peer) -> Unit>()
private val peerCache = ExpiringMap<SECP256K1.PublicKey, String>()
- private val totalClientsGauge = meter.longValueRecorderBuilder("totalClients").setDescription("Number of nodes used to compute client stats").build()
- private val clientCalculationsCounter = meter.longCounterBuilder("clients").setDescription("Number of times clients were computed").build()
+ private val totalClientsGauge =
+ meter.longValueRecorderBuilder("totalClients").setDescription("Number of nodes used to compute client stats")
+ .build()
+ private val clientCalculationsCounter =
+ meter.longCounterBuilder("clients").setDescription("Number of times clients were computed").build()
override fun addListener(listener: (Peer) -> Unit) {
listeners.add(listener)
@@ -121,7 +114,10 @@ open class RelationalPeerRepository(
fun recordInfo(wireConnection: WireConnection, status: Status?) {
dataSource.connection.use { conn ->
- val peer = get(wireConnection.peerPublicKey(), Endpoint(wireConnection.peerHost(), wireConnection.peerPort())) as RepositoryPeer
+ val peer = get(
+ wireConnection.peerPublicKey(),
+ Endpoint(wireConnection.peerHost(), wireConnection.peerPort())
+ ) as RepositoryPeer
val stmt =
conn.prepareStatement(
"insert into nodeInfo(id, createdAt, host, port, publickey, p2pVersion, clientId, capabilities, genesisHash, bestHash, totalDifficulty, identity, disconnectReason) values(?,?,?,?,?,?,?,?,?,?,?,?,?)"
@@ -173,11 +169,16 @@ open class RelationalPeerRepository(
}
}
- internal fun getPeersWithInfo(infoCollected: Long, from: Int? = null, limit: Int? = null): List<PeerConnectionInfoDetails> {
+ internal fun getPeersWithInfo(
+ infoCollected: Long,
+ from: Int? = null,
+ limit: Int? = null,
+ ): List<PeerConnectionInfoDetails> {
dataSource.connection.use { conn ->
- var query = "select distinct nodeinfo.createdAt, nodeinfo.publickey, nodeinfo.p2pversion, nodeinfo.clientId, nodeinfo.capabilities, nodeinfo.genesisHash, nodeinfo.besthash, nodeinfo.totalDifficulty from nodeinfo " +
- " inner join (select identity, max(createdAt) as maxCreatedAt from nodeinfo group by identity) maxSeen " +
- " on nodeinfo.identity = maxSeen.identity and nodeinfo.createdAt = maxSeen.maxCreatedAt where createdAt < ? order by nodeInfo.createdAt desc"
+ var query =
+ "select distinct nodeinfo.createdAt, nodeinfo.publickey, nodeinfo.p2pversion, nodeinfo.clientId, nodeinfo.capabilities, nodeinfo.genesisHash, nodeinfo.besthash, nodeinfo.totalDifficulty from nodeinfo " +
+ " inner join (select identity, max(createdAt) as maxCreatedAt from nodeinfo group by identity) maxSeen " +
+ " on nodeinfo.identity = maxSeen.identity and nodeinfo.createdAt = maxSeen.maxCreatedAt where createdAt < ? order by nodeInfo.createdAt desc"
if (from != null && limit != null) {
query += " limit $limit offset $from"
}
@@ -197,7 +198,18 @@ open class RelationalPeerRepository(
val genesisHash = rs.getString(6) ?: ""
val bestHash = rs.getString(7) ?: ""
val totalDifficulty = rs.getString(8) ?: ""
- result.add(PeerConnectionInfoDetails(createdAt, pubkey, p2pVersion, clientId, capabilities, genesisHash, bestHash, totalDifficulty))
+ result.add(
+ PeerConnectionInfoDetails(
+ createdAt,
+ pubkey,
+ p2pVersion,
+ clientId,
+ capabilities,
+ genesisHash,
+ bestHash,
+ totalDifficulty
+ )
+ )
}
return result
}
@@ -227,8 +239,8 @@ open class RelationalPeerRepository(
}
private var clientIds: List<ClientInfo>? = null
- private var londonStats: ClientReadyStats? = null
private var clientsStats: Map<String, Map<String, Long>>? = null
+ private var upgradeStats: MutableMap<String, ClientReadyStats> = mutableMapOf()
private val started = AtomicBoolean(false)
fun start() {
@@ -240,23 +252,28 @@ open class RelationalPeerRepository(
val newClientIds = getClientIdsInternal()
logger.info("Found client ids ${newClientIds.size}")
clientIds = newClientIds
- var londonReady = 0
- var total = 0
val newClientsStats = mutableMapOf<String, MutableMap<String, Long>>()
+ val total = newClientIds.stream().mapToInt { it.count }.sum()
+
newClientIds.forEach { newClientCount ->
- total += newClientCount.count
- val clientVersion = ClientIdInfo(newClientCount.clientId)
- val versionStats = newClientsStats.computeIfAbsent(clientVersion.name) { mutableMapOf() }
- val statsCount = versionStats[clientVersion.version] ?: 0
- versionStats[clientVersion.version] = statsCount + newClientCount.count
- londonClientVersions[clientVersion.name().toLowerCase()]?.let { londonVersion ->
- if (clientVersion >= londonVersion) {
- londonReady += newClientCount.count
+ val clientIdInfo = ClientIdInfo(newClientCount.clientId)
+ val versionStats = newClientsStats.computeIfAbsent(clientIdInfo.name) { mutableMapOf() }
+ val statsCount = versionStats[clientIdInfo.version] ?: 0
+ versionStats[clientIdInfo.version] = statsCount + newClientCount.count
+ }
+ for (upgradeConfig in upgradeConfigs) {
+ var upgradeReady = 0
+ newClientIds.forEach { newClientCount ->
+ val clientIdInfo = ClientIdInfo(newClientCount.clientId)
+ upgradeConfig.versions.get(clientIdInfo.name().toLowerCase())?.let { upgradeVersion ->
+ if (clientIdInfo >= upgradeVersion) {
+ upgradeReady += newClientCount.count
+ }
}
}
+ upgradeStats.put(upgradeConfig.name, ClientReadyStats(total, upgradeReady))
}
clientsStats = newClientsStats
- londonStats = ClientReadyStats(total, londonReady)
totalClientsGauge.record(total.toLong())
clientCalculationsCounter.add(1)
@@ -269,7 +286,7 @@ open class RelationalPeerRepository(
started.set(false)
}
- internal fun getLondonStats() = londonStats
+ internal fun getUpgradeStats() = upgradeStats
internal fun getClientIds(): List<ClientInfo> = clientIds ?: listOf()
@@ -277,7 +294,8 @@ open class RelationalPeerRepository(
internal fun getClientIdsInternal(): List<ClientInfo> {
dataSource.connection.use { conn ->
- val sql = "select clients.clientId, count(clients.clientId) from (select nodeinfo.clientId, nodeInfo.createdAt from nodeinfo inner join (select identity, max(createdAt) as maxCreatedAt from nodeinfo group by identity) maxSeen on nodeinfo.identity = maxSeen.identity and nodeinfo.createdAt = maxSeen.maxCreatedAt) as clients where clients.createdAt > ? group by clients.clientId"
+ val sql =
+ "select clients.clientId, count(clients.clientId) from (select nodeinfo.clientId, nodeInfo.createdAt from nodeinfo inner join (select identity, max(createdAt) as maxCreatedAt from nodeinfo group by identity) maxSeen on nodeinfo.identity = maxSeen.identity and nodeinfo.createdAt = maxSeen.maxCreatedAt) as clients where clients.createdAt > ? group by clients.clientId"
val stmt =
conn.prepareStatement(sql)
stmt.use {
@@ -299,9 +317,10 @@ open class RelationalPeerRepository(
internal fun getPeerWithInfo(infoCollected: Long, publicKey: String): PeerConnectionInfoDetails? {
dataSource.connection.use { conn ->
- var query = "select distinct nodeinfo.createdAt, nodeinfo.publickey, nodeinfo.p2pversion, nodeinfo.clientId, nodeinfo.capabilities, nodeinfo.genesisHash, nodeinfo.besthash, nodeinfo.totalDifficulty from nodeinfo " +
- " inner join (select identity, max(createdAt) as maxCreatedAt from nodeinfo group by identity) maxSeen " +
- " on nodeinfo.identity = maxSeen.identity and nodeinfo.createdAt = maxSeen.maxCreatedAt where createdAt < ? and nodeinfo.publickey = ? order by nodeInfo.createdAt desc"
+ var query =
+ "select distinct nodeinfo.createdAt, nodeinfo.publickey, nodeinfo.p2pversion, nodeinfo.clientId, nodeinfo.capabilities, nodeinfo.genesisHash, nodeinfo.besthash, nodeinfo.totalDifficulty from nodeinfo " +
+ " inner join (select identity, max(createdAt) as maxCreatedAt from nodeinfo group by identity) maxSeen " +
+ " on nodeinfo.identity = maxSeen.identity and nodeinfo.createdAt = maxSeen.maxCreatedAt where createdAt < ? and nodeinfo.publickey = ? order by nodeInfo.createdAt desc"
val stmt =
conn.prepareStatement(query)
stmt.use {
@@ -318,7 +337,16 @@ open class RelationalPeerRepository(
val genesisHash = rs.getString(6) ?: ""
val bestHash = rs.getString(7) ?: ""
val totalDifficulty = rs.getString(8) ?: ""
- return PeerConnectionInfoDetails(createdAt, pubkey, p2pVersion, clientId, capabilities, genesisHash, bestHash, totalDifficulty)
+ return PeerConnectionInfoDetails(
+ createdAt,
+ pubkey,
+ p2pVersion,
+ clientId,
+ capabilities,
+ genesisHash,
+ bestHash,
+ totalDifficulty
+ )
} else {
return null
}
@@ -326,10 +354,20 @@ open class RelationalPeerRepository(
}
}
}
+
internal data class ClientReadyStats(val total: Int, val ready: Int)
internal data class ClientInfo(val clientId: String, val count: Int)
internal data class PeerConnectionInfo(val nodeId: SECP256K1.PublicKey, val host: String, val port: Int)
-internal data class PeerConnectionInfoDetails(val createdAt: Long, val nodeId: SECP256K1.PublicKey, val p2pVersion: Int, val clientId: String, val capabilities: String, val genesisHash: String, val bestHash: String, val totalDifficulty: String)
+internal data class PeerConnectionInfoDetails(
+ val createdAt: Long,
+ val nodeId: SECP256K1.PublicKey,
+ val p2pVersion: Int,
+ val clientId: String,
+ val capabilities: String,
+ val genesisHash: String,
+ val bestHash: String,
+ val totalDifficulty: String,
+)
internal class RepositoryPeer(
override val nodeId: SECP256K1.PublicKey,
diff --git a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/rest/ClientsService.kt b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/rest/ClientsService.kt
index 076d04a..c7e048f 100644
--- a/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/rest/ClientsService.kt
+++ b/eth-crawler/src/main/kotlin/org/apache/tuweni/eth/crawler/rest/ClientsService.kt
@@ -23,6 +23,7 @@ import org.apache.tuweni.eth.crawler.RelationalPeerRepository
import javax.servlet.ServletContext
import javax.ws.rs.GET
import javax.ws.rs.Path
+import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
@@ -51,12 +52,10 @@ class ClientsService {
return result
}
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("london/stats")
- fun getLondonStats(): String {
+ @Path("{upgrade}/stats")
+ fun getClientStats(@PathParam("upgrade") upgrade: String): String {
val repo = context!!.getAttribute("repo") as RelationalPeerRepository
- val peers = repo.getLondonStats()
+ val peers = repo.getUpgradeStats()[upgrade]
val result = mapper.writeValueAsString(peers)
return result
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tuweni.apache.org
For additional commands, e-mail: commits-help@tuweni.apache.org