-
Notifications
You must be signed in to change notification settings - Fork 74
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
Initial attempt at a logger that allows deferred conditional logging #835
Initial attempt at a logger that allows deferred conditional logging #835
Conversation
Open questions: 1. Is there a better way to do this? 2. Can this be made to work with LoggerFactory? Related to Issue typelevel#834
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this have been less painful if the levels were a sealed trait, and we didn't need multiple DeerredLogMessage
implementations, multiple case statements, etc? Maybe not, because you have to dispatch to the right method on Logger
?
How worried should we be about the unbounded size of the Chain? I don't know what to do about it other than premature logging or dropped logging.
It would probably be about the same. At some point it might be worth collapsing all of these into a single I don't really think this merits the major version bump that removing the existing classes would require, but it's unquestionably tech debt.
That's a good question that I don't really have a concrete answer for. Deferring anything implies some sort of buffer, and it's kind of up to the user to make sure they're not logging so much stuff that it would cause a problem. It might be worth adding something to the scaladoc calling that out caveat. |
@rossabaker I realized I was being kind of lazy about it, so I converted the old There's still the ones hanging around for the testing loggers, but those are old so I left them alone. |
Never mind, TIL that converting a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The size of this feels overwhelming for the simplicity of the added functionality, but I don't see an easier and compatible way, and the functionality seems useful. 👍
Same 😅 |
- Scalafmt - Copyright headers - Add scaladocs and documentation of caveats - Fix incorrect test names - Eagerly respect log levels, when possible - Make ScalaJS happy
3feb2a6
to
97f8e3f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave this open a day or two in case anyone else wants to wade in, but looks good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's huge!
Log4cats is notoriously known for having a sort of complicated hierarchy of interfaces that confuses some newcomers. So I'm wondering if we could not bring new interfaces DeferredLogger
, DeferredLoggerFactory
, DeferredSelfAwareStructuredLogger
and DeferredStructuredLogger
, and devise DeferredSelfAwareStructuredLogger
/ DeferredStructuredLogger
as implementations of SelfAwareStructuredLogger
/ StructuredLogger
with some extra functionality via corresponding 'smart' constructors. WDYT?
core/shared/src/main/scala/org/typelevel/log4cats/extras/DeferredLogger.scala
Outdated
Show resolved
Hide resolved
core/shared/src/main/scala/org/typelevel/log4cats/extras/DeferredLoggerFactory.scala
Outdated
Show resolved
Hide resolved
core/shared/src/main/scala/org/typelevel/log4cats/extras/DeferredStructuredLogger.scala
Outdated
Show resolved
Hide resolved
testing/shared/src/main/scala/org/typelevel/log4cats/testing/StructuredTestingLogger.scala
Outdated
Show resolved
Hide resolved
testing/shared/src/test/scala/org/typelevel/log4cats/extras/DeferredStructuredLoggerTest.scala
Outdated
Show resolved
Hide resolved
testing/shared/src/test/scala/org/typelevel/log4cats/extras/DeferredLoggerTest.scala
Outdated
Show resolved
Hide resolved
testing/shared/src/test/scala/org/typelevel/log4cats/extras/DeferredLoggerFactoryTest.scala
Outdated
Show resolved
Hide resolved
testing/shared/src/main/scala/org/typelevel/log4cats/testing/TestingLoggerFactory.scala
Outdated
Show resolved
Hide resolved
testing/shared/src/main/scala/org/typelevel/log4cats/testing/TestingLogger.scala
Outdated
Show resolved
Hide resolved
def apply[F[_]: Concurrent]( | ||
loggerFactory: LoggerFactory[F] | ||
): Resource[F, DeferredLoggerFactory[F]] = | ||
DeferredSelfAwareStructuredLogger.makeCache[F].map { cache => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DeferredLoggerFactory
depends on DeferredSelfAwareStructuredLogger
. It feels a bit non-shapely. Also, it makes me think that perhaps we don't need the DeferredLoggerFactory
at all... But maybe I'm overlooking something simple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ended up paralleling a similar dependency in LoggerFactory
, as that conceptually depends on SelfAwareStructuredLogger
(it's a bit hard to see in the code, but LoggerType
is a big clue).
We need DeferredLoggerFactory
because, the way LoggerFactory
is written, it's near enough impossible to create a LoggerFactory
that emits DeferredSelfAwareStructuredLogger
s that are aware that they are DeferredSelfAwareStructuredLogger
s rather than vanilla SelfAwareStructuredLogger
s - which then makes it impossible to manually trigger logging for errors that don't involve an error embedded in F[_]
I'm sure that, if we're able to do breaking changes, then we'd be able to streamline this considerably. That being said, I don't think we can get away with a completely folded hierarchy because of the need to expose the |
> Let's keep coherency with the old-fashioned but widely adopted imports across the Log4cats Co-authored-by: Daniel Esik <[email protected]>
I mean, we could have something like this trait InspectLogging[F[_]] {
def inspect: F[Chain[DeferredLogMessage]]
def log: F[Unit]
}
object StructuredLogger {
def makeDeferred[F[_]]: StructuredLogger[F] with InspectLogging[F] = ???
} Do we actually need new subtypes like |
I'm not really sure it'll make much of a difference in terms of the volume of the code, other than potentially making the type signatures longer 🤷🏻 I would be a bit reluctant to put the implementations into the companion objects of the existing loggers, for two reasons:
The thoughts I had about streamlining this via breaking changes would be to try and figure out how to take advantage of the general shape that e.g. |
I'm not worrying about reducing code size or having code DRY at max. I'm rather worried about adding new abstractions. |
I am, I messed up the dispatching a bunch of times, that's why there are so many tests 😅
Fair enough, I'll see what I can do with it. We're under a heat advisory and that makes it hard to get anything done, so I wouldn't expect to see any movement before the weekend. |
JFTR, I don't want to be a party pooper! My comments should be considered mostly as recommendations, and Ross's approval is enough to move on. |
No worries. A bit of surprise good/bad news: we probably do need the subclasses. Without them the ability to log on demand is lost at the first The good news is that the process of figuring out raised a missed override of As an aside, how easy it was to miss that these were missed is an example of why I'd like to figure out if there's a better way to abstract over the various ways that loggers are transformed. It's just way too easy to get wrong. |
Also collapse the new LogMessage classes into a single class
…e/log4cats into deferrable-loggers
I think I may have found a way to improve the experience of transforming loggers, it's currently in PR in my fork (due to merge target shenanigans), but I'll convert it to a PR here once this is merged. |
Open questions:
Can this be made to work with LoggerFactory?YesRelated to Issue #834