From 81801d4566364facca4a5303ea24e3db8cd39f44 Mon Sep 17 00:00:00 2001 From: Christian Sailer Date: Tue, 20 Feb 2018 11:04:08 +0000 Subject: [PATCH] Graphite reporter polish (#465) * Improve generation of default graphite prefix and add an sanitatization for all graphite prefixes (including warning if a custom name needs to be changed) * Convert graphite rates to per second * Code review: make it IPv6 safe --- .../net/corda/node/internal/EnterpriseNode.kt | 20 ++++++++----- .../corda/node/internal/EnterpriseNodeTest.kt | 29 +++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 node/src/test/kotlin/net/corda/node/internal/EnterpriseNodeTest.kt diff --git a/node/src/main/kotlin/net/corda/node/internal/EnterpriseNode.kt b/node/src/main/kotlin/net/corda/node/internal/EnterpriseNode.kt index d4bb045015..1195c3ae3a 100644 --- a/node/src/main/kotlin/net/corda/node/internal/EnterpriseNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/EnterpriseNode.kt @@ -14,16 +14,15 @@ import net.corda.core.internal.concurrent.thenMatch import net.corda.core.utilities.loggerFor import net.corda.node.VersionInfo import net.corda.node.internal.cordapp.CordappLoader -import net.corda.node.services.config.GraphiteOptions import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.RelayConfiguration import net.corda.node.services.statemachine.MultiThreadedStateMachineManager -import net.corda.node.services.statemachine.SingleThreadedStateMachineManager import net.corda.node.services.statemachine.StateMachineManager import net.corda.nodeapi.internal.persistence.CordaPersistence import org.fusesource.jansi.Ansi import org.fusesource.jansi.AnsiConsole import java.io.IOException +import java.net.Inet6Address import java.net.InetAddress import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -38,11 +37,18 @@ open class EnterpriseNode(configuration: NodeConfiguration, private val logger by lazy { loggerFor() } private fun defaultGraphitePrefix(legalName: CordaX500Name): String { - return legalName.organisation + "_" + InetAddress.getLocalHost().hostAddress.trim().replace(".", "_") + return (legalName.organisation + "_" + legalName.locality + "_" + legalName.country + "_" + Inet6Address.getLocalHost().hostAddress) } - private fun getGraphitePrefix(configuration: NodeConfiguration): String { - return configuration.graphiteOptions!!.prefix ?: defaultGraphitePrefix(configuration.myLegalName) + fun getGraphitePrefix(configuration: NodeConfiguration): String { + val customPrefix = configuration.graphiteOptions!!.prefix + // Create a graphite prefix stripping all non-allowed characteres + val graphiteName = (customPrefix ?: defaultGraphitePrefix(configuration.myLegalName)) + .trim().replace(Regex("[^0-9a-zA-Z_]"), "_") + if (customPrefix != null && graphiteName != customPrefix) { + logger.warn("Invalid graphite prefix ${customPrefix} specified in config - got mangled to ${graphiteName}. Only letters, numbers and underscores are allowed") + } + return graphiteName } } @@ -140,7 +146,7 @@ D""".trimStart() GraphiteReporter.forRegistry(metrics) .prefixedWith(getGraphitePrefix(configuration)) .convertDurationsTo(TimeUnit.MILLISECONDS) - .convertRatesTo(TimeUnit.MINUTES) + .convertRatesTo(TimeUnit.SECONDS) .filter(MetricFilter.ALL) .build(PickledGraphite(configuration.graphiteOptions!!.server, configuration.graphiteOptions!!.port)) .start(configuration.graphiteOptions!!.sampleInvervallSeconds, TimeUnit.SECONDS) @@ -181,4 +187,4 @@ D""".trimStart() return super.makeStateMachineManager(database) } } -} \ No newline at end of file +} diff --git a/node/src/test/kotlin/net/corda/node/internal/EnterpriseNodeTest.kt b/node/src/test/kotlin/net/corda/node/internal/EnterpriseNodeTest.kt new file mode 100644 index 0000000000..6c5ec1d73a --- /dev/null +++ b/node/src/test/kotlin/net/corda/node/internal/EnterpriseNodeTest.kt @@ -0,0 +1,29 @@ +package net.corda.node.internal + +import com.nhaarman.mockito_kotlin.mock +import com.nhaarman.mockito_kotlin.whenever +import net.corda.core.identity.CordaX500Name +import net.corda.node.services.config.GraphiteOptions +import net.corda.node.services.config.NodeConfiguration +import org.junit.Test + +class EnterpriseNodeTest { + @Test + fun `Check sanitizing of graphite names`() { + checkReplacement("abc", "abc") + checkReplacement("abc.1.2", "abc_1_2") + checkReplacement("abc", "foo__bar_", "foo (bar)") + + } + + fun checkReplacement(orgname: String, expectedName: String, custom: String? = null) { + val nodeConfig = mock() { + whenever(it.myLegalName).thenReturn(CordaX500Name(orgname, "London", "GB")) + whenever(it.graphiteOptions).thenReturn(GraphiteOptions("server", 12345, custom)) + } + + val expectedPattern = if (custom == null) "${expectedName}_London_GB_\\d+_\\d+_\\d+_\\d+" else expectedName + val createdName = EnterpriseNode.getGraphitePrefix(nodeConfig) + assert(Regex(expectedPattern).matches(createdName), { "${createdName} did not match ${expectedPattern}" }) + } +} \ No newline at end of file