From 53315a092466528e8596c4b1861d64ec3aa37061 Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Thu, 11 Apr 2019 03:09:38 +0200 Subject: [PATCH] fallback to reference configuration when the application config fails to load, related to #564 --- .../kamon/InitialConfigLoadingSpec.scala | 51 +++++++++++++++++++ kamon-core/src/main/scala/kamon/Kamon.scala | 23 ++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 kamon-core-tests/src/test/scala/kamon/InitialConfigLoadingSpec.scala diff --git a/kamon-core-tests/src/test/scala/kamon/InitialConfigLoadingSpec.scala b/kamon-core-tests/src/test/scala/kamon/InitialConfigLoadingSpec.scala new file mode 100644 index 000000000..f5f22020c --- /dev/null +++ b/kamon-core-tests/src/test/scala/kamon/InitialConfigLoadingSpec.scala @@ -0,0 +1,51 @@ +package kamon + +import java.io._ +import java.util.concurrent.TimeUnit + +import org.scalatest.{Matchers, WordSpec} +import org.scalatest.concurrent.Eventually +import org.scalatest.time.SpanSugar._ + +import scala.util.{Failure, Success, Try} + +class InitialConfigLoadingSpec extends WordSpec with Matchers with Eventually { + + "the initial config loading" should { + "fallback to using reference configuration only when application.conf files are malformed" in { + val process = Runtime.getRuntime.exec(createProcessWithConfig("kamon.KamonWithCustomConfig", "{This is a bad config}")) + val processOutputReader = new BufferedReader(new InputStreamReader(process.getInputStream())) + + eventually(timeout(10 seconds)) { + val outputLine = processOutputReader.readLine() + outputLine shouldBe "All Good" + } + + if(process.isAlive) { + process.destroyForcibly().waitFor(5, TimeUnit.SECONDS) + } + } + } + + def createProcessWithConfig(mainClass: String, configContent: String): String = { + val tempConfigFile = File.createTempFile("bad-config", ".conf") + val writer = new BufferedWriter(new FileWriter(tempConfigFile)) + writer.write(configContent) + writer.flush() + writer.close() + + val configOptions = "-Dconfig.trace=loads -Dconfig.file=" + tempConfigFile.getAbsolutePath() + System.getProperty("java.home") + File.separator + "bin" + File.separator + "java " + configOptions + + " -cp " + System.getProperty("java.class.path") + " " + mainClass + } +} + +object KamonWithCustomConfig extends App { + Try { + Kamon.counter("test").increment() + } match { + case Success(_) => println("All Good") + case Failure(_) => println("All Bad") + } + +} \ No newline at end of file diff --git a/kamon-core/src/main/scala/kamon/Kamon.scala b/kamon-core/src/main/scala/kamon/Kamon.scala index 720e0dfb4..d7267bd94 100644 --- a/kamon-core/src/main/scala/kamon/Kamon.scala +++ b/kamon-core/src/main/scala/kamon/Kamon.scala @@ -32,7 +32,7 @@ import scala.util.Try object Kamon extends MetricLookup with ReporterRegistry with Tracer { private val logger = LoggerFactory.getLogger("kamon.Kamon") - @volatile private var _config = ConfigFactory.load() + @volatile private var _config = loadInitialConfiguration() @volatile private var _environment = Environment.fromConfig(_config) @volatile private var _filters = Filters.fromConfig(_config) @@ -187,6 +187,27 @@ object Kamon extends MetricLookup with ReporterRegistry with Tracer { private def schedulerPoolSize(config: Config): Int = config.getInt("kamon.scheduler-pool-size") + private def loadInitialConfiguration(): Config = { + Try { + ConfigFactory.load(ConfigFactory.load()) + + } recoverWith { + case t: Throwable => + logger.warn("Failed to load the default configuration, attempting to load the reference configuration", t) + + Try { + val referenceConfig = ConfigFactory.defaultReference() + logger.warn("Initializing with the default reference configuration, none of the user settings might be in effect", t) + referenceConfig + } + + } recover { + case t: Throwable => + logger.error("Failed to load the reference configuration, please check your reference.conf files for errors", t) + ConfigFactory.empty() + } get + } + } trait OnReconfigureHook {