Netty metrics (#745)

This commit is contained in:
KirillPamPam
2025-11-19 13:14:52 +04:00
committed by GitHub
parent d1ae0b4052
commit 2c9352a4de
13 changed files with 56 additions and 7 deletions

View File

@@ -65,7 +65,7 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref =
lettuce-core = "io.lettuce:lettuce-core:5.2.2.RELEASE" lettuce-core = "io.lettuce:lettuce-core:5.2.2.RELEASE"
micrometer-registry-prometheus = "io.micrometer:micrometer-registry-prometheus:1.5.6" micrometer-registry-prometheus = "io.micrometer:micrometer-registry-prometheus:1.10.0"
mockserver-netty = "org.mock-server:mockserver-netty:5.11.2" mockserver-netty = "org.mock-server:mockserver-netty:5.11.2"

View File

@@ -18,21 +18,32 @@ package io.emeraldpay.dshackle.config
class MonitoringConfig( class MonitoringConfig(
val enabled: Boolean, val enabled: Boolean,
val prometheus: PrometheusConfig, val prometheus: PrometheusConfig,
val nettyMetricsConfig: NettyMetricsConfig,
) { ) {
companion object { companion object {
fun default(): MonitoringConfig { fun default(): MonitoringConfig {
return MonitoringConfig(true, PrometheusConfig.default()) return MonitoringConfig(true, PrometheusConfig.default(), NettyMetricsConfig.default())
} }
fun disabled(): MonitoringConfig { fun disabled(): MonitoringConfig {
return MonitoringConfig(false, PrometheusConfig.disabled()) return MonitoringConfig(false, PrometheusConfig.disabled(), NettyMetricsConfig.default())
} }
} }
var enableJvm: Boolean = true var enableJvm: Boolean = true
var enableExtended: Boolean = false var enableExtended: Boolean = false
data class NettyMetricsConfig(
val enabled: Boolean,
) {
companion object {
fun default(): NettyMetricsConfig {
return NettyMetricsConfig(false)
}
}
}
data class PrometheusConfig( data class PrometheusConfig(
val enabled: Boolean, val enabled: Boolean,
val path: String, val path: String,

View File

@@ -32,13 +32,22 @@ class MonitoringConfigReader : YamlConfigReader<MonitoringConfig>() {
return MonitoringConfig.disabled() return MonitoringConfig.disabled()
} }
val prometheus = readPrometheus(getMapping(input, "prometheus")) val prometheus = readPrometheus(getMapping(input, "prometheus"))
return MonitoringConfig(enabled, prometheus).also { conf -> val netty = readNettyCfg(getMapping(input, "netty-metrics"))
return MonitoringConfig(enabled, prometheus, netty).also { conf ->
getValueAsBool(input, "JVM")?.let { conf.enableJvm = it } getValueAsBool(input, "JVM")?.let { conf.enableJvm = it }
getValueAsBool(input, "jvm")?.let { conf.enableJvm = it } getValueAsBool(input, "jvm")?.let { conf.enableJvm = it }
getValueAsBool(input, "extended")?.let { conf.enableExtended = it } getValueAsBool(input, "extended")?.let { conf.enableExtended = it }
} }
} }
private fun readNettyCfg(input: MappingNode?): MonitoringConfig.NettyMetricsConfig {
if (input == null) {
return MonitoringConfig.NettyMetricsConfig.default()
}
val enabled = getValueAsBool(input, "enabled") ?: false
return MonitoringConfig.NettyMetricsConfig(enabled)
}
private fun readPrometheus(input: MappingNode?): MonitoringConfig.PrometheusConfig { private fun readPrometheus(input: MappingNode?): MonitoringConfig.PrometheusConfig {
if (input == null) { if (input == null) {
return MonitoringConfig.PrometheusConfig.default() return MonitoringConfig.PrometheusConfig.default()

View File

@@ -86,7 +86,7 @@ open class SchedulersConfig {
size * threadsMultiplier, size * threadsMultiplier,
60L, 60L,
TimeUnit.SECONDS, TimeUnit.SECONDS,
LinkedBlockingQueue(1000), LinkedBlockingQueue(10000),
CustomizableThreadFactory("$name-"), CustomizableThreadFactory("$name-"),
) )

View File

@@ -3,6 +3,7 @@ package io.emeraldpay.dshackle.startup.configure
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.FileResolver import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.MonitoringConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.upstream.BasicHttpFactory import io.emeraldpay.dshackle.upstream.BasicHttpFactory
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.BlockValidator
@@ -24,6 +25,7 @@ open class GenericConnectorFactoryCreator(
private val headScheduler: Scheduler, private val headScheduler: Scheduler,
private val wsScheduler: Scheduler, private val wsScheduler: Scheduler,
private val headLivenessScheduler: Scheduler, private val headLivenessScheduler: Scheduler,
private val monitoringCfg: MonitoringConfig,
) : ConnectorFactoryCreator { ) : ConnectorFactoryCreator {
protected val log = LoggerFactory.getLogger(this::class.java) protected val log = LoggerFactory.getLogger(this::class.java)
@@ -66,7 +68,14 @@ open class GenericConnectorFactoryCreator(
} }
} }
urls?.add(endpoint.url) urls?.add(endpoint.url)
BasicHttpFactory(endpoint.url.toString(), endpoint.maxConnections, endpoint.queueSize, conn.basicAuth, tls) BasicHttpFactory(
endpoint.url.toString(),
endpoint.maxConnections,
endpoint.queueSize,
conn.basicAuth,
tls,
monitoringCfg.nettyMetricsConfig.enabled,
)
} }
} }

View File

@@ -4,6 +4,7 @@ import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.FileResolver import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.MonitoringConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.upstream.BlockValidator import io.emeraldpay.dshackle.upstream.BlockValidator
import io.emeraldpay.dshackle.upstream.TonCompoundHttpFactory import io.emeraldpay.dshackle.upstream.TonCompoundHttpFactory
@@ -20,12 +21,14 @@ class RestConnectorFactoryCreator(
fileResolver: FileResolver, fileResolver: FileResolver,
private val headScheduler: Scheduler, private val headScheduler: Scheduler,
private val headLivenessScheduler: Scheduler, private val headLivenessScheduler: Scheduler,
monitoringCfg: MonitoringConfig,
) : GenericConnectorFactoryCreator( ) : GenericConnectorFactoryCreator(
fileResolver, fileResolver,
Schedulers.single(), Schedulers.single(),
headScheduler, headScheduler,
Schedulers.single(), Schedulers.single(),
headLivenessScheduler, headLivenessScheduler,
monitoringCfg,
) { ) {
override fun createConnectorFactory( override fun createConnectorFactory(
id: String, id: String,

View File

@@ -17,6 +17,7 @@ class BasicHttpFactory(
private val queueSize: Int, private val queueSize: Int,
private val basicAuth: AuthConfig.ClientBasicAuth?, private val basicAuth: AuthConfig.ClientBasicAuth?,
private val tls: ByteArray?, private val tls: ByteArray?,
private val nettyMetricsEnabled: Boolean,
) : HttpFactory { ) : HttpFactory {
private val log = LoggerFactory.getLogger(this::class.java) private val log = LoggerFactory.getLogger(this::class.java)
@@ -39,6 +40,7 @@ class BasicHttpFactory(
.description("Number of failures of HTTP JSON RPC requests") .description("Number of failures of HTTP JSON RPC requests")
.tags(metricsTags) .tags(metricsTags)
.register(Metrics.globalRegistry), .register(Metrics.globalRegistry),
nettyMetricsEnabled,
) )
if (chain.type.apiType == ApiType.REST) { if (chain.type.apiType == ApiType.REST) {

View File

@@ -38,12 +38,21 @@ abstract class HttpReader(
.maxConnections(maxConnections) .maxConnections(maxConnections)
.pendingAcquireMaxCount(queueSize) .pendingAcquireMaxCount(queueSize)
.pendingAcquireTimeout(Duration.ofSeconds(10)) .pendingAcquireTimeout(Duration.ofSeconds(10))
.apply {
if (metrics?.nettyMetricsEnabled ?: false) {
metrics(true)
}
}
.build() .build()
var build = HttpClient.create(connectionProvider) var build = HttpClient.create(connectionProvider)
.compress(true) .compress(true)
.resolver(DefaultAddressResolverGroup.INSTANCE) .resolver(DefaultAddressResolverGroup.INSTANCE)
if (metrics?.nettyMetricsEnabled ?: false) {
build = build.metrics(true) { s -> s }
}
build = build.headers { h -> build = build.headers { h ->
h.add(HttpHeaderNames.CONTENT_TYPE, "application/json") h.add(HttpHeaderNames.CONTENT_TYPE, "application/json")
} }

View File

@@ -21,4 +21,5 @@ import io.micrometer.core.instrument.Timer
class RequestMetrics( class RequestMetrics(
val timer: Timer, val timer: Timer,
val fails: Counter, val fails: Counter,
val nettyMetricsEnabled: Boolean,
) )

View File

@@ -40,6 +40,7 @@ open class WsConnectionFactory(
.description("Number of failures of WebSocket JSON RPC requests") .description("Number of failures of WebSocket JSON RPC requests")
.tags(metricsTags) .tags(metricsTags)
.register(Metrics.globalRegistry), .register(Metrics.globalRegistry),
false,
) )
} }

View File

@@ -295,6 +295,7 @@ class GrpcUpstreams(
.description("Number of failures of Dshackle/gRPC requests") .description("Number of failures of Dshackle/gRPC requests")
.tags(metricsTags) .tags(metricsTags)
.register(Metrics.globalRegistry), .register(Metrics.globalRegistry),
false,
) )
} }

View File

@@ -37,7 +37,8 @@ class JsonRpcHttpReaderSpec extends Specification {
int port = 19332 int port = 19332
RequestMetrics metrics = new RequestMetrics( RequestMetrics metrics = new RequestMetrics(
Timer.builder("test1").register(TestingCommons.meterRegistry), Timer.builder("test1").register(TestingCommons.meterRegistry),
Counter.builder("test2").register(TestingCommons.meterRegistry) Counter.builder("test2").register(TestingCommons.meterRegistry),
false,
) )
def setup() { def setup() {

View File

@@ -4,6 +4,7 @@ import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.FileResolver import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.ChainsConfigReader import io.emeraldpay.dshackle.config.ChainsConfigReader
import io.emeraldpay.dshackle.config.MonitoringConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.foundation.ChainOptionsReader import io.emeraldpay.dshackle.foundation.ChainOptionsReader
import io.emeraldpay.dshackle.startup.configure.GenericConnectorFactoryCreator import io.emeraldpay.dshackle.startup.configure.GenericConnectorFactoryCreator
@@ -37,6 +38,7 @@ class GenericConnectorFactoryCreatorTest {
immediate(), immediate(),
immediate(), immediate(),
immediate(), immediate(),
MonitoringConfig.default(),
) )
var args: List<*>? = null var args: List<*>? = null