OSGi EventHandler dynamically listen to LogService
More information in logging Conflicts: project/AkkaBuild.scala
This commit is contained in:
parent
49e73f2fb7
commit
a88eb0d850
3 changed files with 109 additions and 54 deletions
|
|
@ -5,9 +5,8 @@ package akka.osgi
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
import java.util.{ Dictionary, Properties }
|
import java.util.{ Dictionary, Properties }
|
||||||
import org.osgi.framework.{ ServiceRegistration, BundleContext, BundleActivator }
|
import org.osgi.framework._
|
||||||
import org.osgi.service.log.LogService
|
import org.osgi.service.log.LogService
|
||||||
import org.osgi.util.tracker.ServiceTracker
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract bundle activator implementation to bootstrap and configure an actor system in an
|
* Abstract bundle activator implementation to bootstrap and configure an actor system in an
|
||||||
|
|
@ -40,22 +39,40 @@ abstract class ActorSystemActivator extends BundleActivator {
|
||||||
*/
|
*/
|
||||||
def start(context: BundleContext): Unit = {
|
def start(context: BundleContext): Unit = {
|
||||||
system = Some(OsgiActorSystemFactory(context).createActorSystem(Option(getActorSystemName(context))))
|
system = Some(OsgiActorSystemFactory(context).createActorSystem(Option(getActorSystemName(context))))
|
||||||
findLogService(context) foreach (log ⇒ system.foreach(sys ⇒ sys.eventStream.publish(log)))
|
system foreach (addLogServiceListener(context, _))
|
||||||
system foreach (configure(context, _))
|
system foreach (configure(context, _))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a LogService in the BundleContext in any
|
* Adds a LogService Listener that will advertise the ActorSystem on LogService registration and unregistration
|
||||||
*
|
*
|
||||||
* @param context the BundleContext
|
* @param context the BundleContext
|
||||||
* @return An option of the LogService in the BundleContext
|
* @param system the ActorSystem to be advertised
|
||||||
*/
|
*/
|
||||||
def findLogService(context: BundleContext): Option[LogService] = {
|
def addLogServiceListener(context: BundleContext, system: ActorSystem) {
|
||||||
val logServiceTracker = new ServiceTracker(context, classOf[LogService].getName, null)
|
val logServiceListner = new ServiceListener {
|
||||||
logServiceTracker.open()
|
def serviceChanged(event: ServiceEvent) {
|
||||||
Option(logServiceTracker.getService.asInstanceOf[LogService])
|
event.getType match {
|
||||||
|
case ServiceEvent.REGISTERED ⇒ system.eventStream.publish(serviceForReference[LogService](context, event.getServiceReference))
|
||||||
|
case ServiceEvent.UNREGISTERING ⇒ system.eventStream.publish(UnregisteringLogService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val filter = s"(objectclass=${classOf[LogService].getName})"
|
||||||
|
context.addServiceListener(logServiceListner, filter)
|
||||||
|
|
||||||
|
//Small trick to create an event if the service is registred before this start listing for
|
||||||
|
Option(context.getServiceReference(classOf[LogService].getName)).foreach(x ⇒ {
|
||||||
|
logServiceListner.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, x))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to find a service by its reference.
|
||||||
|
*/
|
||||||
|
def serviceForReference[T](context: BundleContext, reference: ServiceReference): T =
|
||||||
|
context.getService(reference).asInstanceOf[T]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts down the ActorSystem when the bundle is stopped and, if necessary, unregisters a service registration.
|
* Shuts down the ActorSystem when the bundle is stopped and, if necessary, unregisters a service registration.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
83
akka-osgi/src/main/scala/akka/osgi/DefaultOSGiLogger.scala
Normal file
83
akka-osgi/src/main/scala/akka/osgi/DefaultOSGiLogger.scala
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||||
|
*/
|
||||||
|
package akka.osgi
|
||||||
|
|
||||||
|
import akka.event.Logging
|
||||||
|
import org.osgi.service.log.LogService
|
||||||
|
import akka.event.Logging.{ DefaultLogger, LogEvent }
|
||||||
|
import akka.event.Logging.Error.NoCause
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EventHandler for OSGi environment.
|
||||||
|
* Stands for an interface between akka and the OSGi LogService
|
||||||
|
* It uses the OSGi LogService to log the received LogEvents
|
||||||
|
*/
|
||||||
|
class DefaultOSGiLogger extends DefaultLogger {
|
||||||
|
|
||||||
|
val messageFormat = " %s | %s | %s | %s"
|
||||||
|
|
||||||
|
override def receive: Receive = uninitialisedReceive orElse super.receive
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Behaviour of the EventHandler that waits for its LogService
|
||||||
|
* @return Receive: Store LogEvent or become initialised
|
||||||
|
*/
|
||||||
|
def uninitialisedReceive: Receive = {
|
||||||
|
var messagesToLog: Vector[LogEvent] = Vector()
|
||||||
|
//the Default Logger needs to be aware of the LogService which is published on the EventStream
|
||||||
|
context.system.eventStream.subscribe(self, classOf[LogService])
|
||||||
|
context.system.eventStream.unsubscribe(self, UnregisteringLogService.getClass)
|
||||||
|
/**
|
||||||
|
* Logs every already received LogEvent and set the EventHandler ready to log every incoming LogEvent.
|
||||||
|
*
|
||||||
|
* @param logService OSGi LogService that has been registered,
|
||||||
|
*/
|
||||||
|
def setLogService(logService: LogService) {
|
||||||
|
messagesToLog.foreach(x ⇒ {
|
||||||
|
logMessage(logService, x)
|
||||||
|
})
|
||||||
|
context.become(initialisedReceive(logService))
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
case logService: LogService ⇒ setLogService(logService)
|
||||||
|
case logEvent: LogEvent ⇒ messagesToLog :+= logEvent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Behaviour of the Eventhanlder that is setup (has received a LogService)
|
||||||
|
* @param logService registrered OSGi LogService
|
||||||
|
* @return Receive : Logs LogEvent or go back to the uninitialised state
|
||||||
|
*/
|
||||||
|
def initialisedReceive(logService: LogService): Receive = {
|
||||||
|
context.system.eventStream.subscribe(self, UnregisteringLogService.getClass)
|
||||||
|
context.system.eventStream.unsubscribe(self, classOf[LogService])
|
||||||
|
|
||||||
|
{
|
||||||
|
case logEvent: LogEvent ⇒ logMessage(logService, logEvent)
|
||||||
|
case UnregisteringLogService ⇒ context.become(uninitialisedReceive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message in an OSGi LogService
|
||||||
|
*
|
||||||
|
* @param logService OSGi LogService registered and used for logging
|
||||||
|
* @param event akka LogEvent that is log unsing the LogService
|
||||||
|
*/
|
||||||
|
def logMessage(logService: LogService, event: LogEvent) {
|
||||||
|
event match {
|
||||||
|
case error: Logging.Error if error.cause != NoCause ⇒ logService.log(event.level.asInt, messageFormat.format(timestamp, event.thread.getName, event.logSource, event.message), error.cause)
|
||||||
|
case _ ⇒ logService.log(event.level.asInt, messageFormat.format(timestamp, event.thread.getName, event.logSource, event.message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message sent when LogService is unregistred.
|
||||||
|
* Sent from the ActorSystemActivator to an EventHandler (as DefaultOsgiLogger).
|
||||||
|
*/
|
||||||
|
case object UnregisteringLogService
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
|
||||||
*/
|
|
||||||
package akka.osgi.impl
|
|
||||||
|
|
||||||
import akka.event.Logging.{ LogEvent, DefaultLogger }
|
|
||||||
import org.osgi.service.log.LogService
|
|
||||||
import akka.event.Logging
|
|
||||||
import collection.mutable.Buffer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EventHandler for OSGi environment.
|
|
||||||
* Stands for an interface between akka and the OSGi LogService
|
|
||||||
* It uses the OSGi LogService to log the received LogEvents
|
|
||||||
*/
|
|
||||||
class DefaultOSGiLogger extends DefaultLogger {
|
|
||||||
|
|
||||||
//the Default Logger needs to be aware of the LogService which is published on the EventStream
|
|
||||||
context.system.eventStream.subscribe(self, classOf[LogService])
|
|
||||||
|
|
||||||
val messageFormat = "[%s] %s"
|
|
||||||
|
|
||||||
var messagesToLog: Vector[LogEvent] = Vector()
|
|
||||||
|
|
||||||
override def receive: Receive = {
|
|
||||||
//register the log service to use
|
|
||||||
case logService: LogService ⇒ setLogService(logService)
|
|
||||||
case logEvent: LogEvent ⇒ messagesToLog = messagesToLog :+ logEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
def setLogService(logService: LogService) {
|
|
||||||
messagesToLog.foreach(logMessage(logService, _))
|
|
||||||
context.become(receiveEvent(logService))
|
|
||||||
}
|
|
||||||
|
|
||||||
def receiveEvent(logService: LogService): Receive = { case logEvent: LogEvent ⇒ logMessage(logService, logEvent) }
|
|
||||||
|
|
||||||
def logMessage(logService: LogService, event: LogEvent) {
|
|
||||||
event match {
|
|
||||||
case error: Logging.Error ⇒ logService.log(event.level.asInt, Logging.stackTraceFor(error.cause))
|
|
||||||
case _ => logService.log(event.level.asInt, messageFormat.format(event.logSource, event.message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue