Giter Site home page Giter Site logo

kotlin-logging's Introduction

Lightweight Multiplatform logging framework for Kotlin, written in Pure Kotlin.
A convenient and performant logging facade.

Call log methods, without checking whether the respective log level is enabled

logger.debug { "Some $expensive message!" }

Behind the scenes the expensive message do not get evaluated if debug is not enabled:

// This is what happens when you write the above ^^^
if (logger.isDebugEnabled) logger.debug("Some $expensive message!")

Define the logger, without explicitly specifying the class name

// Place definition above class declaration to make field static
private val logger = KotlinLogging.logger {}

Behind the scenes val logger will be created in the class, with the class/file name:

// This is what happens when you write the above ^^^
val logger = LoggerFactory.getLogger("package.ClassName")

Log exceptions in a Kotlin-style

// exception as first parameter with message as lambda
logger.error(exception) { "a $fancy message about the $exception" }

Fluent logging in a Kotlin-style

logger.atWarn {
    message    = "foo $bar"
    cause      = exception
    payload    = buildMap(capacity = 3) {
        put("foo", 1)
        put("bar", "x")
        put("obj", Pair(2, 3))
    }
}

Getting started

import io.github.oshai.kotlinlogging.KotlinLogging

private val logger = KotlinLogging.logger {} 

class FooWithLogging {
    val message = "world"
    fun bar() {
        logger.debug { "hello $message" }
    }
}

Version 5 vs. previous versions

Version 5 is not backward compatible with previous versions (v.3, v.2, v.1). Group id (in maven) and packages names changed. It is possible to use both version 5 and previous versions side-by-side so some of the code from the old version and some new. It is also possible to have libs using old version and use the new version (and vice-versa).
In that sense it's a completely new dependency.

Main changes are:

  • Maven group id changed from io.github.microutils -> io.github.oshai.
  • Root package change from mu -> io.github.oshai.kotlinlogging.
  • Slf4j dependency is not provided anymore (users have to provide it). It means that >= 5.x can work with both slf4j 1 or 2.
  • There are changes to multiplatform class hierarchy that might break compatibility.

More details in issue #264, and in the change log

Download

Important note: kotlin-logging depends on slf4j-api (in the JVM artifact). In runtime, it is also required to depend on a logging implementation. More details in how-to-configure-slf4j. And an excellent detailed explanation in a-guide-to-logging-in-java.
In version 5 users should also provide slf4j-api dependency.

In short, if you just want to log statements to stdout, it's possible to add the following dependency: org.slf4j:slf4j-simple:2.0.3.

Maven

<dependency>
  <groupId>io.github.oshai</groupId>
  <artifactId>kotlin-logging-jvm</artifactId>
  <version>5.1.0</version>
</dependency>

See the full example in kotlin-logging-example-maven.

Gradle

implementation 'io.github.oshai:kotlin-logging-jvm:5.1.0'

Alternatively, download the JAR from github or maven-central.

Multiplatform

An experimental multiplatform support is available.
More information is available on the wiki and issues #21 #45.

Overview

After seeing many questions like Idiomatic way of logging in Kotlin and Best practices for loggers, it seems like there should be a standard for logging and obtaining a logger in Kotlin. kotlin-logging provides a wrapper for slf4j-api to be used by Kotlin classes with the following advantages:

  • No need to write the logger and class name or logger name boilerplate code.
  • A straight forward way to log messages with lazy-evaluated string using lambda expression {}.
  • All previous slf4j implementation can still be used.

Who is using it

And many more... (add your name above)

FAQ

  • Why not use plain slf4j? kotlin-logging has better native Kotlin support. It adds more functionality and enables less boilerplate code.
  • Is all slf4j implementation supported (Markers, params, etc')? Yes.
  • Is location logging possible? Yes, location awareness was added in kotlin-logging 1.4.
  • When I do logger.debug, my IntelliJ IDEA run console doesn't show any output. Do you know how I could set the console logger to debug or trace levels? Is this an IDE setting, or can it be set in the call to KLogging()? Setting log level is done per implementation. kotlin-logging and slf4j are just facades for the underlying logging lib (log4j, logback etc') more details here.
  • Can I access the actual logger? In platforms available yes, via DelegatingKLogger.underlyingLogger property.

Usage

  • See wiki for more examples.

It is possible to configure IntelliJ live templates. For file level logger configure the following:

  • Text template: private val logger = io.github.oshai.kotlinlogging.KotlinLogging.logger {}.
  • Applicable in Kotlin: top-level.

Support

More links

Contributing

Any contribution is appreciated.
See the contributors list in: https://github.com/oshai/kotlin-logging/graphs/contributors

Pull requests are welcome! See instructions in https://github.com/oshai/kotlin-logging/blob/master/CONTRIBUTING.md.

Show your ❤ with a ★

kotlin-logging's People

Contributors

altavir avatar aybefox avatar azimmuradov avatar bespaltovyj avatar borzdeg avatar connected-zfreedman avatar conradev avatar corneil avatar darioseidl avatar dependabot[bot] avatar ilya-yamschikov avatar imanushin avatar imsprathap avatar jangalinski avatar krokofant avatar lrusso96 avatar mfickett avatar mlewe avatar morj avatar napperley avatar oshai avatar ravikumar-n avatar rnentjes avatar sebastianaigner avatar severn-everett avatar stigkj avatar t0astt avatar walokra avatar yarnsphere avatar yeikel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotlin-logging's Issues

How to show time of log

i've seen the documentation but, i didn't find anything about it.

I wanna show logger like log4j where u can set the log pattern

Any way to (easily) grab an extra copy of the logs?

Logging works great! It picks up /resources/simplelogger.properties just fine and prints to console, great ramp-up.

Now I'd like to do something extra with the info+ level logs (write them to a db) Which I assume is a "Handler" But I started looking into slf4j-simple and Handlers, and wasn't sure where to start.

Is there an easy way to say "also throw everything at this function, thanks!"

oddity with delegation of isDebugEnabled

I have configured my underlying logger to debug log, but I'm not getting any output.
I then error logged a look at the logger and the underlying logger. The underlying logger says debug is enabled, but when I ask the KotlinLogger about debug, it says it is not enabled.

It's weird. I see in LocationIgnorantKLogger that it uses delegation to the underlying logger, but it doesn't seem to be working since the values differ.

Any thoughts on this?

logger.error { "logger.javaClass.simpleName = ${logger.javaClass.simpleName}" }
        logger.error { "logger.underlyingLogger.javaClass.simpleName = ${logger.underlyingLogger.javaClass.simpleName}" }
        logger.error { "logger.isDebugEnabled = ${logger.isDebugEnabled}" }
        logger.error { "logger.underlyingLogger.isDebugEnabled = ${logger.underlyingLogger.isDebugEnabled}" }

output:

ERROR: logger.javaClass.simpleName = LocationIgnorantKLogger
ERROR: logger.underlyingLogger.javaClass.simpleName = TinylogLogger
ERROR: logger.isDebugEnabled = false
ERROR: logger.underlyingLogger.isDebugEnabled = true

KLogger obscures location info

I am using log4j with a patternlayout that includes class, method, and line number information. I expect log statements to print in the form below. This form holds when I manually set val logger: Logger = LoggerFactory.getLogger(this.javaClass).

INFO TEST_CONFIG.<init>(80) - test log

Instead, when I extend a companion object (or any singleton object) with object : KLogging(), the following unhelpful information prints

INFO KLogger.info(?) - test log

The code responsible for picking the location info is here in LocationInfo. The code sees that KLogger is the immediately logging class on the stack trace and uses KLogger for location info. It should instead use the class immediately below KLogger in the stack trace.

I'm not sure how to fix it, but there should be some hook in the log4j (ideally, slf4j) library that allows manipulating location info.

Inline all logging functions

It seems that the whole fuzz around logging is to not create "expensive" String object, if logging level is not enabled. That totally makes sense.

And that's why we library offers a nice function:

    fun unknownElementType(elementType: Int) {

        // Lazy evaluation of the log message
        log.warn  { "Unknown element: $elementType" }

    }

So, what gets generated for this line?

this.log.warn((Function0)(new Function0() {
         // $FF: synthetic method
         // $FF: bridge method
         public Object invoke() {
            return this.invoke();
         }

         @NotNull
         public final String invoke() {
            return "Unknown element: " + elementType;
         }
      }));

Hm... instead of a String, we create:

  1. An anonymous inner class
  2. Instance of this class, which gets the closure reference to all required outer variables like elementType

That doesn't look very cheap to me.

On the other hand, in Kotlin StdLib pretty much all map or forEach functions are inline. So, we might write it like this:

inline fun KLogger.warnInline(message: () -> String) {
    if (underlyingLogger.isWarnEnabled) 
        underlyingLogger.warn(message())
}

And this gets compiled to the simplest possible, desired lazy evaluation of String:

   void unknownElementType(int elementType) {

      KLogger $receiver$iv = this.log;
      Logger logger$iv = $receiver$iv.getUnderlyingLogger();
      if (logger$iv.isWarnEnabled()) {
         // Lazy evaluation of the log message
         String var7 = "Unknown element: " + elementType;
         logger$iv.warn(var7);
      }

   }

Just like we wanted in the first place.

Have to use companion object for something else too

@oshai First of all: AWESOME LIB! 🏆

But...I really want something like this...

companion object {
        const val VIEW_NAME = ""
        val logger = KLogging().logger()
    }
    
    fun some() { logger.debug {"foo bar"}}

Unfortunately this way your library uses it's own class (mu.Klogging) in the log file:

2017-09-22 11:10:24.831  INFO 5919 --- [nio-8082-exec-6] mu.KLogging                              : foo bar

Is there a kotlin way that I can use the companion object for something else too?

Feature: MDC support

Consider adding some additional functions for managing MDC (Javadoc: https://www.slf4j.org/api/org/slf4j/MDC.html) by putting and removing keys

Additional consideration: it would be great to have it with coroutines

Docs: https://www.slf4j.org/manual.html#mdc

I don't have a concrete API proposal but here is some initial thoughts:

object MDC {
  // additional overloads for varargs and up to some N number of `Pair`
  fun <T> withContext(keyPair: Pair<String, String>, body: () -> T) {
    return org.slf4j.MDC.putCloseable(keyPair.first, keyPair.second).use {
      body()
    }
  }
}

Null values are causing problems

LocationAwareKLogger class uses not nullable arguments for logging operations. Because of this when a null parameter value is passed it causes an exception and doesn't log anything. Passing such values are OK according to slf4j api and it works fine with underlying implementations (log4j, logback, etc.)

val param : String? = null
logger.warn("Nulls should work {}!", param)

Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method mu.internal.LocationAwareKLogger.warn, parameter arg
at mu.internal.LocationAwareKLogger.warn(LocationAwareKLogger.kt)

Upgrade to Kotlin 1.3.0

kotlin-logging is dependent of Kotlin 1.2.60 which causes problems when used on Kotlin 1.3.0 project.

Support SLF4J Markers

The SLF4J Logger allows specifying a Marker for log messages, e.g.

log.debug(MARKER, msg)

It would be nice if the KLogger would support these too to be able to specify a marker when using a lambda for the message.

I'd be happy to submit a pull request :)

How to set project loglevel

Hi,

Thanks for putting this library together. In using kotlin, I was putoff by the long/complex answers to the simple question "how do you log in kotlin (http://stackoverflow.com/questions/34416869/idiomatic-way-of-logging-in-kotlin)".

I'm using Klogging as follows:

    companion object: KLogging()

     init {
        logger.info("NewsArticle initialized: " + this)
      }

This works nicely, but when I do logger.debug, my IntelliJ IDEA run console doesn't show any output. Do you know how I could set the console logger to debug or trace levels? Is this an IDE setting, or can it be set in the call to KLogging()?

performance problem: logger.*(lambda) are not inlined

Problem

The logger.info/debug/error/etc. calls that take a lambda should be inlined.
Otherwise we replace the creation of one object (e.g. a StringBuilder) with the creation of another object (the lambda instance), which in time will put unnecessary pressure on the garbage collector.

Decompile a class that has logger.*(lambda) calls to see the problem. The procyon decompiler works ok for this case, though sometimes it chokes on Kotlin compiled bytecode.

I wanted to fix this myself and create a pull request, but these calls are inside an interface (KLogger) and functions inside interfaces cannot be inlined. This probably means that fixing this issue will result in breaking the existing API. Since it's your call if you want to break the backwards compatibility (and in what way), I didn't do it.

Idea for solution

Here is an idea for the solution:

import org.slf4j.Logger
import org.slf4j.LoggerFactory

fun main(args: Array<String>) {
    App().sayHi("World")
}

class App {

    companion object {
        private val logger = KInlineLogger.create()
    }

    fun sayHi(name: String) {
        logger.info { "Hello $name!" }
    }
}

class KInlineLogger private constructor(val wrappedLogger: Logger): Logger by wrappedLogger  {

    companion object {
        private val kInlineLoggerFqn = KInlineLogger::class.java.name

        fun create(): KInlineLogger {
            return KInlineLogger(
                    LoggerFactory.getLogger(
                            findLoggerName()
                    )
            )
        }

        private fun findLoggerName(): String {
            val exception = Exception()

            return exception.stackTrace
                    .map { it.className }
                    .filter { it != kInlineLoggerFqn }       // exclude self
                    .filter { !it.endsWith("\$Companion") }  // exclude self companion & any other companions (if the KInlineLogger is declared inside a companion object)
                    .first()
        }
    }

    inline fun info(messageBlock: () -> Any) {
        if (wrappedLogger.isInfoEnabled) {
            wrappedLogger.info(messageBlock.invoke().toString())
        }
    }

}

The App.sayHi method compiles to:

public final void sayHi(@NotNull final String name) {
    Intrinsics.checkParameterIsNotNull((Object)name, "name");
    final KInlineLogger this_$iv = App.Companion.getLogger();
    if (this_$iv.getWrappedLogger().isInfoEnabled()) {
        this_$iv.getWrappedLogger().info(("Hello " + name + "!").toString());
    }
}

Which is how we would optimize it manually.

Without inlining the info method though, a lambda instance is created (to capture the name):

public final void sayHi(@NotNull final String name) {
    Intrinsics.checkParameterIsNotNull((Object)name, "name");
    App.Companion.getLogger().info((Function0<?>)new App$sayHi.App$sayHi$1(name));
}

Notice how the lambda is instantiated, creating an unnecessary object, that the garbage collector has to clean.
A new object will be created for each log statement that needs to capture some variables.

In addition to this the call to the constructor and the dispatch to lambda.invoke is not free. It probably takes very little time, but it's unnecessary.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder"

i added below code to build.gradle
implementation 'io.github.microutils:kotlin-logging:1.5.9'

then I compiler & run show this message:
09-02 00:31:12.297 28733-28733/com.example.tonyyang.tonyptt W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Issues

Hi,

following the readme, I instantiated at top level here: val logger = KotlinLogging.logger {}

and then I use wherever I need it like: logger.warn{ "omg" }

But whenever I run some tests, I always get the following:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

why?

Weblogic - java.lang.NoClassDefFoundError: mu/KotlinLogging

Hi,
I tried to use this logging in application which I deployed to Weblogic (12.2.1.1.0) and I've got an java.lang.NoClassDefFoundError: mu/KotlinLogging. On embedded Tomcat the application is running well. When I remove KotlinLogging from service, application is running on Weblogic well too.
Application uses Spring Boot (2.1.3), Gradle and Kotlin. I'm Kotlin newbie so maybe I'm doing something wrong..

Given class:

private val logger = KotlinLogging.logger {}
@Service
internal class CockService(
        @Value("\${spring.datasource.url}")
        val db: String) {
    @Scheduled(fixedDelay = 10 * 1000, initialDelay = 10 * 1000)
    fun export() {
        logger.info("Database URL: $db")
    }
}

Exception:

java.lang.NoClassDefFoundError: mu/KotlinLogging
	at cz.homecredit.cock.service.CockServiceKt.<clinit>(CockService.kt:15) ~[_wl_cls_gen.jar:na]
	at cz.homecredit.cock.service.CockService.export(CockService.kt:27) ~[_wl_cls_gen.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_144]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_144]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_144]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_144]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_144]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_144]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]
Caused by: java.lang.ClassNotFoundException: mu.KotlinLogging
	at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:1025) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:986) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAwareClassLoader.java:83) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.GenericClassLoader.doFindClass(GenericClassLoader.java:607) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:539) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:492) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:469) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	at weblogic.utils.classloaders.ChangeAwareClassLoader.loadClass(ChangeAwareClassLoader.java:53) ~[com.bea.core.utils.classloaders.jar:12.2.1.1]
	... 15 common frames omitted

Support for slf4j-ext

How about support for slf4j-ext https://www.slf4j.org/extensions.html#extended_logger

This would imply something like:

actual interface KXLogger : XLogger, KLogger {
 // similar to KLogger with added methods for XLogger
}

open class KXLogging : KXLoggable {
    override val logger: KXLogger = logger()
}

I would be up for the PR if you are interested.

[Question] Next release?

I just discovered the JS log level issue in 1.6.10, and I can see its fixed in the repo... will a new release be cut soon that includes that change? The library looks great other then that issue! 💯

Incorrect file name and line number

For my logback.xml configuration of:

<pattern>... \(%F:%L\) %msg%n</pattern>

I'm consistently getting file name / line number in the KLogger file (KLogger.kt:23) for all my debug statements, which is precisely where KLogger itself calls debug().

I'm using 1.4.2 so #11 shouldn't apply. This happens when I use val logger = LoggerFactory.getLogger("class name") or private val logger = KotlinLogging.logger {}.

Thanks!

update to android studio 3.0 logging can't work

can't see any logger to console

10-19 04:37:09.356 17905-17917/? I/art: Debugger is no longer active

10-19 04:37:10.507 17905-17905/ I/InstantRun: starting instant run server: is main process
10-19 04:37:10.546 17905-17905/ W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
10-19 04:37:10.547 17905-17905/ W/System.err: SLF4J: Defaulting to no-operation (NOP) logger implementation
10-19 04:37:10.547 17905-17905/ W/System.err: SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Kotlin-Reflect dependency

Is there a way to drop the kotlin reflection dependency? a 5 MB library for getting the name of the class from companion sounds too much :)

Two questions: Swallowing exceptions? Accepting nullable Throwables?

Hello,

Thank you for this library! I love how it provides true lazy-evaluation. Prettier and, afaict, even faster than the idiomatic way of Slf4j log.info("foo: {}", bar).

However, I noticed the toStringSafe method in MessageInvoker.kt:

internal inline fun (() -> Any?).toStringSafe(): String {
    try {
        return invoke().toString()
    } catch (e: Exception) {
        return "Log message invocation failed: $e"
    }
}

This means that exceptions from a logging lambda will be caught and swallowed. Just the exception message will be logged, on the same log level as the base statement. E.g.

log.info{"Test ${"x".toInt()}"}   

prints, on level INFO

Log message invocation failed: java.lang.NumberFormatException: For input string: "x"

I'm wondering if this is desirable? It should be rare to actually get any exception from a log statement, but when it happens, I would rather see the exception fall through so that it can be handled by whatever root exception handling is in place. In our current project, we would log on level ERROR and send a mail, to make sure that no exception goes unnoticed.

What do you think? Is there a way to skip or replace the toStringSafe?

--

Another thing, not very important at all, but is there a reason that the methods of Klogger.kt don't accept nullable Throwables?

I would like to do, for example, the following, in an exception handler implementation

val ex: Throwable? = httpServletRequest.getAttribute(DispatcherServlet.EXCEPTION_ATTRIBUTE) as? Throwable
log.error (ex) { "Error $status dispatched for request $requestURI" } 

That's not possible though, since ex is nullable, and KLogger.error expects an Throwable. The underlying Slf4j logger would accept null and simply handle it as if no exception was passed to it. so I don't see a reason why Klogger could not accept a Throwable? as well.

Companion Object's logger is public

Normally, when we define a logger in our class, it is private. But if we use the companion object strategy, there's no way to achieve that.

Kotlin 1.2.0 support

In class "KLoggerNameResolver" the line
"import kotlin.reflect.companionObject" (this was deprecated anyway in Kotlin 1.1)
should change to
"import kotlin.reflect.full.companionObject"

in a build npm

Hello,
I use your project in my own mpp kotlin lib
I plan to use my lib and your in another app build by npm. (package.json)

Any Idea how I can publish my lib on npm or what i should add to my package.json to use my lib?

Thank-you !

Please add copyright notice

The project contains an Apache 2.0 license file, however, it does not follow the conditions and recommendation in the appendix of the license.

Packages are routinely rejected by the OSS legal offices because of missing or incomplete copyright information. So it would be great to include the copyright statement to avoid problems when using this framework.

Apache 2 license conditions according to Github License summary
License and copyright notice
State changes

Thanks a lot.

Need a guide setting up JS flavor

Adding compile 'io.github.microutils:kotlin-logging:1.6.20' to Gradle dependencies only pulls jvm and common artifacts, and can't be used for a js project

Examples/documentation with custom message format and different loggging system

Ok I have included this lib via maven dependency and what next?

  1. What logging system it uses by default?
  2. I have put log4j.properties file in resources folder which has no impact on logging. So additional dependencies for log4j should be added? What exactly?
  3. The same question about logback
  4. Could please provide a couple of maven project with different message format settings for different logging system? This would be the best to see exact examples.

Duplicate zip entry causing build failures

I just tried updating to Kotlin Logging 1.4.7 but when I try to build my project, I get the following error:

Warning:Exception while processing task java.io.IOException: Can't write [D:\AndroidApp\Repo\app\build\intermediates\transforms\proguard\debug\0.jar] (Can't read [C:\Users\User\.gradle\caches\modules-2\files-2.1\io.github.microutils\kotlin-logging\1.4.7\8b05153a42982548197a87f0aed852c8804c943f\kotlin-logging-1.4.7.jar(;;;;;;**.class)] (Duplicate zip entry [kotlin-logging-1.4.7.jar:mu/internal/KLoggerFactory.class]))

The SHA-1 hash of kotlin-logging-1.4.7.jar in my gradle cache is: 8B05153A42982548197A87F0AED852C8804C943F

The jar has duplicate entries for every .class file when viewed in 7-zip. I examined the .class files in a text editor and it seems like one file is using the string "kotlin-logging" and the other is using "kotlin-logging_main".

Doesn't work out of the box

I am authoring an android app and added the build.gradle compile line as told:

compile 'io.github.microutils:kotlin-logging:1.4.9'

The logcat output when actually using my app:

03-10 23:28:59.090 25160-25160/? I/InstantRun: starting instant run server: is main process
03-10 23:28:59.150 25160-25160/? W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
03-10 23:28:59.150 25160-25160/? W/System.err: SLF4J: Defaulting to no-operation (NOP) logger implementation
03-10 23:28:59.150 25160-25160/? W/System.err: SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

I know that third-party libraries are not supposed to place a dependency on a slf4j implementation. But ideally the installation instructions should produce a working implementatation, even for Java/Kotlin/Android newbies.

Suggestion: tell users how to set up slf4j when using kotlin-logging.

Kotlin/Native Support

As issue #21 was only dedicated for Kotlin/JVM and Kotlin/JS multi platform support, this issue is for Kotlin/Native support.

Kotlin/Native target platform is seen in org.jetbrains.kotlin.konan.target.KonanTarget.kt file
line 43 as of 2018 August 16th:

sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named {
    object ANDROID_ARM32 :  KonanTarget( "android_arm32",   Family.ANDROID, Architecture.ARM32)
    object ANDROID_ARM64 :  KonanTarget( "android_arm64",   Family.ANDROID, Architecture.ARM64)
    object IOS_ARM32 :      KonanTarget( "ios_arm32",       Family.IOS,     Architecture.ARM32)
    object IOS_ARM64 :      KonanTarget( "ios_arm64",       Family.IOS,     Architecture.ARM64)
    object IOS_X64 :        KonanTarget( "ios_x64",         Family.IOS,     Architecture.X64)
    object LINUX_X64 :      KonanTarget( "linux_x64",       Family.LINUX,   Architecture.X64)
    object MINGW_X64 :      KonanTarget( "mingw_x64",       Family.MINGW,   Architecture.X64)
    object MACOS_X64 :      KonanTarget( "macos_x64",       Family.OSX,     Architecture.X64)
    object LINUX_ARM32_HFP :KonanTarget( "linux_arm32_hfp", Family.LINUX,   Architecture.ARM32)
    object LINUX_MIPS32 :   KonanTarget( "linux_mips32",    Family.LINUX,   Architecture.MIPS32)
    object LINUX_MIPSEL32 : KonanTarget( "linux_mipsel32",  Family.LINUX,   Architecture.MIPSEL32)
    object WASM32 :         KonanTarget( "wasm32",          Family.WASM,    Architecture.WASM32)

    // Tunable targets
    class ZEPHYR(val subName: String, val genericName: String = "zephyr") : KonanTarget("${genericName}_$subName", Family.ZEPHYR, Architecture.ARM32)

    override fun toString() = name
}

Above list can give idea for implementation for different platforms.

withLoggingContext doesn't work well when called inside coroutines

Spent some time tracking down this logging bug involving withLoggingContext and coroutines and wanted to make sure no one else tripped over it.

I had some code written as such:

withLoggingContext("foo" to "bar") {
            withContext(MDCContext()) { suspending_function() }
}

The problem is that you may be in a different thread when you leave suspending_function as when you entered it, so the MDC.remove call won't have an effect. The wiki example code uses launch, so doesn't have this problem.

My workaround was:

val mdc = MDC.getCopyOfContextMap()?.apply { put("foo", "bar") } ?: mapOf("foo" to "bar")
withContext<T>(MDCContext(mdc)) { suspending_function() }

But I rather have something as nice as withLoggingContext. I'd be happy to submit a patch, but I wanted some direction on the API. Do we use a different function entirely, or should withLoggingContext take a flag where that flags the block as suspending? You could argue that this belongs in the slf4j integration directly and I should ping those guys.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.