-
Notifications
You must be signed in to change notification settings - Fork 130

Description
Hi,
TL;DR I need another type of logger, other than regular or LoggerTakingImplicit
. I need a LoggerInMixinContext
or something like that.
scala-logging has Logger and Logger.takingImplicit[Context](canLogContext)
,
Logger has no concept of context,
LoggerTakingImplicit
assumes context is passed on each method implicitly.
I have chosen a different strategy to handle context: create an instance per request, bound to the context, like so:
class MyClass(collaborator: Collaborator)(context: Context) {
def doSomething(payload: Payload): ...
}
object Server {
val collab: Collaborator = ...
val myUncontextedClass = new MyClass(collab)(_)
def onRequest(payload: Payload, context: Context) = myUncontextedClass(context).doSomething(payload)
}
I need a logger that can take the context from the instance it's mixed in with, rather than the context passed implicitly on each method.
something like this maybe
object CanLogContext extends CanLog[Context] ...
trait LoggerInContext[Context] {
def context: Context
@transient
protected val logger = Logger.inContext(context, CanLogContext) //have this use all the cool macro stuff
}
I tried doing something like that myself but all of your classes are private final (especially the macro expansions, so i can't implement our own logger like this).
umm, why is that btw?
The reason why i can't just use the logger taking implicit even in my use case (the callscope is available and can be implicit, so why not just use it?) is because i want to abstract away the context from the core:
//core, no context exists here
trait MyBehavior {
def doSomething(payload: Payload)
}
//core, no context exists here
class MyClass(collaborator: Collaborator, logger: Logger) extends MyBehavior {
def doSomething(payload: Payload) = {
logger.trace(s"doing something with collaborator $collaborator, payload $payload")
doSomethingWithCollaborator(collaborator, payload)
}
}
//context aware layer, this is just wiring of context and things that need it, wrapping the core objects
class MyContextAwareClass(contextAwareCollaborator: Context => Collaborator)(context: Context) extends MyBehavior with LoggerInContext {
//get context bound collaborators / adapters
private val collaborator = contextAwareCollaborator(context)
//get context bound pure core object, unaware of context
private val myClass = new MyClass(collaborator, logger) // note the use of a context bound logger
//delegate all logic to "pure" core
def doSomething(payload: Payload) = myClass.doSomething(payload)
}
Since in core/domain "pure" MyClass there is no implicit Context or concept of context at all, I would not be able to use the LoggerTakingImplicit which requires context on invocation of any log method.
If you approve of this idea but don't think it has high priority or wish to implement it yourselves i am open to contributing to you it via PR if you are willing to merge it when it's done.
Alternatively, if you would be willing to make your macros / traits / classes public and not private final, so consumers can reuse them to compose additional loggers, that would also be great...
many thanks!