Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for os_log on Apple platforms #227

Merged
merged 3 commits into from May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
12 changes: 7 additions & 5 deletions src/nativeMain/kotlin/mu/Appender.kt
@@ -1,9 +1,11 @@
package mu

public interface Appender {
public fun trace(message: Any?)
public fun debug(message: Any?)
public fun info(message: Any?)
public fun warn(message: Any?)
public fun error(message: Any?)
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)
public fun warn(loggerName: String, message: String)
public fun error(loggerName: String, message: String)
}
11 changes: 6 additions & 5 deletions src/nativeMain/kotlin/mu/ConsoleOutputAppender.kt
Expand Up @@ -4,12 +4,13 @@ import platform.posix.fprintf
import platform.posix.stderr

public object ConsoleOutputAppender : Appender {
public override fun trace(message: Any?): Unit = println(message)
public override fun debug(message: Any?): Unit = println(message)
public override fun info(message: Any?): Unit = println(message)
public override fun warn(message: Any?): Unit = println(message)
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)
public override fun warn(loggerName: String, message: String): Unit = println(message)

override fun error(message: Any?) {
override fun error(loggerName: String, message: String) {
fprintf(stderr, "$message\n")
}
}
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
9 changes: 5 additions & 4 deletions src/nativeMain/kotlin/mu/Formatter.kt
@@ -1,14 +1,15 @@
package mu

public interface Formatter {
public fun formatMessage(level: KotlinLoggingLevel, loggerName: String, msg: () -> Any?): Any?
public fun formatMessage(level: KotlinLoggingLevel, loggerName: String, t: Throwable?, msg: () -> Any?): Any?
public fun formatMessage(level: KotlinLoggingLevel, loggerName: String, marker: Marker?, msg: () -> Any?): Any?
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?,
t: Throwable?,
msg: () -> Any?
): Any?
): String
}
4 changes: 2 additions & 2 deletions src/nativeMain/kotlin/mu/KMarkerFactory.kt
@@ -1,8 +1,8 @@
package mu

import mu.internal.MarkerLinux
import mu.internal.MarkerNative

public actual object KMarkerFactory {

public actual fun getMarker(name: String): Marker = MarkerLinux(name)
public actual fun getMarker(name: String): Marker = MarkerNative(name)
}
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
16 changes: 8 additions & 8 deletions src/nativeMain/kotlin/mu/internal/KLoggerLinux.kt
Expand Up @@ -57,32 +57,32 @@ internal class KLoggerLinux(
override fun error(marker: Marker?, t: Throwable?, msg: () -> Any?) =
ERROR.logIfEnabled(marker, msg, t, appender::error)

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

private fun KotlinLoggingLevel.logIfEnabled(msg: () -> Any?, t: Throwable?, logFunction: (Any?) -> Unit) {
private fun KotlinLoggingLevel.logIfEnabled(msg: () -> Any?, t: Throwable?, logFunction: (String, String) -> Unit) {
if (isLoggingEnabled()) {
logFunction(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: (Any?) -> Unit) {
private fun KotlinLoggingLevel.logIfEnabled(marker: Marker?, msg: () -> Any?, logFunction: (String, String) -> Unit) {
if (isLoggingEnabled()) {
logFunction(formatter.formatMessage(this, loggerName, marker, msg))
logFunction(loggerName, formatter.formatMessage(appender.includePrefix, this, loggerName, marker, msg))
}
}

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

Expand Down
Expand Up @@ -2,7 +2,7 @@ package mu.internal

import mu.Marker

internal class MarkerLinux(private val name: String) : Marker {
internal class MarkerNative(private val name: String) : Marker {

override fun getName(): String = this.name
}