aboutsummaryrefslogtreecommitdiff
path: root/kamon-core/src/main/scala/kamon/supervisor
diff options
context:
space:
mode:
authorIvan Topolnjak <ivantopo@gmail.com>2015-01-30 03:25:54 +0100
committerIvan Topolnjak <ivantopo@gmail.com>2015-01-30 03:25:54 +0100
commitaa1980de105ce128ba75099815f97de3d0d4b552 (patch)
tree4ca0acdd72f8316ef778f5702c8ad40af613884f /kamon-core/src/main/scala/kamon/supervisor
parented950a320c7b3edba36d07288a69fb0049b33063 (diff)
downloadKamon-aa1980de105ce128ba75099815f97de3d0d4b552.tar.gz
Kamon-aa1980de105ce128ba75099815f97de3d0d4b552.tar.bz2
Kamon-aa1980de105ce128ba75099815f97de3d0d4b552.zip
+ all: use ModuleSupervisor init all auto-start modules.
The new ModuleSupervisor implementation will make use of special configuration keys under the `kamon.modules` section to detect all the available modules in the classpath and do two things with that info: 1. Log the AspectJ Weaver missing error if any of the available modules requires AspectJ. 2. Start all available modules that are marked with the auto-start setting.
Diffstat (limited to 'kamon-core/src/main/scala/kamon/supervisor')
-rw-r--r--kamon-core/src/main/scala/kamon/supervisor/AspectJPresent.scala15
-rw-r--r--kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorExtension.scala109
-rw-r--r--kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorSettings.scala33
3 files changed, 157 insertions, 0 deletions
diff --git a/kamon-core/src/main/scala/kamon/supervisor/AspectJPresent.scala b/kamon-core/src/main/scala/kamon/supervisor/AspectJPresent.scala
new file mode 100644
index 00000000..bbb8b69b
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/supervisor/AspectJPresent.scala
@@ -0,0 +1,15 @@
+package kamon.supervisor
+
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation.{ Around, Aspect, Pointcut }
+
+@Aspect
+class AspectJPresent {
+
+ @Pointcut("execution(* kamon.supervisor.KamonSupervisor.isAspectJPresent())")
+ def isAspectJPresentAtModuleSupervisor(): Unit = {}
+
+ @Around("isAspectJPresentAtModuleSupervisor()")
+ def aroundIsAspectJPresentAtModuleSupervisor(pjp: ProceedingJoinPoint): Boolean = true
+
+}
diff --git a/kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorExtension.scala b/kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorExtension.scala
new file mode 100644
index 00000000..1ff6bfc6
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorExtension.scala
@@ -0,0 +1,109 @@
+package kamon.supervisor
+
+import akka.actor
+import akka.actor._
+import kamon.Kamon
+import kamon.supervisor.KamonSupervisor.CreateModule
+
+import scala.concurrent.{ Promise, Future }
+import scala.util.Success
+
+object ModuleSupervisor extends ExtensionId[ModuleSupervisorExtension] with ExtensionIdProvider {
+ def lookup(): ExtensionId[_ <: actor.Extension] = ModuleSupervisor
+ def createExtension(system: ExtendedActorSystem): ModuleSupervisorExtension = new ModuleSupervisorExtensionImpl(system)
+}
+
+trait ModuleSupervisorExtension extends actor.Extension {
+ def createModule(name: String, props: Props): Future[ActorRef]
+}
+
+class ModuleSupervisorExtensionImpl(system: ExtendedActorSystem) extends ModuleSupervisorExtension {
+ import system.dispatcher
+
+ private val _settings = ModuleSupervisorSettings(system)
+ private val _supervisor = system.actorOf(KamonSupervisor.props(_settings, system.dynamicAccess), "kamon")
+
+ def createModule(name: String, props: Props): Future[ActorRef] = Future {} flatMap { _: Unit ⇒
+ val modulePromise = Promise[ActorRef]()
+ _supervisor ! CreateModule(name, props, modulePromise)
+ modulePromise.future
+ }
+}
+
+class KamonSupervisor(settings: ModuleSupervisorSettings, dynamicAccess: DynamicAccess) extends Actor with ActorLogging {
+
+ init()
+
+ def receive = {
+ case CreateModule(name, props, childPromise) ⇒ createChildModule(name, props, childPromise)
+ }
+
+ def createChildModule(name: String, props: Props, childPromise: Promise[ActorRef]): Unit =
+ context.child(name).map { alreadyAvailableModule ⇒
+ log.warning("Received a request to create module [{}] but the module is already available, returning the existent instance.")
+ childPromise.complete(Success(alreadyAvailableModule))
+
+ } getOrElse (childPromise.complete(Success(context.actorOf(props, name))))
+
+ def init(): Unit = {
+ if (settings.modulesRequiringAspectJ.nonEmpty && !isAspectJPresent && !settings.disableAspectJMissingWarning)
+ logAspectJWeaverMissing(settings.modulesRequiringAspectJ)
+
+ // Force initialization of all modules marked with auto-start.
+ settings.availableModules.filter(_.autoStart).foreach { module ⇒
+ if (module.extensionClass == "none")
+ log.debug("Ignoring auto start of the [{}] module with no extension class.")
+ else
+ dynamicAccess.getObjectFor[ExtensionId[Kamon.Extension]](module.extensionClass).map { moduleID ⇒
+ moduleID.get(context.system)
+ log.debug("Auto starting the [{}] module.", module.name)
+
+ } recover {
+ case th: Throwable ⇒ log.error(th, "Failed to auto start the [{}] module.", module.name)
+ }
+
+ }
+ }
+
+ // When AspectJ is present the kamon.supervisor.AspectJPresent aspect will make this return true.
+ def isAspectJPresent: Boolean = false
+
+ def logAspectJWeaverMissing(modulesRequiringAspectJ: List[AvailableModuleInfo]): Unit = {
+ val moduleNames = modulesRequiringAspectJ.map(_.name).mkString(", ")
+ val weaverMissingMessage =
+ """
+ |
+ | ___ _ ___ _ _ ___ ___ _ _
+ | / _ \ | | |_ | | | | | | \/ |(_) (_)
+ |/ /_\ \ ___ _ __ ___ ___ | |_ | | | | | | ___ __ _ __ __ ___ _ __ | . . | _ ___ ___ _ _ __ __ _
+ || _ |/ __|| '_ \ / _ \ / __|| __| | | | |/\| | / _ \ / _` |\ \ / // _ \| '__| | |\/| || |/ __|/ __|| || '_ \ / _` |
+ || | | |\__ \| |_) || __/| (__ | |_ /\__/ / \ /\ /| __/| (_| | \ V /| __/| | | | | || |\__ \\__ \| || | | || (_| |
+ |\_| |_/|___/| .__/ \___| \___| \__|\____/ \/ \/ \___| \__,_| \_/ \___||_| \_| |_/|_||___/|___/|_||_| |_| \__, |
+ | | | __/ |
+ | |_| |___/
+ |
+ | It seems like your application was not started with the -javaagent:/path-to-aspectj-weaver.jar option but Kamon detected
+ | the following modules which require AspecJ to work properly:
+ |
+ """.stripMargin + moduleNames +
+ """
+ |
+ | If you need help on setting up the aspectj weaver go to http://kamon.io/introduction/get-started/ for more info. On the
+ | other hand, if you are sure that you do not need or do not want to use the weaver then you can disable this error message
+ | by changing the kamon.disable-aspectj-missing-warning setting in your configuration file.
+ |
+ """.stripMargin
+
+ log.error(weaverMissingMessage)
+ }
+
+}
+
+object KamonSupervisor {
+ case class CreateModule(name: String, props: Props, childPromise: Promise[ActorRef])
+
+ def props(settings: ModuleSupervisorSettings, dynamicAccess: DynamicAccess): Props =
+ Props(new KamonSupervisor(settings, dynamicAccess))
+
+}
+
diff --git a/kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorSettings.scala b/kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorSettings.scala
new file mode 100644
index 00000000..c5556004
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/supervisor/ModuleSupervisorSettings.scala
@@ -0,0 +1,33 @@
+package kamon.supervisor
+
+import akka.actor.ActorSystem
+
+case class AvailableModuleInfo(name: String, extensionClass: String, requiresAspectJ: Boolean, autoStart: Boolean)
+case class ModuleSupervisorSettings(disableAspectJMissingWarning: Boolean, availableModules: List[AvailableModuleInfo]) {
+ val modulesRequiringAspectJ = availableModules.filter(_.requiresAspectJ)
+}
+
+object ModuleSupervisorSettings {
+
+ def apply(system: ActorSystem): ModuleSupervisorSettings = {
+ import kamon.util.ConfigTools.Syntax
+
+ val config = system.settings.config.getConfig("kamon.modules")
+ val disableAspectJMissingWarning = system.settings.config.getBoolean("kamon.disable-aspectj-missing-warning")
+
+ val modules = config.firstLevelKeys
+ val availableModules = modules.map { moduleName ⇒
+ val moduleConfig = config.getConfig(moduleName)
+
+ AvailableModuleInfo(
+ moduleName,
+ moduleConfig.getString("extension-id"),
+ moduleConfig.getBoolean("requires-aspectj"),
+ moduleConfig.getBoolean("auto-start"))
+
+ } toList
+
+ ModuleSupervisorSettings(disableAspectJMissingWarning, availableModules)
+ }
+
+}