Skip to content

feature request: logger taking context from mixin #208

@ghost

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions