kamon.Init.scala Maven / Gradle / Ivy
/*
* Copyright 2013-2021 The Kamon Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kamon
import com.typesafe.config.Config
import kamon.status.InstrumentationStatus
import org.slf4j.LoggerFactory
import java.util.concurrent.{ScheduledExecutorService, ScheduledThreadPoolExecutor}
import scala.concurrent.Future
/**
* Provides APIs for handling common initialization tasks like starting modules, attaching instrumentation and
* reconfiguring Kamon.
*/
trait Init { self: ModuleManagement with Configuration with CurrentStatus with Metrics with Utilities with Tracing with ContextStorage =>
private val _logger = LoggerFactory.getLogger(classOf[Init])
@volatile private var _scheduler: Option[ScheduledExecutorService] = None
self.onReconfigure(newConfig => reconfigureInit(newConfig))
/**
* Attempts to attach the instrumentation agent and start all registered modules.
*/
def init(): Unit = {
self.attachInstrumentation()
self.initScheduler()
self.loadModules()
self.moduleRegistry().init()
}
/**
* Reconfigures Kamon to use the provided configuration and then attempts to attach the instrumentation agent and
* start all registered modules.
*/
def init(config: Config): Unit = {
self.attachInstrumentation()
self.initScheduler()
self.reconfigure(config)
self.loadModules()
self.moduleRegistry().init()
}
/**
* Initializes Kamon without trying to attach the instrumentation agent from the Kamon Bundle.
*/
def initWithoutAttaching(): Unit = {
self.initScheduler()
self.loadModules()
self.moduleRegistry().init()
}
/**
* Initializes Kamon without trying to attach the instrumentation agent from the Kamon Bundle.
*/
def initWithoutAttaching(config: Config): Unit = {
self.reconfigure(config)
self.initWithoutAttaching()
}
def stop(): Future[Unit] = {
self.clearRegistry()
self.stopScheduler()
self.moduleRegistry().shutdown()
self.stopModules()
}
/**
* Tries to attach the Kanela instrumentation agent, if the Kamon Bundle dependency is available on the classpath. If
* the Status module indicates that instrumentation has been already applied this method will not try to do anything.
*/
def attachInstrumentation(): Unit = {
if(!InstrumentationStatus.create(warnIfFailed = false).present) {
try {
val attacherClass = Class.forName("kamon.runtime.Attacher")
val attachMethod = attacherClass.getDeclaredMethod("attach")
attachMethod.invoke(null)
} catch {
case _: ClassNotFoundException =>
_logger.warn(
"Your application is running without the Kanela instrumentation agent. None of Kamon's automatic " +
"instrumentation will be applied to the current JVM. Consider using the kamon-bundle dependency " +
"or setting up the Kanela agent via the -javaagent:/path/to/kanela.jar command-line option"
)
case t: Throwable =>
_logger.error("Failed to attach the Kanela agent included in the kamon-bundle", t)
}
}
}
private def initScheduler(): Unit = synchronized {
val newScheduler = newScheduledThreadPool(2, numberedThreadFactory("kamon-scheduler", daemon = true))
self.tracer().bindScheduler(newScheduler)
self.registry().bindScheduler(newScheduler)
}
private def stopScheduler(): Unit = synchronized {
self.tracer().shutdown()
self.registry().shutdown()
_scheduler.foreach(_.shutdown())
_scheduler = None
}
private def reconfigureInit(config: Config): Unit = {
_scheduler.foreach {
case stpe: ScheduledThreadPoolExecutor =>
val newPoolSize = config.getInt("kamon.scheduler-pool-size")
stpe.setCorePoolSize(newPoolSize)
case _ => // cannot change the pool size on other unknown types.
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy