Skip to content

Commit

Permalink
Add OSLogAppender to append logs to os_log on Darwin platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
conradev authored and oshai committed May 20, 2022
1 parent 2ea0674 commit f089853
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 22 deletions.
36 changes: 29 additions & 7 deletions build.gradle.kts
Expand Up @@ -51,9 +51,24 @@ kotlin {
nodejs()
}

linuxX64("linuxX64")
macosX64("macosX64")
mingwX64("mingwX64")
val linuxTargets = listOf(
linuxArm64(),
linuxX64(),
mingwX64()
)
val darwinTargets = listOf(
macosArm64(),
macosX64(),
iosArm64(),
iosSimulatorArm64(),
iosX64(),
watchosArm64(),
watchosSimulatorArm64(),
watchosX64(),
tvosArm64(),
tvosSimulatorArm64(),
tvosX64()
)

sourceSets {
val commonMain by getting {}
Expand Down Expand Up @@ -88,14 +103,21 @@ kotlin {
val nativeMain by creating {
dependsOn(commonMain)
}
val linuxX64Main by getting {
val linuxMain by creating {
dependsOn(nativeMain)
}
val mingwX64Main by getting {
val darwinMain by creating {
dependsOn(nativeMain)
}
val macosX64Main by getting {
dependsOn(nativeMain)
linuxTargets.forEach {
getByName("${it.targetName}Main") {
dependsOn(linuxMain)
}
}
darwinTargets.forEach {
getByName("${it.targetName}Main") {
dependsOn(darwinMain)
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/darwinMain/kotlin/mu/KotlinLoggingConfiguration.kt
@@ -0,0 +1,3 @@
package mu

public actual val DefaultAppender: Appender = OSLogAppender()
49 changes: 49 additions & 0 deletions src/darwinMain/kotlin/mu/OSLogAppender.kt
@@ -0,0 +1,49 @@
package mu

import kotlinx.cinterop.ptr
import platform.darwin.OS_LOG_DEFAULT
import platform.darwin.OS_LOG_TYPE_DEBUG
import platform.darwin.OS_LOG_TYPE_DEFAULT
import platform.darwin.OS_LOG_TYPE_ERROR
import platform.darwin.OS_LOG_TYPE_INFO
import platform.darwin.__dso_handle
import platform.darwin._os_log_internal
import platform.darwin.os_log_t
import platform.darwin.os_log_type_enabled
import platform.darwin.os_log_type_t
import kotlin.native.concurrent.AtomicReference

public open class OSLogAppender: Appender {
override val includePrefix: Boolean = true

protected open fun logger(loggerName: String): os_log_t {
return OS_LOG_DEFAULT
}

private fun log(level: os_log_type_t, loggerName: String, message: String) {
val logger = logger(loggerName)
if (os_log_type_enabled(logger, level)) {
_os_log_internal(__dso_handle.ptr, logger, level, message)
}
}

override fun trace(loggerName: String, message: String) {
log(OS_LOG_TYPE_DEBUG, loggerName, message)
}

override fun debug(loggerName: String, message: String) {
log(OS_LOG_TYPE_DEBUG, loggerName, message)
}

override fun info(loggerName: String, message: String) {
log(OS_LOG_TYPE_INFO, loggerName, message)
}

override fun warn(loggerName: String, message: String) {
log(OS_LOG_TYPE_DEFAULT, loggerName, message)
}

override fun error(loggerName: String, message: String) {
log(OS_LOG_TYPE_ERROR, loggerName, message)
}
}
28 changes: 28 additions & 0 deletions src/darwinMain/kotlin/mu/OSLogSubsystemAppender.kt
@@ -0,0 +1,28 @@
package mu

import platform.darwin.os_log_create
import platform.darwin.os_log_t
import kotlin.native.concurrent.AtomicReference

public class OSLogSubsystemAppender(public val subsystem: String) : OSLogAppender() {
override val includePrefix: Boolean = false

private val logs: AtomicReference<Map<String, os_log_t>> = AtomicReference(mapOf())

override fun logger(loggerName: String): os_log_t {
var logger: os_log_t
do {
val existing = logs.value
logger = existing[loggerName]
if (logger != null) {
return logger
}

val updated = existing.toMutableMap()
logger = os_log_create(subsystem, loggerName)
updated[loggerName] = logger
} while (!logs.compareAndSet(existing, updated))

return logger
}
}
3 changes: 3 additions & 0 deletions src/linuxMain/kotlin/mu/KotlinLoggingConfiguration.kt
@@ -0,0 +1,3 @@
package mu

public actual val DefaultAppender: Appender = ConsoleOutputAppender
2 changes: 2 additions & 0 deletions src/nativeMain/kotlin/mu/Appender.kt
@@ -1,6 +1,8 @@
package mu

public interface Appender {
public val includePrefix: Boolean

public fun trace(loggerName: String, message: String)
public fun debug(loggerName: String, message: String)
public fun info(loggerName: String, message: String)
Expand Down
1 change: 1 addition & 0 deletions src/nativeMain/kotlin/mu/ConsoleOutputAppender.kt
Expand Up @@ -4,6 +4,7 @@ import platform.posix.fprintf
import platform.posix.stderr

public object ConsoleOutputAppender : Appender {
override val includePrefix: Boolean = true
public override fun trace(loggerName: String, message: String): Unit = println(message)
public override fun debug(loggerName: String, message: String): Unit = println(message)
public override fun info(loggerName: String, message: String): Unit = println(message)
Expand Down
23 changes: 16 additions & 7 deletions src/nativeMain/kotlin/mu/DefaultMessageFormatter.kt
Expand Up @@ -3,23 +3,32 @@ package mu
import mu.internal.toStringSafe

public object DefaultMessageFormatter : Formatter {
public override fun formatMessage(level: KotlinLoggingLevel, loggerName: String, msg: () -> Any?): String =
"${level.name}: [$loggerName] ${msg.toStringSafe()}"
public override fun formatMessage(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String, msg: () -> Any?): String =
"${prefix(includePrefix, level, loggerName)}${msg.toStringSafe()}"

public override fun formatMessage(level: KotlinLoggingLevel, loggerName: String, t: Throwable?, msg: () -> Any?): String =
"${level.name}: [$loggerName] ${msg.toStringSafe()}${t.throwableToString()}"
public override fun formatMessage(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String, t: Throwable?, msg: () -> Any?): String =
"${prefix(includePrefix, level, loggerName)}${msg.toStringSafe()}${t.throwableToString()}"

public override fun formatMessage(level: KotlinLoggingLevel, loggerName: String, marker: Marker?, msg: () -> Any?): String =
"${level.name}: [$loggerName] ${marker?.getName()} ${msg.toStringSafe()}"
public override fun formatMessage(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String, marker: Marker?, msg: () -> Any?): String =
"${prefix(includePrefix, level, loggerName)}${marker?.getName()} ${msg.toStringSafe()}"

public override fun formatMessage(
includePrefix: Boolean,
level: KotlinLoggingLevel,
loggerName: String,
marker: Marker?,
t: Throwable?,
msg: () -> Any?
): String =
"${level.name}: [$loggerName] ${marker?.getName()} ${msg.toStringSafe()}${t.throwableToString()}"
"${prefix(includePrefix, level, loggerName)}${marker?.getName()} ${msg.toStringSafe()}${t.throwableToString()}"

private fun prefix(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String): String {
return if (includePrefix) {
"${level.name}: [$loggerName] "
} else {
""
}
}

private fun Throwable?.throwableToString(): String {
if (this == null) {
Expand Down
7 changes: 4 additions & 3 deletions src/nativeMain/kotlin/mu/Formatter.kt
@@ -1,10 +1,11 @@
package mu

public interface Formatter {
public fun formatMessage(level: KotlinLoggingLevel, loggerName: String, msg: () -> Any?): String
public fun formatMessage(level: KotlinLoggingLevel, loggerName: String, t: Throwable?, msg: () -> Any?): String
public fun formatMessage(level: KotlinLoggingLevel, loggerName: String, marker: Marker?, msg: () -> Any?): String
public fun formatMessage(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String, msg: () -> Any?): String
public fun formatMessage(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String, t: Throwable?, msg: () -> Any?): String
public fun formatMessage(includePrefix: Boolean, level: KotlinLoggingLevel, loggerName: String, marker: Marker?, msg: () -> Any?): String
public fun formatMessage(
includePrefix: Boolean,
level: KotlinLoggingLevel,
loggerName: String,
marker: Marker?,
Expand Down
4 changes: 3 additions & 1 deletion src/nativeMain/kotlin/mu/KotlinLoggingConfiguration.kt
Expand Up @@ -2,6 +2,8 @@ package mu

import kotlin.native.concurrent.AtomicReference

public expect val DefaultAppender: Appender

@Suppress("ObjectPropertyName")
public object KotlinLoggingConfiguration {
private val _logLevel = AtomicReference(KotlinLoggingLevel.INFO)
Expand All @@ -10,7 +12,7 @@ public object KotlinLoggingConfiguration {
set(value) {
_logLevel.value = value
}
private val _appender = AtomicReference<Appender>(ConsoleOutputAppender)
private val _appender = AtomicReference<Appender>(DefaultAppender)
public var appender: Appender
get() = _appender.value
set(value) {
Expand Down
8 changes: 4 additions & 4 deletions src/nativeMain/kotlin/mu/internal/KLoggerLinux.kt
Expand Up @@ -59,19 +59,19 @@ internal class KLoggerLinux(

private fun KotlinLoggingLevel.logIfEnabled(msg: () -> Any?, logFunction: (String, String) -> Unit) {
if (isLoggingEnabled()) {
logFunction(loggerName, formatter.formatMessage(this, loggerName, msg))
logFunction(loggerName, formatter.formatMessage(appender.includePrefix, this, loggerName, msg))
}
}

private fun KotlinLoggingLevel.logIfEnabled(msg: () -> Any?, t: Throwable?, logFunction: (String, String) -> Unit) {
if (isLoggingEnabled()) {
logFunction(loggerName, formatter.formatMessage(this, loggerName, t, msg))
logFunction(loggerName, formatter.formatMessage(appender.includePrefix, this, loggerName, t, msg))
}
}

private fun KotlinLoggingLevel.logIfEnabled(marker: Marker?, msg: () -> Any?, logFunction: (String, String) -> Unit) {
if (isLoggingEnabled()) {
logFunction(loggerName, formatter.formatMessage(this, loggerName, marker, msg))
logFunction(loggerName, formatter.formatMessage(appender.includePrefix, this, loggerName, marker, msg))
}
}

Expand All @@ -82,7 +82,7 @@ internal class KLoggerLinux(
logFunction: (String, String) -> Unit
) {
if (isLoggingEnabled()) {
logFunction(loggerName, formatter.formatMessage(this, loggerName, marker, t, msg))
logFunction(loggerName, formatter.formatMessage(appender.includePrefix, this, loggerName, marker, t, msg))
}
}

Expand Down

0 comments on commit f089853

Please sign in to comment.