Kermit is a Kotlin Multiplatform logging utility with composable log outputs

Overview

Kermit the log

Kermit is a Kotlin Multiplatform logging utility with composable log outputs. The library provides prebuilt loggers for outputting to platform logging tools such as Logcat and NSLog.

Check out KaMP Kit to get started developing for Kotlin Multiplatform

Pre-release

Kermit is in a pre-release stage. We are still working to improve usage and future versions may change the public api.

Design Philosophy

Read more about our api and architecture decisions here: DESIGN

Installation

The Kermit dependency should added to your commonMain source set in your Kotlin Multiplatform module.

commonMain {
    dependencies {
        implementation(kotlin("stdlib-common"))
        api("co.touchlab:kermit:0.1.9")
    }
}

Notice the use of the api configuration. This is to expose Kermit to the native Android & iOS code which includes your shared library. If using an iOS framework (including through CocoaPods) you will also need to transitively export kermit to make it available for use in swift. Learn more under "Exporting dependencies to binaries" Here

framework {
    export("co.touchlab:kermit:0.1.9")
    transitiveExport = true
}

When using cocoapods to package your shared module (we've found this to be the best way right now), you can use Touchlab's cocoapods plugin to configure the framework.

cocoapodsext {
    summary = "Sample for Kermit"
    homepage = "https://www.touchlab.co"
    framework {
        export("co.touchlab:kermit:0.1.9")
        transitiveExport = true
    }
}

Usage

Logging calls are made to a Kermit instance which delegates logging to implementations of the Logger interface which are provided during instantiation. If no Loggers are provided, CommonLogger(which outputs to println) will be used by default.

val kermit = Kermit(LogcatLogger(),CommonLogger(),CustomCrashLogger())
kermit.i("CustomTag", optionalThrowable) { "Message" }

Kermit provides convenience functions for each severity level:

  • v() - Verbose
  • d() - Debug
  • i() - Info
  • w() - Warn
  • e() - Error
  • wtf() - Assert

Each call takes optional parameters for tag and throwable and a function parameter which returns the string to be logged. The message function will only be invoked if there are loggers configured to log that particular message.

Tags

Tags are passed to Logger implementations which can decide how to use them (or ignore them). LogcatLogger passes it along to Logcat's tag field.

Tags can be set for logs in a few different ways:

  • If no tag is specified, a default tag of "Kermit" will be used
  • The default tag can be overridden in the Kermit constructor
  • A copy of Kermit with a new default tag can be obtained with kermit.withTag("newTag"). This is handy for using a tag within a particular scope
  • Each log can specify it's own tag with the optional tag parameter

Loggers

Implementations of the Logger interface are passed into Kermit and determine the destination(s) of each log statement.

Prebuilt Loggers

The Kermit library provides prebuilt loggers for common mobile cases:

  • CommonLogger - Uses println to send logs in Kotlin
  • LogCatLogger - Uses LogCat to send logs in Android
  • NSLogLogger - Uses NSLog to send logs in iOS

These can be created and passed into the Kermit object during initialization

val kermit = Kermit(LogcatLogger(),CommonLogger())

Custom Logger

If you want to customize what happens when a log is received, you can create a customized logger. For a simple Logger you only need to implement the log method, which handles all logs of every Severity.

class NSLogLogger : Logger() {
    override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) {
        NSLog("%s: (%s) %s", severity.name, tag, message)
    }
}

You can optionally override the severity convenience functions if desired.

override fun v(message: String, tag: String, throwable: Throwable?) {
    Log.v(tag, message, throwable)
}

isLoggable

Custom loggers may also override fun isLoggable(severity: Severity): Boolean. Kermit will check this value before logging to this Logger

Sample

Kermit comes with a Sample Multiplatform project which gives a brief example of how it can be used in both Android and iOS. The example demonstrates logs being called from within common code as well as from each platform.

OSLogLogger

The iOS sample also includes a custom logger for outputting using os_log. os_log is not currently available in Kotlin/Native and consequently could not be included as a prebuilt logger in the library, but does serve as a good demonstration of custom logger implementation

Primary Maintainer

Michael Friend

Image of Michael

Comments
  • Kermit 1.2.2: ld: symbol(s) not found for architecture arm64

    Kermit 1.2.2: ld: symbol(s) not found for architecture arm64

    > Task :core:linkDebugFrameworkIosArm64 FAILED
    e: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors
    Please try to disable compiler caches and rerun the build. To disable compiler caches, add the following line to the gradle.properties file in the project's root directory:
        
        kotlin.native.cacheKind.iosArm64=none
        
    Also, consider filing an issue with full Gradle log here: https://kotl.in/issue
    The /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.
    output:
    Undefined symbols for architecture arm64:
      "_OBJC_CLASS_$_FIRCrashlytics", referenced from:
          objc-class-ref in libco.touchlab.crashkios:crashlytics-cache.a(result.o)
      "_OBJC_CLASS_$_FIRExceptionModel", referenced from:
          objc-class-ref in libco.touchlab.crashkios:crashlytics-cache.a(result.o)
      "_OBJC_CLASS_$_FIRStackFrame", referenced from:
          objc-class-ref in libco.touchlab.crashkios:crashlytics-cache.a(result.o)
    ld: symbol(s) not found for architecture arm64
    
    Execution failed for task ':core:linkDebugFrameworkIosArm64'.
    > Compilation finished with errors
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights.
    

    Kermit 1.2.1-alpha works fine.

    Environment: macOS 12.6 Monterey 12.6 Xcode Version 14.1 (14B47b)

    opened by magnumrocha 22
  • 1.1.0 not publishing kotlin-api artifact for platform type common

    1.1.0 not publishing kotlin-api artifact for platform type common

    Unfortunately 1.1.0 doesn't publish a kotlin-api artifact for platform type common which leads to the following error if the consuming project doesn't have a hierarchical project structure:

    Could not determine the dependencies of task ':module:compileKotlinMetadata'.
    > Could not resolve all task dependencies for configuration ':module:metadataCompileClasspath'.
       > Could not resolve co.touchlab:kermit:{require 1.1.0; reject _}.
         Required by:
             project :project
          > The consumer was configured to find a usage of 'kotlin-api' of a library, preferably optimized for non-jvm, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common'. However we cannot choose between the following variants of co.touchlab:kermit:1.1.0:
              - androidNativeArm32ApiElements-published
              - androidNativeArm64ApiElements-published
              - androidNativeX64ApiElements-published
              - androidNativeX86ApiElements-published
              - debugApiElements-published
              - debugRuntimeElements-published
              - iosArm32ApiElements-published
              - iosArm64ApiElements-published
              - iosSimulatorArm64ApiElements-published
              - iosX64ApiElements-published
              - jsIrApiElements-published
              - jsLegacyApiElements-published
              - jvmApiElements-published
              - jvmRuntimeElements-published
              - linuxArm32HfpApiElements-published
              - linuxMips32ApiElements-published
              - linuxX64ApiElements-published
              - macosArm64ApiElements-published
              - macosX64ApiElements-published
              - mingwX64ApiElements-published
              - mingwX86ApiElements-published
              - releaseApiElements-published
              - releaseRuntimeElements-published
              - tvosArm64ApiElements-published
              - tvosSimulatorArm64ApiElements-published
              - tvosX64ApiElements-published
              - watchosArm32ApiElements-published
              - watchosArm64ApiElements-published
              - watchosSimulatorArm64ApiElements-published
              - watchosX64ApiElements-published
              - watchosX86ApiElements-published
              ... more log outout
    

    This is what's missing:

      "variants": [
        {
          "name": "metadataApiElements",
          "attributes": {
            "org.gradle.category": "library",
            "org.gradle.usage": "kotlin-api",
            "org.jetbrains.kotlin.platform.type": "common"
    

    The current artifact only contains:

    "variants": [
        {
          "name": "metadataApiElements",
          "attributes": {
            "org.gradle.category": "library",
            "org.gradle.usage": "kotlin-metadata",
            "org.jetbrains.kotlin.platform.type": "common"
          },
    

    --> kotlin-metadata instead of kotlin-api, hence the error when using it as dependency with other than Android platforms. All you need to do is to set this gradle flag: kotlin.mpp.enableCompatibilityMetadataVariant=true

    See also: https://kotlinlang.org/docs/multiplatform-hierarchy.html#for-library-authors

    opened by 1gravity 21
  • setupUnhandledExceptionHook swallows exceptions

    setupUnhandledExceptionHook swallows exceptions

    Currently, the exception hooks do not propagate exceptions but rather swallows the kotlin exceptions.

    This means that if the handler, set by setupUnhandledExceptionHook is called, the application does not crash. This is problematic because it brings the application in an unexpected state.

    For example if you were to call a function like this from swift, the logger would be called but the application would not crash.

    public fun launchCrashApp() {
      GlobalScope.launch {
        delay(2.seconds)
        throw AssertionError("Here we die.")
      }
    }
    

    As kermit is advertised as:

    Kermit is a Kotlin Multiplatform logging utility

    I recommend to throw the exception from within the library, i.e.

    fun setupUnhandledExceptionHook(logger: Logger, onCrash: () -> String) {
        val unhandMe: ReportUnhandledExceptionHook = { t ->
            logger.e(t, onCrash)
            throw t
        }
    
        setUnhandledExceptionHook(unhandMe.freeze())
    }
    

    If this behavior is actually desired I suggest to rename the functions so they say what they do, i.e. setupSentryExceptionHookAndSwallowAllExceptions(Logger)

    opened by PaulWoitaschek 11
  • Differentiate logs per Severity

    Differentiate logs per Severity

    Android default logger is already giving us ability to set different colors for logs, so no problem there.

    In Xcode unfortunately all logs are same color and if you are logging much stuff then it is hard to differentiate verbose, debug, warning...

    It would be great to have the ability of setting colors for them if not possible then setting colorful icon in the tag like Napier does, please check the link.

    opened by mustafaozhan 9
  • [Question] With version 1.1.0 tag appears as suffix instead of prefix (on iOS)

    [Question] With version 1.1.0 tag appears as suffix instead of prefix (on iOS)

    With Kermit 1.0.0:

    Logger.withTag("my tag")
    logger.d { "some loging" }
    

    output: (my tag) some loging

    With Kermit 1.1.0:

    Logger.withTag("my tag")
    logger.d { "some loging" }
    

    output: (some loging) my tag

    Is it a bug or a configuration?

    opened by GuilhE 7
  • Kermit Koin 1.1.3 is incompatible with Kotlin Test 1.7.0

    Kermit Koin 1.1.3 is incompatible with Kotlin Test 1.7.0

    Gradle is unable to resolve dependencies when kotlin-test:1.7.0 with kermit-koin:1.1.3.

    'co.touchlab:kermit-koin:1.1.3' (debugRuntimeElements-published) --> 'co.touchlab:kermit-koin-android-debug:1.1.3' (debugRuntimeElements-published) --> 'org.jetbrains.kotlin:kotlin-test:1.6.20'
    
    'org.jetbrains.kotlin:kotlin-test:{strictly 1.6.20}' because of the following reason: debugRuntimeClasspath uses version 1.6.20
    
    opened by thipokch 5
  • Kermit Crashlytics or Bugsnag

    Kermit Crashlytics or Bugsnag

    I'm trying to follow the instructions on https://github.com/touchlab/Kermit/pull/177 for integrating Kermit Crashlytics, but my builds now always fail with this error message:

    
    Showing Recent Messages
    > Task :shared:linkDebugFrameworkIos
    
    e: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors
    
    
    
    The /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.
    
    output:
    
    Undefined symbols for architecture arm64:
    
      "_OBJC_CLASS_$_FIRStackFrame", referenced from:
    
          objc-class-ref in result.o
    
      "_OBJC_CLASS_$_FIRExceptionModel", referenced from:
    
          objc-class-ref in result.o
    
      "_OBJC_CLASS_$_FIRCrashlytics", referenced from:
    
          objc-class-ref in result.o
    
    ld: symbol(s) not found for architecture arm64
    
    
    
    > Task :shared:linkDebugFrameworkIos FAILED
    

    Is there anything else I'm missing? I'm using Kermit version "1.0.0-rc4"

    opened by puelocesar 5
  • Build library for js with IR

    Build library for js with IR

    When using this library with a js(IR) target I have this error:

    Could not determine the dependencies of task ':shared:jsPackageJson'.
    > Could not resolve all dependencies for configuration ':shared:jsNpm'.
       > Could not resolve co.touchlab:kermit:0.1.8.
         Required by:
             project :shared
          > No matching variant of co.touchlab:kermit:0.1.8 was found. The consumer was configured to find a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js', attribute 'org.jetbrains.kotlin.js.compiler' with value 'ir'
    

    I suppose you just need to add js(IR) to your targets, but I never developed a multiplatform library so I'm not sure :)

    opened by EmmanueleVilla 5
  • Draft plan for Koin

    Draft plan for Koin "getWithTag" helper

    we want a helper for Koin that makes getting with tags easier. See https://github.com/touchlab/KaMPKit/blob/main/shared/src/commonMain/kotlin/co/touchlab/kampkit/Koin.kt#L68 for a more generic example.

    We're going to have a Koin-specific module in Kermit, so adding this is another thing that's useful and I've added a few times manually. This compiles and does what we want, so let's try this:

    inline fun <reified Logger> Scope.getLoggerWithTag(tag: String): Logger {
        return get(parameters = { parametersOf(tag) })
    }
    
    opened by kpgalligan 4
  • Crash on iOS devices < iOS 13

    Crash on iOS devices < iOS 13

    I happen to be testing my iOS/KMM app on an iOS 12.5.5 device, and there was a crash related to the Kermit code. Here is the call stack:

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSDate now]: unrecognized selector sent to class 0x10bc82898' *** First throw call stack: ( 0 CoreFoundation 0x000000010b9d58db __exceptionPreprocess + 331 1 libobjc.A.dylib 0x000000010af80ac5 objc_exception_throw + 48 2 CoreFoundation 0x000000010b9f3b94 +[NSObject(NSObject) doesNotRecognizeSelector:] + 132 3 CoreFoundation 0x000000010b9da623 ___forwarding___ + 1443 4 CoreFoundation 0x000000010b9dc418 _CF_forwarding_prep_0 + 120 5 SalonBiz 0x0000000108ff6908 kfun:co.touchlab.kermit.XcodeSeverityWriter#formatMessage(co.touchlab.kermit.Severity;kotlin.String;kotlin.String;kotlin.Throwable?){}kotlin.String + 808 6 SalonBiz 0x0000000108ff37e7 kfun:co.touchlab.kermit.CommonWriter#log(co.touchlab.kermit.Severity;kotlin.String;kotlin.String;kotlin.Throwable?){} + 375 7 SalonBiz 0x0000000108ff51d6 kfun:co.touchlab.kermit.Logger#log(co.touchlab.kermit.Severity;kotlin.String;kotlin.Throwable?;kotlin.String){} + 950 8 SalonBiz 0x0000000108ff4dc9 kfun:co.touchlab.kermit.Logger#d(kotlin.String){} + 777

    We see here that NSDate.now is being called, which is an iOS 13+ API. What is odd is that I searched the kermit repo, and there are no explicit calls to this method. So perhaps it is something in the compiler or stdlib?

    I removed kermit from my code for now, but thought I should let others know what I found. Thank you!

    opened by tylerwilson 4
  • Unresolved reference to Logger

    Unresolved reference to Logger

    Hello folks,

    I am trying to use the version 0.3.0-m1 of Kermit, but the AS do not resolve all the methods.

    Gradle version: 7.2 Kotlin version: 1.5.31

    image

    I followed the steps described on the Basic Config.

    opened by francismariano 3
  • Kermit - 1.8 Release Testing

    Kermit - 1.8 Release Testing

    Switch from RC to official release, reverify that 1.8 still works and get the branch ready to merge

    Perform the list of sanity checks on your work projects (it mostly consists of basic actions).

    • Compile your project with a current Kotlin version.
    • Check the highlighting in different IDE modules.
    • Compile the project with the EAP Kotlin version and install the EAP IDE plugin.
    • Verify that the project re-imported successfully.
    • Check that highlighting from p.2 works not worse than before.
    • Compile the project again and look for new surprising warnings.
    • Change something in the code and check if incremental compilation works.
    • Run your tests with a new Kotlin version.
    • Stop at some well-known piece of code, run the debugger and try stepping.
    • Look for performance issues in compilation, runtime, re-import or IDE behavior.

    Pay additional attention to these features and subsystems if applicable to your use case:

    • Kotlin Gradle plugin: lots of changes in all typical usage scenarios
    • The new Gradle Incremental compilation, which we plan to stabilize soon
    • Expose compiler flags via Gradle lazy properties
    • Ability to not fallback with compiler daemon by default
    • arm64 support for watchOS targets
    • Xcode 14 and new Objective-C frameworks support in Kotlin/Native
    opened by KatieGalvin 1
  • Align CrashKios Versions

    Align CrashKios Versions

    We are currently using different versions for crashkios than for crashkios-bugsnag and crashkios-utils. We should bring them to the same version. We need to wait for the latest to be published for each though

    opened by samhill303 0
  • Kermit Evaluate Simplified Sample Set

    Kermit Evaluate Simplified Sample Set

    Some of the samples may be easier to demonstrate through documentation (and be easier to maintain).

    Remove all but one primary sample. For each removed sample, write a doc/tutorial which demonstrates the concept we were demonstrating in the sample.

    The primary sample should be similar to what is currently sample-production except we don't want to include kermit-crashlytics.

    opened by KatieGalvin 1
  • Docs for crashlytics unhandled exception hook are out of date

    Docs for crashlytics unhandled exception hook are out of date

    The docs for iOS reference setting up the exception hook as follows:

    setupCrashlyticsExceptionHook(Logger)
    

    However, it appears on the latest releases, this is no longer the correct call. It now appears to be:

    import co.touchlab.kermit.crashlytics.setCrashlyticsUnhandledExceptionHook
    
    setCrashlyticsUnhandledExceptionHook()
    

    Should be updated: https://github.com/touchlab/Kermit/blob/main/kermit-crashlytics/README.md?plain=1#L42

    opened by rocketraman 0
  • Kermit - 1.8 Beta Testing

    Kermit - 1.8 Beta Testing

    Perform the list of sanity checks on your work projects (it mostly consists of basic actions).

    • Compile your project with a current Kotlin version.
    • Check the highlighting in different IDE modules.
    • Compile the project with the EAP Kotlin version and install the EAP IDE plugin.
    • Verify that the project re-imported successfully.
    • Check that highlighting from p.2 works not worse than before.
    • Compile the project again and look for new surprising warnings.
    • Change something in the code and check if incremental compilation works.
    • Run your tests with a new Kotlin version.
    • Stop at some well-known piece of code, run the debugger and try stepping.
    • Look for performance issues in compilation, runtime, re-import or IDE behavior.

    Pay additional attention to these features and subsystems if applicable to your use case:

    • Kotlin Gradle plugin: lots of changes in all typical usage scenarios
    • The new Gradle Incremental compilation, which we plan to stabilize soon
    • Expose compiler flags via Gradle lazy properties
    • Ability to not fallback with compiler daemon by default
    • arm64 support for watchOS targets
    • Xcode 14 and new Objective-C frameworks support in Kotlin/Native
    opened by KatieGalvin 1
Releases(1.2.2)
A tiny Kotlin API for cheap logging on top of Android's normal Log class.

A tiny Kotlin API for cheap logging on top of Android's normal Log class.

Square 849 Dec 23, 2022
Kotlin multi-platform logging library with structured logging and coroutines support

Klogging Klogging is a pure-Kotlin logging library that aims to be flexible and easy to use. It uses Kotlin idioms for creating loggers and sending lo

Klogging 51 Dec 20, 2022
A logger with a small, extensible API which provides utility on top of Android's normal Log class.

This is a logger with a small, extensible API which provides utility on top of Android's normal Log class. I copy this class into all the little apps

Jake Wharton 9.9k Jan 8, 2023
This is an Kotlin Library that enables Annotation-triggered method call logging for Kotlin Multiplatform.

This is an Kotlin Library that enables Annotation-triggered method call logging for Kotlin Multiplatform.

Jens Klingenberg 187 Dec 18, 2022
simple Kotlin logging: colorized logs for Kotlin on the JVM

sklog - simple Kotlin logging Kotlin (JVM) logging library for printing colorized text to the console, with an easy upgrade path to the popular kotlin

null 1 Jul 26, 2022
Simple application to log your mood through the day and explain feature flags.

Mood Logger App (Android version) This Repo This repository contains code for building a very basic application to log your mood through the days. The

MongoDB Developer Relations 3 Oct 24, 2021
Library that makes debugging, log collection, filtering and analysis easier.

AndroidLogger Android Library that makes debugging, log collection, filtering and analysis easier. Contains 2 modules: Logger: 'com.github.ShiftHackZ.

ShiftHackZ 2 Jul 13, 2022
A demonstration of Kotlin-logging with logback.

try-kotlin-logging A demonstration of Kotlin-logging with logback. Usage # output a log to STDOUT and file(myApp.log) $ ./gradlew run # => 2021-12-11

Hayato Tachikawa 1 Dec 13, 2021
Annotation-triggered method call logging for your debug builds.

Hugo Annotation-triggered method call logging for your debug builds. As a programmer, you often add log statements to print method calls, their argume

Jake Wharton 7.9k Dec 31, 2022
📄The reliable, generic, fast and flexible logging framework for Android

logback-android v2.0.0 Overview logback-android brings the power of logback to Android. This library provides a highly configurable logging framework

Tony Trinh 1.1k Jan 5, 2023
An in-display logging library for Android 📲

Vlog provides an easy and convenient way to access logs right on your phone.

girish budhwani 121 Dec 26, 2022
Jambo is an open source remote logging library

Jambo Jambo is an open source remote logging library. For those who would like to see their logs remotely on their android device Jambo is the library

Tabasumu 6 Aug 26, 2022
Utility logger library for storing logs into database and push them to remote server for debugging

HyperLog Android Overview Log format Download Initialize Usage Get Logs in a File Push Logs Files to Remote Server Sample Testing Endpoint using Reque

HyperTrack 675 Nov 14, 2022
Napier is a logger library for Kotlin Multiplatform.

Napier is a logger library for Kotlin Multiplatform. It supports for the android, ios, jvm, js. Logs written in common module are displayed on logger

Akira Aratani 457 Jan 7, 2023
Kotlin Multi Platform Logger, for android an ios : Logcat & print

Multiplatform Preferences Use a single object : Logger in your kotlin shared projects to display logs Note you can also use it in your real code on An

Florent CHAMPIGNY 49 Aug 22, 2022
Yakl - Yet Another Kotlin Logger

YAKL Yet Another Kotlin Logger. Motivation Current jvm loggers have some disadva

Mark Kosichkin 4 Jan 19, 2022
An easy way to customize your log in Android,including output to console, writing log to file in high performance way and so on

EasyLog An easy way to customize your log in Android,including output to console, writing log to file in high performance way and so on. 1. Initializa

Taylor 40 Dec 8, 2022
A tiny Kotlin API for cheap logging on top of Android's normal Log class.

A tiny Kotlin API for cheap logging on top of Android's normal Log class.

Square 849 Dec 23, 2022
Kotlin multi-platform logging library with structured logging and coroutines support

Klogging Klogging is a pure-Kotlin logging library that aims to be flexible and easy to use. It uses Kotlin idioms for creating loggers and sending lo

Klogging 51 Dec 20, 2022
A logger with a small, extensible API which provides utility on top of Android's normal Log class.

This is a logger with a small, extensible API which provides utility on top of Android's normal Log class. I copy this class into all the little apps

Jake Wharton 9.9k Jan 8, 2023