diff --git a/build.gradle.kts b/build.gradle.kts index 5df8770..94f6ac4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,5 +4,5 @@ plugins { allprojects { group = "org.kodein.log" - version = "0.19.0" + version = "1.0.0" } \ No newline at end of file diff --git a/canard/build.gradle.kts b/canard/build.gradle.kts index 5ea62e1..9238b12 100644 --- a/canard/build.gradle.kts +++ b/canard/build.gradle.kts @@ -3,37 +3,11 @@ plugins { } kotlin.kodein { - jsEnv() + all() -// all() TODO kotlinx-datetime does not support WASM - - val commonMain by common.main -// val datetimeMain by sourceSets.creating { -// dependsOn(common.main) -// dependencies { -// api(libs.kotlinx.datetime) -// } -// } - val datetimeMain by kotlin.sourceSets.creating { - dependsOn(commonMain) - dependencies { - api(libs.kotlinx.datetime) - } - } - -// add(kodeinTargets.jvm.jvm) { -// main.dependsOn(datetimeMain) -// target.setCompileClasspath() -// main.dependencies { -// implementation(libs.slf4j.api) -// compileOnly(rootProject.files("libs/android-log.jar")) -// } -// } -// } jvm { target.setCompileClasspath() sources.main { - dependsOn(datetimeMain) dependencies { implementation(libs.slf4j.api) compileOnly(rootProject.files("libs/android-log.jar")) @@ -41,94 +15,28 @@ kotlin.kodein { } } -// add(kodeinTargets.js.js) { -// main.dependsOn(datetimeMain) -// configure(listOf(mainCompilation, testCompilation)) { -// kotlinOptions { -// sourceMap = true -// sourceMapEmbedSources = "always" -// } -// } -// } - js { - sources.main { dependsOn(datetimeMain) } - compilations.configureEach { - kotlinOptions { - sourceMap = true - sourceMapEmbedSources = "always" - } + allApple { + compilations.main { + cinterops.create("darwin_log") } - } - - val allNativeMain by kotlin.sourceSets.creating { - dependsOn(commonMain) - } -// val defaultNativeMain by sourceSets.creating { -// dependsOn(common.main) -// } - val defaultNativeMain by kotlin.sourceSets.creating { - dependsOn(allNativeMain) - } - -// add(kodeinTargets.native.allDesktop) { -// main { -// dependsOn(defaultNativeMain) -// dependsOn(datetimeMain) -// } -// } - allDesktop { sources.main { - dependsOn(defaultNativeMain) - dependsOn(datetimeMain) + languageSettings { + optIn("kotlinx.cinterop.ExperimentalForeignApi") + } } } -// val embeddedNativeMain by sourceSets.creating { -// dependsOn(common.main) -// } - val embeddedNativeMain by kotlin.sourceSets.creating { - dependsOn(allNativeMain) + val nativeMain by kotlin.sourceSets.getting + val defaultNativeMain by kotlin.sourceSets.creating { + dependsOn(nativeMain) } -// add(kodeinTargets.native.allEmbeddedLinux) { -// main { -// dependsOn(defaultNativeMain) -// dependsOn(embeddedNativeMain) -// } -// } - linuxArm64 { + addAll(targets.allNative - targets.allApple) { sources.main { dependsOn(defaultNativeMain) - dependsOn(embeddedNativeMain) } } -// add(kodeinTargets.native.allDarwin) { -// main.dependsOn(datetimeMain) -// mainCompilation.cinterops.create("darwin_log") -// } - val allAppleMobileMain by kotlin.sourceSets.creating { - dependsOn(allNativeMain) - } - // TODO watchosDeviceArm64 is not supported by KotlinX DateTime - addAll(targets.allAppleMobile - targets.watchosDeviceArm64) { - sources.main { - dependsOn(allAppleMobileMain) - dependsOn(datetimeMain) - languageSettings { - optIn("kotlinx.cinterop.ExperimentalForeignApi") - } - } - compilations.main { - cinterops.create("darwin_log") - } - } -} - -kotlin.sourceSets.all { - languageSettings { - optIn("kotlin.RequiresOptIn") - } } kodeinUpload { diff --git a/canard/src/allAppleMobileMain/kotlin/org/kodein/log/frontend/darwinFrontend.kt b/canard/src/appleMain/kotlin/org/kodein/log/frontend/darwinFrontend.kt similarity index 100% rename from canard/src/allAppleMobileMain/kotlin/org/kodein/log/frontend/darwinFrontend.kt rename to canard/src/appleMain/kotlin/org/kodein/log/frontend/darwinFrontend.kt diff --git a/canard/src/allAppleMobileMain/kotlin/org/kodein/log/frontend/defaultDarwin.kt b/canard/src/appleMain/kotlin/org/kodein/log/frontend/defaultDarwin.kt similarity index 100% rename from canard/src/allAppleMobileMain/kotlin/org/kodein/log/frontend/defaultDarwin.kt rename to canard/src/appleMain/kotlin/org/kodein/log/frontend/defaultDarwin.kt diff --git a/canard/src/commonMain/kotlin/org/kodein/log/Logger.kt b/canard/src/commonMain/kotlin/org/kodein/log/Logger.kt index 36eea01..1f30dbb 100644 --- a/canard/src/commonMain/kotlin/org/kodein/log/Logger.kt +++ b/canard/src/commonMain/kotlin/org/kodein/log/Logger.kt @@ -58,7 +58,6 @@ private val defaultFrontEnds by lazy { listOf(defaultLogFrontend) } -@Suppress("NOTHING_TO_INLINE") /** * Logger */ @@ -87,7 +86,7 @@ public class Logger( /** * Metadata that helps describe log messages */ - public data class Entry(val level: Level, val ex: Throwable? = null, val meta: Map = emptyMap(), val instant: Instant = now()) + public data class Entry(val level: Level, val ex: Throwable? = null, val meta: Map = emptyMap(), val timestamp: Timestamp = now()) @PublishedApi internal fun createEntry(level: Level, error: Throwable? = null, meta: Map): Entry? = @@ -123,6 +122,7 @@ public class Logger( /** * Log an exception with [WARNING] severity */ + @Suppress("NOTHING_TO_INLINE") public inline fun warning(ex: Throwable) { log(level = WARNING, error = ex) } /** @@ -132,6 +132,7 @@ public class Logger( /** * Log an exception with [ERROR] severity */ + @Suppress("NOTHING_TO_INLINE") public inline fun error(ex: Throwable) { log(level = ERROR, error = ex) } public companion object { diff --git a/canard/src/commonMain/kotlin/org/kodein/log/frontend/PrintFrontend.kt b/canard/src/commonMain/kotlin/org/kodein/log/frontend/PrintFrontend.kt index f7625ca..be79b2a 100644 --- a/canard/src/commonMain/kotlin/org/kodein/log/frontend/PrintFrontend.kt +++ b/canard/src/commonMain/kotlin/org/kodein/log/frontend/PrintFrontend.kt @@ -7,7 +7,7 @@ import org.kodein.log.toLocalString public fun printLogIn(tag: Logger.Tag, entry: Logger.Entry, msg: String?, printer: (String) -> Unit) { - val prefix = " ".repeat(7 - entry.level.name.length) + "${entry.level.name}: ${entry.instant.toLocalString()} |" + val prefix = " ".repeat(7 - entry.level.name.length) + "${entry.level.name}: ${entry.timestamp.toLocalString()} |" val indent = " ".repeat(prefix.length) if (msg != null) { msg.lines().forEachIndexed { i, l -> diff --git a/canard/src/commonMain/kotlin/org/kodein/log/instant.kt b/canard/src/commonMain/kotlin/org/kodein/log/instant.kt deleted file mode 100644 index 2cf64c7..0000000 --- a/canard/src/commonMain/kotlin/org/kodein/log/instant.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.kodein.log - -public expect class Instant - -public expect fun now(): Instant - -public expect fun Instant.toLocalString(): String diff --git a/canard/src/commonMain/kotlin/org/kodein/log/timestamp.kt b/canard/src/commonMain/kotlin/org/kodein/log/timestamp.kt new file mode 100644 index 0000000..9d1446b --- /dev/null +++ b/canard/src/commonMain/kotlin/org/kodein/log/timestamp.kt @@ -0,0 +1,10 @@ +package org.kodein.log + +import kotlin.jvm.JvmInline + +@JvmInline +public value class Timestamp(public val msecSinceEpoch: ULong) + +public expect fun now(): Timestamp + +public expect fun Timestamp.toLocalString(): String diff --git a/canard/src/commonTest/kotlin/org/kodein/log/TestFrontend.kt b/canard/src/commonTest/kotlin/org/kodein/log/TestFrontend.kt index 4926056..cc98bd8 100644 --- a/canard/src/commonTest/kotlin/org/kodein/log/TestFrontend.kt +++ b/canard/src/commonTest/kotlin/org/kodein/log/TestFrontend.kt @@ -2,15 +2,15 @@ package org.kodein.log class TestFrontend : LogFrontend { - private val instant = now() + private val timestamp = now() val entries: MutableList> = ArrayList() override fun getReceiverFor(tag: Logger.Tag): LogReceiver = LogReceiver { entry, message -> - entries += Triple(tag, entry.copy(instant = instant), message) + entries += Triple(tag, entry.copy(timestamp = timestamp), message) } fun testEntry(level: Logger.Level, ex: Throwable? = null, meta: Map = emptyMap()): Logger.Entry = - Logger.Entry(level, ex, meta, instant) + Logger.Entry(level, ex, meta, timestamp) } diff --git a/canard/src/datetimeMain/kotlin/org/kodein/log/instantDateTime.kt b/canard/src/datetimeMain/kotlin/org/kodein/log/instantDateTime.kt deleted file mode 100644 index ad56a24..0000000 --- a/canard/src/datetimeMain/kotlin/org/kodein/log/instantDateTime.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.kodein.log - -import kotlinx.datetime.TimeZone -import kotlinx.datetime.toLocalDateTime - - -public actual typealias Instant = kotlinx.datetime.Instant - -public actual fun now(): Instant = kotlinx.datetime.Clock.System.now() - -public actual fun Instant.toLocalString(): String = toLocalDateTime(TimeZone.currentSystemDefault()).toString() diff --git a/canard/src/embeddedNativeMain/kotlin/org/kodein/log/instantEmbedded.kt b/canard/src/embeddedNativeMain/kotlin/org/kodein/log/instantEmbedded.kt deleted file mode 100644 index bf259fa..0000000 --- a/canard/src/embeddedNativeMain/kotlin/org/kodein/log/instantEmbedded.kt +++ /dev/null @@ -1,31 +0,0 @@ -@file:OptIn(ExperimentalForeignApi::class) - -package org.kodein.log - -import kotlinx.cinterop.* -import platform.posix.* - - -public actual class Instant(public val tv_sec: time_t, public val tv_nsec: Long) - -public actual fun now(): Instant { - memScoped { - val spec = alloc() - clock_gettime(CLOCK_REALTIME, spec.ptr) - return Instant(spec.tv_sec, spec.tv_nsec.convert()) - } -} - -public actual fun Instant.toLocalString(): String { - memScoped { - val ms = tv_nsec / 1_000_000L - val sec = alloc() - sec.value = tv_sec - val info = localtime(sec.ptr) - - val chars = allocArray(32) - strftime(chars, 31.convert(), "%Y-%m-%dT%H:%M:%S", info) - - return chars.toKString() + "." + ms.toString().padStart(3, '0') - } -} diff --git a/canard/src/jsMain/kotlin/org/kodein/log/timestampJs.kt b/canard/src/jsMain/kotlin/org/kodein/log/timestampJs.kt new file mode 100644 index 0000000..522aeca --- /dev/null +++ b/canard/src/jsMain/kotlin/org/kodein/log/timestampJs.kt @@ -0,0 +1,19 @@ +package org.kodein.log + +import kotlin.js.Date + + +public actual fun now(): Timestamp = Timestamp(Date.now().toULong()) + +@Suppress("LocalVariableName") +public actual fun Timestamp.toLocalString(): String = Date(msecSinceEpoch.toDouble()).let { + val Y = it.getFullYear().toString() + val M = it.getMonth().inc().toString().padStart(2, '0') + val D = it.getDate().toString().padStart(2, '0') + val h = it.getHours().toString().padStart(2, '0') + val m = it.getMinutes().toString().padStart(2, '0') + val s = it.getSeconds().toString().padStart(2, '0') + val ss = it.getMilliseconds().toString().padStart(3, '0') + + "$Y/$M/$D $h:$m:$s:$ss" +} diff --git a/canard/src/jvmMain/kotlin/org/kodein/log/timestampJvm.kt b/canard/src/jvmMain/kotlin/org/kodein/log/timestampJvm.kt new file mode 100644 index 0000000..2ded499 --- /dev/null +++ b/canard/src/jvmMain/kotlin/org/kodein/log/timestampJvm.kt @@ -0,0 +1,11 @@ +package org.kodein.log + +import java.text.SimpleDateFormat +import java.util.* + + +public actual fun now(): Timestamp = Timestamp(System.currentTimeMillis().toULong()) + +private val dtf = SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS") + +public actual fun Timestamp.toLocalString(): String = dtf.format(Date(msecSinceEpoch.toLong())) diff --git a/canard/src/allNativeMain/kotlin/org/kodein/log/frontend/printStackTraceNative.kt b/canard/src/nativeMain/kotlin/org/kodein/log/frontend/printStackTraceNative.kt similarity index 80% rename from canard/src/allNativeMain/kotlin/org/kodein/log/frontend/printStackTraceNative.kt rename to canard/src/nativeMain/kotlin/org/kodein/log/frontend/printStackTraceNative.kt index ed308c1..c1f4c5d 100644 --- a/canard/src/allNativeMain/kotlin/org/kodein/log/frontend/printStackTraceNative.kt +++ b/canard/src/nativeMain/kotlin/org/kodein/log/frontend/printStackTraceNative.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalNativeApi::class, ExperimentalForeignApi::class) - package org.kodein.log.frontend import kotlinx.cinterop.ExperimentalForeignApi @@ -10,9 +8,11 @@ import kotlin.experimental.ExperimentalNativeApi import kotlin.native.concurrent.SharedImmutable -@SharedImmutable +@OptIn(ExperimentalForeignApi::class) private val stderr = fdopen(2, "w") +@OptIn(ExperimentalForeignApi::class) internal actual fun errPrintln(msg: String) { fprintf(stderr, "%s\n", msg.cstr) } +@OptIn(ExperimentalNativeApi::class) internal actual fun Throwable.getStackTraceStrings(): Array = getStackTrace() diff --git a/canard/src/allNativeMain/kotlin/org/kodein/log/kclassNative.kt b/canard/src/nativeMain/kotlin/org/kodein/log/kclassNative.kt similarity index 100% rename from canard/src/allNativeMain/kotlin/org/kodein/log/kclassNative.kt rename to canard/src/nativeMain/kotlin/org/kodein/log/kclassNative.kt diff --git a/canard/src/nativeMain/kotlin/org/kodein/log/timestampNative.kt b/canard/src/nativeMain/kotlin/org/kodein/log/timestampNative.kt new file mode 100644 index 0000000..5c5f2f0 --- /dev/null +++ b/canard/src/nativeMain/kotlin/org/kodein/log/timestampNative.kt @@ -0,0 +1,29 @@ +package org.kodein.log + +import kotlinx.cinterop.* +import platform.posix.* + + +@OptIn(UnsafeNumber::class, ExperimentalForeignApi::class) +public actual fun now(): Timestamp { + memScoped { + val spec = alloc() + clock_gettime(CLOCK_REALTIME.convert(), spec.ptr) + return Timestamp(spec.tv_sec.toULong() * 1_000u + spec.tv_nsec.toULong() / 1_000_000u) + } +} + +@OptIn(UnsafeNumber::class, ExperimentalForeignApi::class) +public actual fun Timestamp.toLocalString(): String { + memScoped { + val ms = msecSinceEpoch % 1_000u + val sec = alloc() + sec.value = (msecSinceEpoch / 1_000u).convert() + val info = localtime(sec.ptr) + + val chars = allocArray(32) + strftime(chars, 31.convert(), "%Y-%m-%dT%H:%M:%S", info) + + return chars.toKString() + "." + ms.toString().padStart(3, '0') + } +} diff --git a/canard/src/wasmMain/kotlin/org/kodein/log/frontend/defaultNative.kt b/canard/src/wasmMain/kotlin/org/kodein/log/frontend/defaultNative.kt new file mode 100644 index 0000000..06fb53f --- /dev/null +++ b/canard/src/wasmMain/kotlin/org/kodein/log/frontend/defaultNative.kt @@ -0,0 +1,5 @@ +package org.kodein.log.frontend + +import org.kodein.log.LogFrontend + +public actual val defaultLogFrontend: LogFrontend = printFrontend diff --git a/canard/src/wasmMain/kotlin/org/kodein/log/frontend/printStackTraceWasm.kt b/canard/src/wasmMain/kotlin/org/kodein/log/frontend/printStackTraceWasm.kt new file mode 100644 index 0000000..fdecf8c --- /dev/null +++ b/canard/src/wasmMain/kotlin/org/kodein/log/frontend/printStackTraceWasm.kt @@ -0,0 +1,7 @@ +package org.kodein.log.frontend + + +internal actual fun errPrintln(msg: String) { println(msg) } + +internal actual fun Throwable.getStackTraceStrings(): Array = + arrayOf("Stack traces are currently not supported in WASM") diff --git a/canard/src/wasmMain/kotlin/org/kodein/log/kclassWasm.kt b/canard/src/wasmMain/kotlin/org/kodein/log/kclassWasm.kt new file mode 100644 index 0000000..7fc5b67 --- /dev/null +++ b/canard/src/wasmMain/kotlin/org/kodein/log/kclassWasm.kt @@ -0,0 +1,7 @@ +package org.kodein.log + +import kotlin.reflect.KClass + +public actual val KClass<*>.platformSimpleName: String get() = simpleName ?: "?" + +public actual val KClass<*>.platformPackageName: String get() = "kotlin.wasm" diff --git a/canard/src/wasmMain/kotlin/org/kodein/log/timestampJs.kt b/canard/src/wasmMain/kotlin/org/kodein/log/timestampJs.kt new file mode 100644 index 0000000..64f2390 --- /dev/null +++ b/canard/src/wasmMain/kotlin/org/kodein/log/timestampJs.kt @@ -0,0 +1,30 @@ +package org.kodein.log + + +@JsFun("function dateNow() { return Date.now() }") +private external fun dateNow(): Double + +public actual fun now(): Timestamp = Timestamp(dateNow().toULong()) + +private external class Date(msec: Double) { + fun getFullYear(): Int + fun getMonth(): Int + fun getDate(): Int + fun getHours(): Int + fun getMinutes(): Int + fun getSeconds(): Int + fun getMilliseconds(): Int +} + +@Suppress("LocalVariableName") +public actual fun Timestamp.toLocalString(): String = Date(msecSinceEpoch.toDouble()).let { + val Y = it.getFullYear().toString() + val M = it.getMonth().inc().toString().padStart(2, '0') + val D = it.getDate().toString().padStart(2, '0') + val h = it.getHours().toString().padStart(2, '0') + val m = it.getMinutes().toString().padStart(2, '0') + val s = it.getSeconds().toString().padStart(2, '0') + val ss = it.getMilliseconds().toString().padStart(3, '0') + + "$Y/$M/$D $h:$m:$s:$ss" +} diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 30c9d1b..ae7416b 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -52,11 +52,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@js-joda/core@3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273" - integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg== - "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" diff --git a/settings.gradle.kts b/settings.gradle.kts index 52845e3..77ee433 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,7 +4,7 @@ buildscript { maven(url = "https://raw.githubusercontent.com/kosi-libs/kodein-internal-gradle-plugin/mvn-repo") } dependencies { - classpath("org.kodein.internal.gradle:kodein-internal-gradle-settings:8.2.0") + classpath("org.kodein.internal.gradle:kodein-internal-gradle-settings:8.2.1") } }