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

Add some helpers for using Kleisli or IOLocal for logging context #676

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

wunderk1nd-e
Copy link

  • Add helpers for logging with some propagated ctx and kleisli implementation
  • Add ce3 module and iolocal instances

@wunderk1nd-e wunderk1nd-e changed the title ctxtual Add some helpers for using Kleisli or IOLocal for logging context Aug 17, 2022
Comment on lines +80 to +88
lazy val ce3 = crossProject(JSPlatform, JVMPlatform)
.settings(commonSettings)
.dependsOn(core)
.settings(
name := "log4cats-ce3",
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-effect" % catsEffectV
)
)

Copy link
Member

@kubukoz kubukoz Aug 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't core already depend on CE3? oh, it doesn't. cool

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we can move this to the slf4j module to don't create a new module. Speaking from a user experience it'd be handier - one wouldn't need to add a new dependency. WDYT?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to go with whatever you guys think is most appropriate - just didn't add it to either of the existing ones because:

  • Core doesn't depend on CE3
  • Isn't strictly speaking an slf4j concern

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With #678 we will be depending on cats-effect, and I see no other way to resolve the UUIDGen issue otherwise.

We'll have to track how the dependency on CE in core goes there as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it depends on cats-effect-std. This still introduces the IO dependency.

@@ -48,4 +48,20 @@ object LoggerFactory extends LoggerFactoryGenCompanion {
fk(logger)
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I somehow missed that LoggerFactory was a thing - nice!

Comment on lines +105 to +108
def withContextF[F[_]: FlatMap](
sl: SelfAwareStructuredLogger[F]
)(ctx: F[Map[String, String]]): SelfAwareStructuredLogger[F] =
new ModifiedContextFSelfAwareStructuredLogger[F](sl)(existingCtx => ctx.map(_ ++ existingCtx))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what we're missing is something like this:

def fa: F[A]

def faWithContext: F[A] = StructuredLogger[F].locally(Map("k" -> "v"))(fa)

so that you can wrap an effect, not just a logger. That would help propagate the context to whatever services you're calling, without a need to pass the context or the updated logger.

Copy link
Author

@wunderk1nd-e wunderk1nd-e Aug 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess I was thinking of users doing that using Kleisli.local or similar for IOLocal.
e.g.

  def scope[G, T](local: IOLocal[T], value: T)(task: IO[G]): IO[G] =
    local.getAndSet(value).bracket(_ => task)(local.set)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you imagining something like StructuredLogger[F].locally would work?
Just specific implementations for where there's a IOLocal or Kleisli around?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think we'll need concrete implementations

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have come to believe that almost all uses of IOLocal should have that cats.mtl.Local shape. See typelevel/cats-effect#3385. And I like the scope name: that's what Local calls it.

@armanbilge
Copy link
Member

Instead of adding a CE3 module I think we should just add a CE3 dependency to the core module. CE2 is officially sunset and there's already blocking footguns in core that can only be fixed with CE3.

@armanbilge
Copy link
Member

So I had a discussion with @ChristopherDavenport on Discord wrt #677. Although he is supportive of adding a CE dependency to core, he still thinks anything IOLocal-based should be in a separate module.

I would expect that should be in a different module.
Not core
Because it's not a way I think folks expect, and the way to do it would be unsafe almost certainly.
Since they will globalize.
IOLocal is overspecified. And FiberLocal is a side library.
So it should be a module or repo with FiberLocal which is a better abstraction then forcing everything to IO

@rossabaker
Copy link
Member

So the cats-effect-std dependency landed in core, but IOLocal would require the full cats-effect. Doing that would pull cats-effect (and IO) into all the downstream projects that limited themselves to cats-effect-std. That's a pretty good argument for a separate module.

@wunderk1nd-e
Copy link
Author

wunderk1nd-e commented Jan 23, 2023

So the cats-effect-std dependency landed in core, but IOLocal would require the full cats-effect. Doing that would pull cats-effect (and IO) into all the downstream projects that limited themselves to cats-effect-std. That's a pretty good argument for a separate module.

I've updated the branch with main - any chance you could approve the workflow run? 🙏

@rossabaker rossabaker added this to the 3.6.0 milestone Feb 20, 2023
Copy link
Member

@rossabaker rossabaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for losing track of this one... I approved the CI run and resolved a merge conflict.

Comment on lines +80 to +88
lazy val ce3 = crossProject(JSPlatform, JVMPlatform)
.settings(commonSettings)
.dependsOn(core)
.settings(
name := "log4cats-ce3",
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-effect" % catsEffectV
)
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it depends on cats-effect-std. This still introduces the IO dependency.

.settings(commonSettings)
.dependsOn(core)
.settings(
name := "log4cats-ce3",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call this log4cats-cats-effect. Anything beyond 3 will be a breaking change, and I'd avoid colloquial abbrevations in a jar name.

Comment on lines +105 to +108
def withContextF[F[_]: FlatMap](
sl: SelfAwareStructuredLogger[F]
)(ctx: F[Map[String, String]]): SelfAwareStructuredLogger[F] =
new ModifiedContextFSelfAwareStructuredLogger[F](sl)(existingCtx => ctx.map(_ ++ existingCtx))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have come to believe that almost all uses of IOLocal should have that cats.mtl.Local shape. See typelevel/cats-effect#3385. And I like the scope name: that's what Local calls it.

@armanbilge
Copy link
Member

armanbilge commented Feb 20, 2023

I have come to believe that almost all uses of IOLocal should have that cats.mtl.Local shape. See typelevel/cats-effect#3385. And I like the scope name: that's what Local calls it.

Should this PR then be in terms of Local, instead of offering specific instances?

@rossabaker
Copy link
Member

I would have thought so, until cats-mtl's future stability was questioned on this pull request. The uncertainty around that statement is blocking a cats-effect PR, a clear path forward on otel4s, and now this.

@armanbilge
Copy link
Member

Yeah. I know it's annoying, but might be worth pausing on this one as well until that's decided. We already have a CE dependency in log4cats core, and CE is already (technically) tied to MTL versioning, and thus so are we.

@rossabaker
Copy link
Member

If @wunderk1nd-e isn't desperate for a release on that, I think that's a sound strategy. The fact everything is being done twice is because there's a lovely type class for this if we'd accept it as a routine dependency.

@mattyjbrown
Copy link

Is it worth it/feasible to add a plain and simple LoggerFactory.withContext, as a way of propagating context when you're passing around LoggerFactorys, or is that going to conflict the eventual implementation of this PR?

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

Successfully merging this pull request may close these issues.

8 participants