Permalink
Browse files

! util: remove SprayActorLogging and UtilSettings, simplify LoggingCo…

…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 e234dd99388e4f3ff02af3bbe175c9db739ee26a
@@ -8,7 +8,7 @@ individual HTTP connection. It autonomously manages a configurable pool of conne
Starting an HttpHostConnector
-----------------------------
+-----------------------------
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
@@ -31,7 +31,7 @@ The connector will then respond with an ``Http.HostConnectorInfo`` event message
Using an HttpHostConnector
--------------------------
+--------------------------
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:
@@ -69,16 +69,6 @@ __ http://www.artima.com/weblogs/viewpost.jsp?thread=179766
LoggingContext
--------------
-The ``LoggingContext`` is a simple ``akka.event.LoggingAdapter`` that can be implicitly created from ``ActorRefFactory``
-instances (i.e. ``ActorSystems`` or ``ActorContexts``). It is mainly used by :ref:`spray-routing` directives, which
-require a logging facility for either type of ``ActorRefFactory``.
-
-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.
+The ``LoggingContext`` is a simple ``akka.event.LoggingAdapter`` that can always be implicitly created.
+It is mainly used by :ref:`spray-routing` directives, which require a logging facility for an implicitly available
+``ActorRefFactory`` (i.e. ``ActorSystem`` or ``ActorContext``).
@@ -7,11 +7,9 @@ import akka.util.Timeout
import akka.pattern.ask
import akka.actor._
import spray.can.Http
-import spray.util.SprayActorLogging
import spray.http._
import HttpMethods._
-
trait ConnectionLevelApiDemo {
private implicit val timeout: Timeout = 5.seconds
@@ -27,7 +25,7 @@ trait ConnectionLevelApiDemo {
// as well as how requests are scheduled onto them.
// 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
def receive: Receive = {
@@ -11,8 +11,7 @@ import spray.http._
import HttpMethods._
import MediaTypes._
-
-class DemoService extends Actor with SprayActorLogging {
+class DemoService extends Actor with ActorLogging {
implicit val timeout: Timeout = 1.second // for the actor 'asks'
import context.dispatcher // ExecutionContext for the futures and scheduler
@@ -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 ...")
// we use the successful sending of a chunk as trigger for scheduling the next chunk
@@ -7,7 +7,6 @@ import akka.pattern.ask
import akka.io.{Tcp, IO}
import akka.util.{ByteString, Timeout}
import akka.actor._
-import spray.util._
object Main extends App {
// we need an ActorSystem to host our application in
@@ -30,7 +29,7 @@ object Main extends App {
}
}
-class EchoServer extends Actor with SprayActorLogging {
+class EchoServer extends Actor with ActorLogging {
var childrenCount = 0
def receive = {
@@ -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)
def receive = idle
@@ -3,7 +3,7 @@ package spray.examples
import java.io.File
import org.parboiled.common.FileUtils
import scala.concurrent.duration._
-import akka.actor.{Props, Actor}
+import akka.actor._
import akka.io.Tcp
import spray.routing.{HttpService, RequestContext}
import spray.routing.directives.CachingDirectives
@@ -13,7 +13,6 @@ import spray.http._
import MediaTypes._
import CachingDirectives._
-
// 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
class DemoServiceActor extends Actor with DemoService {
@@ -112,7 +111,7 @@ trait DemoService extends HttpService {
def sendStreamingResponse(ctx: RequestContext): Unit =
actorRefFactory.actorOf {
Props {
- new Actor with SprayActorLogging {
+ new Actor with ActorLogging {
// we use the successful sending of a chunk as trigger for scheduling the next chunk
val responseStart = HttpResponse(entity = HttpEntity(`text/html`, streamStart))
ctx.responder ! ChunkedResponseStart(responseStart).withAck(Ok(16))
@@ -3,7 +3,7 @@ package spray.examples
import java.io.File
import org.parboiled.common.FileUtils
import scala.concurrent.duration._
-import akka.actor.{Props, Actor}
+import akka.actor._
import akka.pattern.ask
import spray.routing.{HttpService, RequestContext}
import spray.routing.directives.CachingDirectives
@@ -16,7 +16,6 @@ import spray.http._
import MediaTypes._
import CachingDirectives._
-
// 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
class DemoServiceActor extends Actor with DemoService {
@@ -140,7 +139,7 @@ trait DemoService extends HttpService {
def sendStreamingResponse(ctx: RequestContext): Unit =
actorRefFactory.actorOf {
Props {
- new Actor with SprayActorLogging {
+ new Actor with ActorLogging {
// we use the successful sending of a chunk as trigger for scheduling the next chunk
val responseStart = HttpResponse(entity = HttpEntity(`text/html`, streamStart))
ctx.responder ! ChunkedResponseStart(responseStart).withAck(Ok(16))
@@ -3,13 +3,11 @@ package spray.examples
import scala.concurrent.duration._
import akka.io.Tcp
import akka.actor._
-import spray.util._
import spray.http._
import MediaTypes._
import HttpMethods._
-
-class DemoService extends Actor with SprayActorLogging {
+class DemoService extends Actor with ActorLogging {
def receive = {
case HttpRequest(GET, Uri.Path("/"), _, _, _) =>
@@ -69,7 +67,7 @@ class DemoService extends Actor with SprayActorLogging {
// simple case class whose instances we use as send confirmation message for streaming chunks
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 ...")
// we use the successful sending of a chunk as trigger for scheduling the next chunk
@@ -20,11 +20,10 @@ import scala.util.control.NonFatal
import akka.actor._
import spray.can.client.{ HttpHostConnector, HttpClientSettingsGroup, ClientConnectionSettings }
import spray.can.server.HttpListener
-import spray.util.SprayActorLogging
import spray.http._
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._
private[this] val listenerCounter = Iterator from 0
private[this] val groupCounter = Iterator from 0
@@ -21,7 +21,6 @@ import scala.collection.immutable.Queue
import scala.concurrent.duration.Duration
import akka.actor._
import akka.io.Inet
-import spray.util.SprayActorLogging
import spray.can.client.HttpHostConnector._
import spray.can.Http
import spray.io.ClientSSLEngineProvider
@@ -32,7 +31,7 @@ private[client] class HttpHostConnectionSlot(host: String, port: Int,
options: immutable.Traversable[Inet.SocketOption],
idleTimeout: Duration,
clientConnectionSettingsGroup: ActorRef)(implicit sslEngineProvider: ClientSSLEngineProvider)
- extends Actor with SprayActorLogging {
+ extends Actor with ActorLogging {
// we cannot sensibly recover from crashes
override def supervisorStrategy = SupervisorStrategy.stoppingStrategy
@@ -18,12 +18,11 @@ package spray.can.client
import scala.collection.immutable.Queue
import akka.actor._
-import spray.util.SprayActorLogging
import spray.http.{ HttpHeaders, HttpRequest }
import spray.can.Http
private[can] class HttpHostConnector(normalizedSetup: Http.HostConnectorSetup, clientConnectionSettingsGroup: ActorRef)
- extends Actor with SprayActorLogging {
+ extends Actor with ActorLogging {
import HttpHostConnector._
import normalizedSetup.{ settings _, _ }
@@ -19,13 +19,12 @@ package spray.can.server
import scala.concurrent.duration.Duration
import akka.io.{ IO, Tcp }
import akka.actor._
-import spray.util.SprayActorLogging
import spray.can.server.StatsSupport.StatsHolder
import spray.can.{ HttpExt, Http }
private[can] class HttpListener(bindCommander: ActorRef,
bind: Http.Bind,
- httpSettings: HttpExt#Settings) extends Actor with SprayActorLogging {
+ httpSettings: HttpExt#Settings) extends Actor with ActorLogging {
import context.system
import bind._
@@ -50,7 +50,7 @@ class HttpHostConnectorSpec extends Specification with NoTimeConversions {
step {
val testService = system.actorOf(Props(
- new Actor with SprayActorLogging {
+ new Actor with ActorLogging {
var dropNext = true
val random = new Random(38)
def receive = {
@@ -17,11 +17,10 @@
package spray.io
import java.net.InetSocketAddress
-import akka.actor.{ ActorRef, Terminated, Actor }
+import akka.actor.{ ActorLogging, ActorRef, Terminated, Actor }
import akka.io.Tcp
-import spray.util.SprayActorLogging
-trait ConnectionHandler extends Actor with SprayActorLogging {
+trait ConnectionHandler extends Actor with ActorLogging {
//# final-stages
def baseCommandPipeline(tcpConnection: ActorRef): Pipeline[Command] = {
@@ -10,27 +10,4 @@ spray {
# Always contains the deployed version of spray.
# Referenced, for example, from the `spray.can.server.server-header` setting.
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
- }
}
@@ -20,11 +20,12 @@ import akka.event.{ Logging, LoggingAdapter }
import akka.actor._
/**
- * A LoggingAdapter that can be implicitly supplied from an implicitly available
- * ActorRefFactory (i.e. ActorSystem or ActorContext).
- * Also, it supports optional reformating of ActorPath strings from slash-separated
- * to dot-separated, which opens them up to the hierarchy-based logger configuration
- * of frameworks like logback or log4j.
+ * A LoggingAdapter that can always be supplied implicitly.
+ * If an implicit ActorSystem the created LoggingContext forwards to the log of the system.
+ * If an implicit ActorContext is in scope the created LoggingContext uses the context's
+ * ActorRef as a log source.
+ * 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
@@ -35,47 +36,29 @@ object LoggingContext extends LoggingContextLowerOrderImplicit1 {
def isInfoEnabled = la.isInfoEnabled
def isDebugEnabled = la.isDebugEnabled
- protected def notifyError(message: String): Unit = { la.error(message) }
- protected def notifyError(cause: Throwable, message: String): Unit = { la.error(cause, message) }
- protected def notifyWarning(message: String): Unit = { la.warning(message) }
- protected def notifyInfo(message: String): Unit = { la.info(message) }
- protected def notifyDebug(message: String): Unit = { la.debug(message) }
+ protected def notifyError(message: String): Unit = la.error(message)
+ protected def notifyError(cause: Throwable, message: String): Unit = la.error(cause, message)
+ protected def notifyWarning(message: String): Unit = la.warning(message)
+ protected def notifyInfo(message: String): Unit = la.info(message)
+ protected def notifyDebug(message: String): Unit = la.debug(message)
}
}
private[util] sealed abstract class LoggingContextLowerOrderImplicit1 extends LoggingContextLowerOrderImplicit2 {
this: LoggingContext.type
-
implicit def fromActorRefFactory(implicit refFactory: ActorRefFactory) =
refFactory match {
case x: ActorSystem fromActorSystem(x)
case x: ActorContext fromActorContext(x)
}
-
def fromActorSystem(system: ActorSystem) = fromAdapter(system.log)
-
- 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)
- }
+ def fromActorContext(context: ActorContext) = fromAdapter(Logging(context.system.eventStream, context.self))
}
private[util] sealed abstract class LoggingContextLowerOrderImplicit2 {
this: LoggingContext.type
-
implicit val NoLogging = fromAdapter(akka.event.NoLogging)
}
-/**
- * Trait that can be mixed into an Actor to easily obtain a reference to a spray-level logger,
- * which is available under the name "log".
- */
-trait SprayActorLogging { this: Actor
- val log: LoggingAdapter = LoggingContext.fromActorContext(context)
-}
+@deprecated("Please use akka.actor.ActorLogging directly instead!")
+trait SprayActorLogging extends akka.actor.ActorLogging { _: Actor }
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011-2013 spray.io
- *
- * 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 spray.util
-
-import com.typesafe.config.Config
-
-case class UtilSettings(
- logActorPathsWithDots: Boolean,
- logActorSystemName: Boolean)
-
-object UtilSettings extends SettingsCompanion[UtilSettings]("spray.util") {
- def fromSubConfig(c: Config) = apply(
- c getBoolean "log-actor-paths-with-dots",
- c getBoolean "log-actor-system-name")
-}
Oops, something went wrong.

0 comments on commit e234dd9

Please sign in to comment.