Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
! util: remove SprayActorLogging and UtilSettings, simplify LoggingCo…
Browse files Browse the repository at this point in the history
…ntext, fixes #421

Since not all SLF4J implementations (most importantly logback) can properly manage a potentially unbounded number of loggers we cannot use actor paths as logger names. The latter would have been nice since, by converting actor paths to dotted notation, we'd be able to use hierarchical configuration as well as logbacks abbreviation feature. However, since we can't use actor paths as logger names the feature of "dottifying" actor paths is not useful.

The `SprayActorLogging` and `UtilSettings` abstractions therefore don't serve any purpose anymore.
Please replace all your usage of `spray.util.SprayActorLogging` with `akka.actor.ActorLogging`, which provides the exact same API.
  • Loading branch information
sirthias committed Aug 21, 2013
1 parent 8dbaaf3 commit e234dd9
Show file tree
Hide file tree
Showing 18 changed files with 38 additions and 130 deletions.
4 changes: 2 additions & 2 deletions docs/documentation/spray-can/http-client/host-level.rst
Expand Up @@ -8,7 +8,7 @@ individual HTTP connection. It autonomously manages a configurable pool of conne




Starting an HttpHostConnector Starting an HttpHostConnector
---------------------------- -----------------------------


The core of this API is the ``HttpHostConnector`` actor, whose class, as with all other *spray-can* actors, you don't The core of this API is the ``HttpHostConnector`` actor, whose class, as with all other *spray-can* actors, you don't
get in direct contact with from your application. All communication happens purely via actor messages, the majority of get in direct contact with from your application. All communication happens purely via actor messages, the majority of
Expand All @@ -31,7 +31,7 @@ The connector will then respond with an ``Http.HostConnectorInfo`` event message




Using an HttpHostConnector Using an HttpHostConnector
------------------------- --------------------------


Once you've got a hold of the connectors ``ActorRef`` you can send it one or more *spray-http* ``HttpRequestPart`` Once you've got a hold of the connectors ``ActorRef`` you can send it one or more *spray-http* ``HttpRequestPart``
messages. The connector will send the request across one of the connections it manages according to the following logic: messages. The connector will send the request across one of the connections it manages according to the following logic:
Expand Down
16 changes: 3 additions & 13 deletions docs/documentation/spray-util/index.rst
Expand Up @@ -69,16 +69,6 @@ __ http://www.artima.com/weblogs/viewpost.jsp?thread=179766
LoggingContext LoggingContext
-------------- --------------


The ``LoggingContext`` is a simple ``akka.event.LoggingAdapter`` that can be implicitly created from ``ActorRefFactory`` The ``LoggingContext`` is a simple ``akka.event.LoggingAdapter`` that can always be implicitly created.
instances (i.e. ``ActorSystems`` or ``ActorContexts``). It is mainly used by :ref:`spray-routing` directives, which It is mainly used by :ref:`spray-routing` directives, which require a logging facility for an implicitly available
require a logging facility for either type of ``ActorRefFactory``. ``ActorRefFactory`` (i.e. ``ActorSystem`` or ``ActorContext``).

The ``LoggingContext`` allows for some deeper configuration via the ``log-actor-paths-with-dots`` and
``log-actor-system-name`` config settings shown in the "Configuration" section above.


SprayActorLogging
-----------------

The ``SprayActorLogging`` trait is a drop-in replacement for the ``akka.actor.ActorLogging`` trait, which provides
logging via a ``LoggingContext`` and therefore supports the same configuration options.
Expand Up @@ -7,11 +7,9 @@ import akka.util.Timeout
import akka.pattern.ask import akka.pattern.ask
import akka.actor._ import akka.actor._
import spray.can.Http import spray.can.Http
import spray.util.SprayActorLogging
import spray.http._ import spray.http._
import HttpMethods._ import HttpMethods._



trait ConnectionLevelApiDemo { trait ConnectionLevelApiDemo {
private implicit val timeout: Timeout = 5.seconds private implicit val timeout: Timeout = 5.seconds


Expand All @@ -27,7 +25,7 @@ trait ConnectionLevelApiDemo {
// as well as how requests are scheduled onto them. // as well as how requests are scheduled onto them.


// Actor that manages the lifecycle of a single HTTP connection for a single request // Actor that manages the lifecycle of a single HTTP connection for a single request
class MyRequestActor(host: String) extends Actor with SprayActorLogging { class MyRequestActor(host: String) extends Actor with ActorLogging {
import context.system import context.system


def receive: Receive = { def receive: Receive = {
Expand Down
Expand Up @@ -11,8 +11,7 @@ import spray.http._
import HttpMethods._ import HttpMethods._
import MediaTypes._ import MediaTypes._



class DemoService extends Actor with ActorLogging {
class DemoService extends Actor with SprayActorLogging {
implicit val timeout: Timeout = 1.second // for the actor 'asks' implicit val timeout: Timeout = 1.second // for the actor 'asks'
import context.dispatcher // ExecutionContext for the futures and scheduler import context.dispatcher // ExecutionContext for the futures and scheduler


Expand Down Expand Up @@ -102,7 +101,7 @@ class DemoService extends Actor with SprayActorLogging {
) )
) )


class Streamer(client: ActorRef, count: Int) extends Actor with SprayActorLogging { class Streamer(client: ActorRef, count: Int) extends Actor with ActorLogging {
log.debug("Starting streaming response ...") log.debug("Starting streaming response ...")


// we use the successful sending of a chunk as trigger for scheduling the next chunk // we use the successful sending of a chunk as trigger for scheduling the next chunk
Expand Down
Expand Up @@ -7,7 +7,6 @@ import akka.pattern.ask
import akka.io.{Tcp, IO} import akka.io.{Tcp, IO}
import akka.util.{ByteString, Timeout} import akka.util.{ByteString, Timeout}
import akka.actor._ import akka.actor._
import spray.util._


object Main extends App { object Main extends App {
// we need an ActorSystem to host our application in // we need an ActorSystem to host our application in
Expand All @@ -30,7 +29,7 @@ object Main extends App {
} }
} }


class EchoServer extends Actor with SprayActorLogging { class EchoServer extends Actor with ActorLogging {
var childrenCount = 0 var childrenCount = 0


def receive = { def receive = {
Expand All @@ -51,7 +50,7 @@ class EchoServer extends Actor with SprayActorLogging {
} }
} }


class EchoServerConnection(tcpConnection: ActorRef) extends Actor with SprayActorLogging { class EchoServerConnection(tcpConnection: ActorRef) extends Actor with ActorLogging {
context.watch(tcpConnection) context.watch(tcpConnection)


def receive = idle def receive = idle
Expand Down
Expand Up @@ -3,7 +3,7 @@ package spray.examples
import java.io.File import java.io.File
import org.parboiled.common.FileUtils import org.parboiled.common.FileUtils
import scala.concurrent.duration._ import scala.concurrent.duration._
import akka.actor.{Props, Actor} import akka.actor._
import akka.io.Tcp import akka.io.Tcp
import spray.routing.{HttpService, RequestContext} import spray.routing.{HttpService, RequestContext}
import spray.routing.directives.CachingDirectives import spray.routing.directives.CachingDirectives
Expand All @@ -13,7 +13,6 @@ import spray.http._
import MediaTypes._ import MediaTypes._
import CachingDirectives._ import CachingDirectives._



// we don't implement our route structure directly in the service actor because // we don't implement our route structure directly in the service actor because
// we want to be able to test it independently, without having to spin up an actor // we want to be able to test it independently, without having to spin up an actor
class DemoServiceActor extends Actor with DemoService { class DemoServiceActor extends Actor with DemoService {
Expand Down Expand Up @@ -112,7 +111,7 @@ trait DemoService extends HttpService {
def sendStreamingResponse(ctx: RequestContext): Unit = def sendStreamingResponse(ctx: RequestContext): Unit =
actorRefFactory.actorOf { actorRefFactory.actorOf {
Props { Props {
new Actor with SprayActorLogging { new Actor with ActorLogging {
// we use the successful sending of a chunk as trigger for scheduling the next chunk // we use the successful sending of a chunk as trigger for scheduling the next chunk
val responseStart = HttpResponse(entity = HttpEntity(`text/html`, streamStart)) val responseStart = HttpResponse(entity = HttpEntity(`text/html`, streamStart))
ctx.responder ! ChunkedResponseStart(responseStart).withAck(Ok(16)) ctx.responder ! ChunkedResponseStart(responseStart).withAck(Ok(16))
Expand Down
Expand Up @@ -3,7 +3,7 @@ package spray.examples
import java.io.File import java.io.File
import org.parboiled.common.FileUtils import org.parboiled.common.FileUtils
import scala.concurrent.duration._ import scala.concurrent.duration._
import akka.actor.{Props, Actor} import akka.actor._
import akka.pattern.ask import akka.pattern.ask
import spray.routing.{HttpService, RequestContext} import spray.routing.{HttpService, RequestContext}
import spray.routing.directives.CachingDirectives import spray.routing.directives.CachingDirectives
Expand All @@ -16,7 +16,6 @@ import spray.http._
import MediaTypes._ import MediaTypes._
import CachingDirectives._ import CachingDirectives._



// we don't implement our route structure directly in the service actor because // we don't implement our route structure directly in the service actor because
// we want to be able to test it independently, without having to spin up an actor // we want to be able to test it independently, without having to spin up an actor
class DemoServiceActor extends Actor with DemoService { class DemoServiceActor extends Actor with DemoService {
Expand Down Expand Up @@ -140,7 +139,7 @@ trait DemoService extends HttpService {
def sendStreamingResponse(ctx: RequestContext): Unit = def sendStreamingResponse(ctx: RequestContext): Unit =
actorRefFactory.actorOf { actorRefFactory.actorOf {
Props { Props {
new Actor with SprayActorLogging { new Actor with ActorLogging {
// we use the successful sending of a chunk as trigger for scheduling the next chunk // we use the successful sending of a chunk as trigger for scheduling the next chunk
val responseStart = HttpResponse(entity = HttpEntity(`text/html`, streamStart)) val responseStart = HttpResponse(entity = HttpEntity(`text/html`, streamStart))
ctx.responder ! ChunkedResponseStart(responseStart).withAck(Ok(16)) ctx.responder ! ChunkedResponseStart(responseStart).withAck(Ok(16))
Expand Down
Expand Up @@ -3,13 +3,11 @@ package spray.examples
import scala.concurrent.duration._ import scala.concurrent.duration._
import akka.io.Tcp import akka.io.Tcp
import akka.actor._ import akka.actor._
import spray.util._
import spray.http._ import spray.http._
import MediaTypes._ import MediaTypes._
import HttpMethods._ import HttpMethods._



class DemoService extends Actor with ActorLogging {
class DemoService extends Actor with SprayActorLogging {


def receive = { def receive = {
case HttpRequest(GET, Uri.Path("/"), _, _, _) => case HttpRequest(GET, Uri.Path("/"), _, _, _) =>
Expand Down Expand Up @@ -69,7 +67,7 @@ class DemoService extends Actor with SprayActorLogging {
// simple case class whose instances we use as send confirmation message for streaming chunks // simple case class whose instances we use as send confirmation message for streaming chunks
case class Ok(remaining: Int) case class Ok(remaining: Int)


class Streamer(client: ActorRef, count: Int) extends Actor with SprayActorLogging { class Streamer(client: ActorRef, count: Int) extends Actor with ActorLogging {
log.debug("Starting streaming response ...") log.debug("Starting streaming response ...")


// we use the successful sending of a chunk as trigger for scheduling the next chunk // we use the successful sending of a chunk as trigger for scheduling the next chunk
Expand Down
3 changes: 1 addition & 2 deletions spray-can/src/main/scala/spray/can/HttpManager.scala
Expand Up @@ -20,11 +20,10 @@ import scala.util.control.NonFatal
import akka.actor._ import akka.actor._
import spray.can.client.{ HttpHostConnector, HttpClientSettingsGroup, ClientConnectionSettings } import spray.can.client.{ HttpHostConnector, HttpClientSettingsGroup, ClientConnectionSettings }
import spray.can.server.HttpListener import spray.can.server.HttpListener
import spray.util.SprayActorLogging
import spray.http._ import spray.http._
import Http.HostConnectorSetup import Http.HostConnectorSetup


private[can] class HttpManager(httpSettings: HttpExt#Settings) extends Actor with SprayActorLogging { private[can] class HttpManager(httpSettings: HttpExt#Settings) extends Actor with ActorLogging {
import httpSettings._ import httpSettings._
private[this] val listenerCounter = Iterator from 0 private[this] val listenerCounter = Iterator from 0
private[this] val groupCounter = Iterator from 0 private[this] val groupCounter = Iterator from 0
Expand Down
Expand Up @@ -21,7 +21,6 @@ import scala.collection.immutable.Queue
import scala.concurrent.duration.Duration import scala.concurrent.duration.Duration
import akka.actor._ import akka.actor._
import akka.io.Inet import akka.io.Inet
import spray.util.SprayActorLogging
import spray.can.client.HttpHostConnector._ import spray.can.client.HttpHostConnector._
import spray.can.Http import spray.can.Http
import spray.io.ClientSSLEngineProvider import spray.io.ClientSSLEngineProvider
Expand All @@ -32,7 +31,7 @@ private[client] class HttpHostConnectionSlot(host: String, port: Int,
options: immutable.Traversable[Inet.SocketOption], options: immutable.Traversable[Inet.SocketOption],
idleTimeout: Duration, idleTimeout: Duration,
clientConnectionSettingsGroup: ActorRef)(implicit sslEngineProvider: ClientSSLEngineProvider) clientConnectionSettingsGroup: ActorRef)(implicit sslEngineProvider: ClientSSLEngineProvider)
extends Actor with SprayActorLogging { extends Actor with ActorLogging {


// we cannot sensibly recover from crashes // we cannot sensibly recover from crashes
override def supervisorStrategy = SupervisorStrategy.stoppingStrategy override def supervisorStrategy = SupervisorStrategy.stoppingStrategy
Expand Down
Expand Up @@ -18,12 +18,11 @@ package spray.can.client


import scala.collection.immutable.Queue import scala.collection.immutable.Queue
import akka.actor._ import akka.actor._
import spray.util.SprayActorLogging
import spray.http.{ HttpHeaders, HttpRequest } import spray.http.{ HttpHeaders, HttpRequest }
import spray.can.Http import spray.can.Http


private[can] class HttpHostConnector(normalizedSetup: Http.HostConnectorSetup, clientConnectionSettingsGroup: ActorRef) private[can] class HttpHostConnector(normalizedSetup: Http.HostConnectorSetup, clientConnectionSettingsGroup: ActorRef)
extends Actor with SprayActorLogging { extends Actor with ActorLogging {


import HttpHostConnector._ import HttpHostConnector._
import normalizedSetup.{ settings _, _ } import normalizedSetup.{ settings _, _ }
Expand Down
3 changes: 1 addition & 2 deletions spray-can/src/main/scala/spray/can/server/HttpListener.scala
Expand Up @@ -19,13 +19,12 @@ package spray.can.server
import scala.concurrent.duration.Duration import scala.concurrent.duration.Duration
import akka.io.{ IO, Tcp } import akka.io.{ IO, Tcp }
import akka.actor._ import akka.actor._
import spray.util.SprayActorLogging
import spray.can.server.StatsSupport.StatsHolder import spray.can.server.StatsSupport.StatsHolder
import spray.can.{ HttpExt, Http } import spray.can.{ HttpExt, Http }


private[can] class HttpListener(bindCommander: ActorRef, private[can] class HttpListener(bindCommander: ActorRef,
bind: Http.Bind, bind: Http.Bind,
httpSettings: HttpExt#Settings) extends Actor with SprayActorLogging { httpSettings: HttpExt#Settings) extends Actor with ActorLogging {
import context.system import context.system
import bind._ import bind._


Expand Down
Expand Up @@ -50,7 +50,7 @@ class HttpHostConnectorSpec extends Specification with NoTimeConversions {


step { step {
val testService = system.actorOf(Props( val testService = system.actorOf(Props(
new Actor with SprayActorLogging { new Actor with ActorLogging {
var dropNext = true var dropNext = true
val random = new Random(38) val random = new Random(38)
def receive = { def receive = {
Expand Down
5 changes: 2 additions & 3 deletions spray-io/src/main/scala/spray/io/ConnectionHandler.scala
Expand Up @@ -17,11 +17,10 @@
package spray.io package spray.io


import java.net.InetSocketAddress import java.net.InetSocketAddress
import akka.actor.{ ActorRef, Terminated, Actor } import akka.actor.{ ActorLogging, ActorRef, Terminated, Actor }
import akka.io.Tcp import akka.io.Tcp
import spray.util.SprayActorLogging


trait ConnectionHandler extends Actor with SprayActorLogging { trait ConnectionHandler extends Actor with ActorLogging {


//# final-stages //# final-stages
def baseCommandPipeline(tcpConnection: ActorRef): Pipeline[Command] = { def baseCommandPipeline(tcpConnection: ActorRef): Pipeline[Command] = {
Expand Down
23 changes: 0 additions & 23 deletions spray-util/src/main/resources/reference.conf
Expand Up @@ -10,27 +10,4 @@ spray {
# Always contains the deployed version of spray. # Always contains the deployed version of spray.
# Referenced, for example, from the `spray.can.server.server-header` setting. # Referenced, for example, from the `spray.can.server.server-header` setting.
version = "<VERSION>" version = "<VERSION>"

util {

# Enables/disables the translation of ActorPaths from slash-separated to
# dot-separated, which opens them up to the hierarchy-based logger configuration
# of frameworks like logback or log4j.
# When logging via the `akka.event.slf4j.Slf4jEventHandler` and a LoggingContext
# created from an ActorContext the logger name will be, for example,
# - `akka://echo-server/user/io-bridge` with this setting off
# - `echo-server.user.io-bridge` with this setting on
# (assuming that `log-actor-system-name = off`)
log-actor-paths-with-dots = off

# Enables/disables the inclusion of the ActorSystem name in the log source / logger name.
# When logging via the `akka.event.slf4j.Slf4jEventHandler` and a LoggingContext
# created from an ActorContext the logger name will be, for example,
# - `akka://echo-server/user/io-bridge` with this setting off
# - `akka://echo-server/user/io-bridge(default-system)` with this setting on
# When combined with `log-actor-paths-with-dots = on` the logger name will be, for example,
# - `echo-server.user.io-bridge` with this setting off
# - `default-system.echo-server.user.io-bridge` with this setting on
log-actor-system-name = off
}
} }
45 changes: 14 additions & 31 deletions spray-util/src/main/scala/spray/util/LoggingContext.scala
Expand Up @@ -20,11 +20,12 @@ import akka.event.{ Logging, LoggingAdapter }
import akka.actor._ import akka.actor._


/** /**
* A LoggingAdapter that can be implicitly supplied from an implicitly available * A LoggingAdapter that can always be supplied implicitly.
* ActorRefFactory (i.e. ActorSystem or ActorContext). * If an implicit ActorSystem the created LoggingContext forwards to the log of the system.
* Also, it supports optional reformating of ActorPath strings from slash-separated * If an implicit ActorContext is in scope the created LoggingContext uses the context's
* to dot-separated, which opens them up to the hierarchy-based logger configuration * ActorRef as a log source.
* of frameworks like logback or log4j. * Otherwise, i.e. if neither an ActorSystem nor an ActorContext is implicitly available,
* the created LoggingContext will forward to NoLogging, i.e. "/dev/null".
*/ */
trait LoggingContext extends LoggingAdapter trait LoggingContext extends LoggingAdapter


Expand All @@ -35,47 +36,29 @@ object LoggingContext extends LoggingContextLowerOrderImplicit1 {
def isInfoEnabled = la.isInfoEnabled def isInfoEnabled = la.isInfoEnabled
def isDebugEnabled = la.isDebugEnabled def isDebugEnabled = la.isDebugEnabled


protected def notifyError(message: String): Unit = { la.error(message) } protected def notifyError(message: String): Unit = la.error(message)
protected def notifyError(cause: Throwable, message: String): Unit = { la.error(cause, message) } protected def notifyError(cause: Throwable, message: String): Unit = la.error(cause, message)
protected def notifyWarning(message: String): Unit = { la.warning(message) } protected def notifyWarning(message: String): Unit = la.warning(message)
protected def notifyInfo(message: String): Unit = { la.info(message) } protected def notifyInfo(message: String): Unit = la.info(message)
protected def notifyDebug(message: String): Unit = { la.debug(message) } protected def notifyDebug(message: String): Unit = la.debug(message)
} }
} }


private[util] sealed abstract class LoggingContextLowerOrderImplicit1 extends LoggingContextLowerOrderImplicit2 { private[util] sealed abstract class LoggingContextLowerOrderImplicit1 extends LoggingContextLowerOrderImplicit2 {
this: LoggingContext.type this: LoggingContext.type

implicit def fromActorRefFactory(implicit refFactory: ActorRefFactory) = implicit def fromActorRefFactory(implicit refFactory: ActorRefFactory) =
refFactory match { refFactory match {
case x: ActorSystem fromActorSystem(x) case x: ActorSystem fromActorSystem(x)
case x: ActorContext fromActorContext(x) case x: ActorContext fromActorContext(x)
} }

def fromActorSystem(system: ActorSystem) = fromAdapter(system.log) def fromActorSystem(system: ActorSystem) = fromAdapter(system.log)

def fromActorContext(context: ActorContext) = fromAdapter(Logging(context.system.eventStream, context.self))
def fromActorContext(context: ActorContext) = fromAdapter {
val system = context.system
val path = context.self.path.toString
val settings = UtilSettings(system)
if (settings.logActorPathsWithDots) {
val fixedPath = path.substring(7).replace('/', '.') // drop the `akka://` prefix and replace slashes
val logSource = if (settings.logActorSystemName) system.toString + '.' + fixedPath else fixedPath
Logging(system.eventStream, logSource)
} else if (settings.logActorSystemName) Logging(system, path) else Logging(system.eventStream, path)
}
} }


private[util] sealed abstract class LoggingContextLowerOrderImplicit2 { private[util] sealed abstract class LoggingContextLowerOrderImplicit2 {
this: LoggingContext.type this: LoggingContext.type

implicit val NoLogging = fromAdapter(akka.event.NoLogging) implicit val NoLogging = fromAdapter(akka.event.NoLogging)
} }


/** @deprecated("Please use akka.actor.ActorLogging directly instead!")
* Trait that can be mixed into an Actor to easily obtain a reference to a spray-level logger, trait SprayActorLogging extends akka.actor.ActorLogging { _: Actor }
* which is available under the name "log".
*/
trait SprayActorLogging { this: Actor
val log: LoggingAdapter = LoggingContext.fromActorContext(context)
}
29 changes: 0 additions & 29 deletions spray-util/src/main/scala/spray/util/UtilSettings.scala

This file was deleted.

0 comments on commit e234dd9

Please sign in to comment.