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 java.util.{ Dictionary, Properties }
|
||||
import org.osgi.framework.{ ServiceRegistration, BundleContext, BundleActivator }
|
||||
import org.osgi.framework._
|
||||
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
|
||||
|
|
@ -40,21 +39,39 @@ abstract class ActorSystemActivator extends BundleActivator {
|
|||
*/
|
||||
def start(context: BundleContext): Unit = {
|
||||
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, _))
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return An option of the LogService in the BundleContext
|
||||
* @param system the ActorSystem to be advertised
|
||||
*/
|
||||
def findLogService(context: BundleContext): Option[LogService] = {
|
||||
val logServiceTracker = new ServiceTracker(context, classOf[LogService].getName, null)
|
||||
logServiceTracker.open()
|
||||
Option(logServiceTracker.getService.asInstanceOf[LogService])
|
||||
def addLogServiceListener(context: BundleContext, system: ActorSystem) {
|
||||
val logServiceListner = new ServiceListener {
|
||||
def serviceChanged(event: ServiceEvent) {
|
||||
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.
|
||||
|
|
|
|||
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