
Lightweight and extensible logging library with a familiar API, supporting multiple log levels, tagged and scoped logging, and customizable output destinations. Features thread-safe and multiplatform capabilities.
Multiplatform Timber-like lightweight and extensible logging library for Kotlin Multiplatform projects. Plant different trees to log to various destinations with beautiful formatting and powerful filtering.
π Familiar API: If you've used Timber before, you'll feel right at home! Cedar Logger uses the same intuitive API but extends it to support Kotlin Multiplatform, making migration simple and straightforward.
dependencies {
implementation("org.kimplify:cedar-logging:0.2.0")
}// In your iOS app's build.gradle.kts
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { target ->
target.binaries.framework {
export("org.kimplify:cedar-logging:0.2.0")
baseName = "YourApp"
isStatic = true
}
}
// In commonMain dependencies
api("org.kimplify:cedar-logging:0.2.0")# In your Podfile
pod 'CedarLogger', :git => 'https://github.com/ChiliNoodles/Cedar-Logger.git', :tag => 'v0.2.0'// Plant a tree
Cedar.plant(ConsoleTree())
// Log messages
Cedar.v("Verbose message")
Cedar.d("Debug message")
Cedar.i("Info message")
Cedar.w("Warning message")
Cedar.e("Error message")
// Tagged logging
Cedar.tag("Network").i("API call successful")
Cedar.tag("Database").d("Query executed")
// Scoped logging with timing
Cedar.tag("Performance").scope("Loading data").use {
// Your operation here - automatically logs start/end and duration
}Beautiful console output with icons and colors.
Cedar.plant(ConsoleTree().withMinPriority(LogPriority.DEBUG))Output: π DEBUG [Network] API call completed successfully
Uses platform-specific logging APIs for optimal performance. Supports platform-specific configuration for advanced features.
Cedar.plant(PlatformLogTree())Cedar.plant(PlatformLogTree().configureForPlatform {
iosSubsystem = "com.myapp.network"
iosCategory = "API"
androidMaxLogLength = 2000
jvmLoggerName = "MyApp.Logger"
enableEmojis = true
})Platform-Specific Features:
π± iOS/Swift Usage: Cedar Logger can be used directly in Swift code via framework export. See iOS/Swift Usage Guide for detailed examples.
Creating your own logging destinations is simple. Here are practical examples for popular services:
import io.sentry.Sentry
import io.sentry.SentryLevel
import com.chilinoodles.cedar.logging.LogTree
import com.chilinoodles.cedar.logging.LogPriority
class SentryTree : LogTree {
override fun log(priority: LogPriority, tag: String, message: String, throwable: Throwable?) {
val sentryLevel = when (priority) {
LogPriority.VERBOSE, LogPriority.DEBUG -> SentryLevel.DEBUG
LogPriority.INFO -> SentryLevel.INFO
LogPriority.WARNING -> SentryLevel.WARNING
LogPriority.ERROR -> SentryLevel.ERROR
}
Sentry.configureScope { scope ->
scope.setTag("logger_tag", tag)
scope.setLevel(sentryLevel)
}
when {
throwable != null -> Sentry.captureException(throwable)
priority >= LogPriority.ERROR -> Sentry.captureMessage(message, sentryLevel)
else -> Sentry.addBreadcrumb(message)
}
}
}
// Usage
Cedar.plant(SentryTree())
Cedar.tag("Payment").e("Credit card processing failed", exception)import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.chilinoodles.cedar.logging.LogTree
import com.chilinoodles.cedar.logging.LogPriority
class CrashlyticsTree : LogTree {
private val crashlytics = FirebaseCrashlytics.getInstance()
override fun log(priority: LogPriority, tag: String, message: String, throwable: Throwable?) {
crashlytics.setCustomKey("last_log_tag", tag)
crashlytics.setCustomKey("last_log_priority", priority.name)
val logMessage = "[$tag] $message"
when {
throwable != null -> {
crashlytics.log(logMessage)
crashlytics.recordException(throwable)
}
priority >= LogPriority.WARNING -> {
crashlytics.log(logMessage)
if (priority == LogPriority.ERROR) {
crashlytics.recordException(RuntimeException(message))
}
}
else -> crashlytics.log(logMessage)
}
}
}
// Usage
Cedar.plant(CrashlyticsTree())
Cedar.tag("Auth").e("Login failed", authException)The project includes a beautiful sample app demonstrating all features:
./gradlew :sample:runCedar.plant(ConsoleTree())
Cedar.plant(SentryTree())
Cedar.plant(CrashlyticsTree())
// All trees receive the same logs// Check planted trees
println("Trees: ${Cedar.treeCount}")
// Remove all trees
Cedar.clearForest()
// Remove specific tree
val sentryTree = SentryTree()
Cedar.plant(sentryTree)
Cedar.uproot(sentryTree)try {
riskyOperation()
} catch (e: Exception) {
Cedar.tag("CriticalError").e(e, "Operation failed")
// Logged to all planted trees
}| Method | Description |
|---|---|
Cedar.plant(tree) |
Add logging tree |
Cedar.tag(name) |
Create tagged logger |
Cedar.v/d/i/w/e() |
Log messages |
Cedar.clearForest() |
Remove all trees |
Cedar.uproot(tree) |
Remove specific tree |
Cedar.treeCount |
Get planted tree count |
Cedar Logger is published to Maven Central and ready for production use:
// Kotlin Multiplatform
implementation("org.kimplify:cedar-logging:0.2.0")
// Android only
implementation("org.kimplify:cedar-logging-android:0.2.0")
// JVM only
implementation("org.kimplify:cedar-logging-jvm:0.2.0")CedarLogger
This project is licensed under the Apache License, Version 2.0.
Made with β€οΈ for the Kotlin Multiplatform community
Multiplatform Timber-like lightweight and extensible logging library for Kotlin Multiplatform projects. Plant different trees to log to various destinations with beautiful formatting and powerful filtering.
π Familiar API: If you've used Timber before, you'll feel right at home! Cedar Logger uses the same intuitive API but extends it to support Kotlin Multiplatform, making migration simple and straightforward.
dependencies {
implementation("org.kimplify:cedar-logging:0.2.0")
}// In your iOS app's build.gradle.kts
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { target ->
target.binaries.framework {
export("org.kimplify:cedar-logging:0.2.0")
baseName = "YourApp"
isStatic = true
}
}
// In commonMain dependencies
api("org.kimplify:cedar-logging:0.2.0")# In your Podfile
pod 'CedarLogger', :git => 'https://github.com/ChiliNoodles/Cedar-Logger.git', :tag => 'v0.2.0'// Plant a tree
Cedar.plant(ConsoleTree())
// Log messages
Cedar.v("Verbose message")
Cedar.d("Debug message")
Cedar.i("Info message")
Cedar.w("Warning message")
Cedar.e("Error message")
// Tagged logging
Cedar.tag("Network").i("API call successful")
Cedar.tag("Database").d("Query executed")
// Scoped logging with timing
Cedar.tag("Performance").scope("Loading data").use {
// Your operation here - automatically logs start/end and duration
}Beautiful console output with icons and colors.
Cedar.plant(ConsoleTree().withMinPriority(LogPriority.DEBUG))Output: π DEBUG [Network] API call completed successfully
Uses platform-specific logging APIs for optimal performance. Supports platform-specific configuration for advanced features.
Cedar.plant(PlatformLogTree())Cedar.plant(PlatformLogTree().configureForPlatform {
iosSubsystem = "com.myapp.network"
iosCategory = "API"
androidMaxLogLength = 2000
jvmLoggerName = "MyApp.Logger"
enableEmojis = true
})Platform-Specific Features:
π± iOS/Swift Usage: Cedar Logger can be used directly in Swift code via framework export. See iOS/Swift Usage Guide for detailed examples.
Creating your own logging destinations is simple. Here are practical examples for popular services:
import io.sentry.Sentry
import io.sentry.SentryLevel
import com.chilinoodles.cedar.logging.LogTree
import com.chilinoodles.cedar.logging.LogPriority
class SentryTree : LogTree {
override fun log(priority: LogPriority, tag: String, message: String, throwable: Throwable?) {
val sentryLevel = when (priority) {
LogPriority.VERBOSE, LogPriority.DEBUG -> SentryLevel.DEBUG
LogPriority.INFO -> SentryLevel.INFO
LogPriority.WARNING -> SentryLevel.WARNING
LogPriority.ERROR -> SentryLevel.ERROR
}
Sentry.configureScope { scope ->
scope.setTag("logger_tag", tag)
scope.setLevel(sentryLevel)
}
when {
throwable != null -> Sentry.captureException(throwable)
priority >= LogPriority.ERROR -> Sentry.captureMessage(message, sentryLevel)
else -> Sentry.addBreadcrumb(message)
}
}
}
// Usage
Cedar.plant(SentryTree())
Cedar.tag("Payment").e("Credit card processing failed", exception)import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.chilinoodles.cedar.logging.LogTree
import com.chilinoodles.cedar.logging.LogPriority
class CrashlyticsTree : LogTree {
private val crashlytics = FirebaseCrashlytics.getInstance()
override fun log(priority: LogPriority, tag: String, message: String, throwable: Throwable?) {
crashlytics.setCustomKey("last_log_tag", tag)
crashlytics.setCustomKey("last_log_priority", priority.name)
val logMessage = "[$tag] $message"
when {
throwable != null -> {
crashlytics.log(logMessage)
crashlytics.recordException(throwable)
}
priority >= LogPriority.WARNING -> {
crashlytics.log(logMessage)
if (priority == LogPriority.ERROR) {
crashlytics.recordException(RuntimeException(message))
}
}
else -> crashlytics.log(logMessage)
}
}
}
// Usage
Cedar.plant(CrashlyticsTree())
Cedar.tag("Auth").e("Login failed", authException)The project includes a beautiful sample app demonstrating all features:
./gradlew :sample:runCedar.plant(ConsoleTree())
Cedar.plant(SentryTree())
Cedar.plant(CrashlyticsTree())
// All trees receive the same logs// Check planted trees
println("Trees: ${Cedar.treeCount}")
// Remove all trees
Cedar.clearForest()
// Remove specific tree
val sentryTree = SentryTree()
Cedar.plant(sentryTree)
Cedar.uproot(sentryTree)try {
riskyOperation()
} catch (e: Exception) {
Cedar.tag("CriticalError").e(e, "Operation failed")
// Logged to all planted trees
}| Method | Description |
|---|---|
Cedar.plant(tree) |
Add logging tree |
Cedar.tag(name) |
Create tagged logger |
Cedar.v/d/i/w/e() |
Log messages |
Cedar.clearForest() |
Remove all trees |
Cedar.uproot(tree) |
Remove specific tree |
Cedar.treeCount |
Get planted tree count |
Cedar Logger is published to Maven Central and ready for production use:
// Kotlin Multiplatform
implementation("org.kimplify:cedar-logging:0.2.0")
// Android only
implementation("org.kimplify:cedar-logging-android:0.2.0")
// JVM only
implementation("org.kimplify:cedar-logging-jvm:0.2.0")CedarLogger
This project is licensed under the Apache License, Version 2.0.
Made with β€οΈ for the Kotlin Multiplatform community