There’s still no good logging library :open_mouth:...
# opensource
m
There’s still no good logging library 😮 And almost all of them synchronously write IO to console which is not nice with coroutines, or performance in general.
d
whats wrong with log4j2?
m
uhm. It’s for Java
d
🤷 you can still use it from Kotlin and based on their performance benchmarks I am unsure whether you could easily get to that level
*unless you are not targeting JVM
m
I’m more interested in Kotlin-like interface (e.g. inline fun so that I don’t have check log level manually), multiplatform & coroutines support.
So something truly Kotlin 🙂
h
Create it!
m
Wrapping log4j2 seems like an easy task
l
@ilya.gorbunov Is that (logging library) something we can expect in kotlinx in 1-2 years? Asking to know if we should make a library in the community.
m
@hallvard yeah that’s probably what I’m going to do. But just a simple one. I find something like log4j wayyy to overpowered for most software. Once you’ve grown your product so much that you require all that functionality you can still change library. Or we provide generic extension points and others can extend it. I had to write simple logging classes for me already so I can just package that as one of too many libraries 😄
👍 2
o
interesting, does anyone have some logger (even like prototype), based on coroutines? And why you really need it based on them?
m
Because logging is blocking IO and shouldn’t happen on the thread where you create a log entry. It could temporarily block arbitraty coroutine dispatchers. Therefore my logger prepares the log message, sends it through a channel to the IO dispatcher and logs it there.
h
Doesn't Lgback permit something similar? If I remember correctly, there's a setting named immediateFlush or somthing, that could be set to false ...
m
I won’t use any Java logger without wrapping anyway. I’d always have to check something like
if (logger.isTraceEnabled) { logger.trace(…) }
which I don’t need if I use Kotlin inline functions:
log.trace { … }
.
So if I abstract the entire front-facing part I can as well add a simple implementation for the rest. You could still plug in slf4j if you want to.
But even slf4j has limitations. For example I cannot pass the timestamp to the log functions. That’s bad when you log asynchronously.
o
I understand that it's IO, but why coroutines? on JVM loggers will handle that on their own, on JS - single thread, only on native, you can push messages to worker, to unload current worker as I see, coroutines, will not give here much sense
m
I won’t create my own threads unless I really have to. Coroutines are widely available now so why still use threads?
o
So you want to use your own JVM logger implementation, based on coroutines, or what? If you will anyway push to slf4j, it will be handled automatically by using some AsyncLogger, that will handle context switch and no blocking will be
m
slf4j is just one option for forwarding if you have to. I’d prefer to have a multiplatform logging library that works consistently across all platforms, is simple with a well-design API for Kotlin. With no external dependencies.
Copy code
val logger = Log.slf4j("foo").withContext(<http://Dispatchers.IO|Dispatchers.IO>)
You could throw any kind of Log in any coroutine context. Or not use coroutines at all.
o
With no external dependencies.
use java.util.logging for jvm + some async handler that will use coroutines if needed Im just not sure, that coroutines are needed for logging, but it's just my opinion BTW, Im also now trying to create some flexible common logger 🙂
w
it would be cool to see a multiplatform logging library, that just delegates to an slf4j implementation in jvm, but then has other implementations for other platforms
o
@wakingrufus Look at microutils/kotlin-logging for that
w
oh nice i didnt realize it was multiplatform. i have only used the jvm flavor of that
o
It happened not so long ago But anyway, it supports only desktop native targets
a
As a user of such a library, I would like to be able to log from not only
suspend
functions. Therefore the library's API should not be based on coroutines. And as a user of such a library I don't care what is used under the hood. I'm ok using it if it has good performance.
l
@Arkadii Ivanov Logging should not delay program operation, so even from suspending functions, you wouldn't want that. However, using channels to send/offer the values, and managing log output with coroutines is perfectly fine.
m
@Arkadii Ivanov the log functions wouldn’t need to be
suspend
if you use coroutines because you can use either Channels or
GlobalScope
.
a
Using coroutines as well as any other async/background library is totally fine in a logging library. What I want to say is I don't care what is used inside, as long as it works fast. I would not choose a logging library just because it is based on coroutines. Actually my benchmarks shown not a good results for native coroutines in some cases. So a simple Worker with a custom queue might work even better.
Coroutines library is not a silver bullet, and does not mean "performance by default". 😀
n
True, however logging is a I/O intensive task which Coroutines is designed for.
There is a logging library written in Kotlin called Kotlin Logging ( https://github.com/MicroUtils/kotlin-logging ). Initial Kotlin Native support (for the linuxX64 target only) was added to the library.