Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature request: logger taking context from mixin #208

Open
grunzwei opened this issue Feb 23, 2020 · 4 comments
Open

feature request: logger taking context from mixin #208

grunzwei opened this issue Feb 23, 2020 · 4 comments

Comments

@grunzwei
Copy link

grunzwei commented Feb 23, 2020

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!

@or-shachar
Copy link

@analytically WDYT?

@analytically
Copy link
Collaborator

PR?

@grunzwei
Copy link
Author

grunzwei commented Mar 1, 2020

@analytically i'll try and do it in the next few days, thanks!

grunzwei added a commit to grunzwei/scala-logging that referenced this issue Mar 24, 2020
… you don't want to pass it each time via implicit for every call, just set it once when you instantiate the logger.

see lightbend-labs#208
grunzwei added a commit to grunzwei/scala-logging that referenced this issue Mar 24, 2020
… you don't want to pass it each time via implicit for every call, just set it once when you instantiate the logger.

see lightbend-labs#208
@grunzwei
Copy link
Author

grunzwei commented Mar 24, 2020

#212

WIP, have some pain points as mentioned in description, also i just realized one of the usecases i wanted to support won't work because the logger call site will be incorrect. would appreciate advice if you have any.

@analytically FYI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants