From a887c35e8772a3c29c3371fedf471cc03165ccb6 Mon Sep 17 00:00:00 2001 From: barinek Date: Fri, 31 May 2024 07:53:54 -0600 Subject: [PATCH] basic json logger --- applications/basic-server/build.gradle.kts | 1 + .../main/kotlin/io/initialcapacity/web/App.kt | 5 + .../src/main/resources/logback.xml | 11 +- .../data-analyzer-server/build.gradle.kts | 2 + .../data-collector-server/build.gradle.kts | 2 + build.gradle.kts | 1 - settings.gradle.kts | 1 + support/logging-support/build.gradle.kts | 9 ++ .../logging/BasicJSONLogger.kt | 111 ++++++++++++++++++ .../logging/BasicJSONLoggerFactory.kt | 16 +++ .../logging/BasicJSONServiceProvider.kt | 36 ++++++ .../org.slf4j.spi.SLF4JServiceProvider | 1 + .../logging/BasicJSONServiceProviderTest.kt | 13 ++ .../src/test/resources/logback.xml | 6 + 14 files changed, 206 insertions(+), 9 deletions(-) create mode 100644 support/logging-support/build.gradle.kts create mode 100644 support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLogger.kt create mode 100644 support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLoggerFactory.kt create mode 100644 support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONServiceProvider.kt create mode 100644 support/logging-support/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider create mode 100644 support/logging-support/src/test/kotlin/test/initialcapacity/logging/BasicJSONServiceProviderTest.kt create mode 100644 support/logging-support/src/test/resources/logback.xml diff --git a/applications/basic-server/build.gradle.kts b/applications/basic-server/build.gradle.kts index 0651b24..a5c987b 100644 --- a/applications/basic-server/build.gradle.kts +++ b/applications/basic-server/build.gradle.kts @@ -8,6 +8,7 @@ val ktorVersion: String by project dependencies { implementation(project(":components:data-analyzer")) + implementation(project(":support:logging-support")) implementation(project(":support:workflow-support")) implementation("io.ktor:ktor-server-core-jvm:$ktorVersion") diff --git a/applications/basic-server/src/main/kotlin/io/initialcapacity/web/App.kt b/applications/basic-server/src/main/kotlin/io/initialcapacity/web/App.kt index 84f4973..5bc5894 100644 --- a/applications/basic-server/src/main/kotlin/io/initialcapacity/web/App.kt +++ b/applications/basic-server/src/main/kotlin/io/initialcapacity/web/App.kt @@ -14,9 +14,14 @@ import io.ktor.server.response.respond import io.ktor.server.routing.Routing import io.ktor.server.routing.get import io.ktor.util.pipeline.PipelineContext +import org.slf4j.LoggerFactory import java.util.* +private val logger = LoggerFactory.getLogger(object {}.javaClass.enclosingClass) + fun Application.module() { + logger.info("starting the app") + install(FreeMarker) { templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates") } diff --git a/applications/basic-server/src/main/resources/logback.xml b/applications/basic-server/src/main/resources/logback.xml index a6ea2d5..ae071f6 100644 --- a/applications/basic-server/src/main/resources/logback.xml +++ b/applications/basic-server/src/main/resources/logback.xml @@ -1,11 +1,6 @@ - - - %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - + + + \ No newline at end of file diff --git a/applications/data-analyzer-server/build.gradle.kts b/applications/data-analyzer-server/build.gradle.kts index 7c60499..3c7cfd1 100644 --- a/applications/data-analyzer-server/build.gradle.kts +++ b/applications/data-analyzer-server/build.gradle.kts @@ -7,6 +7,8 @@ group = "io.initialcapacity.analyzer" val ktorVersion: String by project dependencies { + implementation("org.slf4j:slf4j-simple:2.0.7") + implementation(project(":components:data-analyzer")) implementation(project(":support:workflow-support")) diff --git a/applications/data-collector-server/build.gradle.kts b/applications/data-collector-server/build.gradle.kts index 8f9fe19..3a66358 100644 --- a/applications/data-collector-server/build.gradle.kts +++ b/applications/data-collector-server/build.gradle.kts @@ -7,6 +7,8 @@ group = "io.initialcapacity.collector" val ktorVersion: String by project dependencies { + implementation("org.slf4j:slf4j-simple:2.0.7") + implementation(project(":components:data-collector")) implementation(project(":support:workflow-support")) diff --git a/build.gradle.kts b/build.gradle.kts index 6deab01..8fe590e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,6 @@ subprojects { dependencies { implementation("org.slf4j:slf4j-api:2.0.7") - implementation("org.slf4j:slf4j-simple:2.0.7") testImplementation(kotlin("test-junit")) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 37379fe..9a40c78 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,5 +8,6 @@ include( "components:data-collector", "components:data-analyzer", + "support:logging-support", "support:workflow-support" ) diff --git a/support/logging-support/build.gradle.kts b/support/logging-support/build.gradle.kts new file mode 100644 index 0000000..0f69ca7 --- /dev/null +++ b/support/logging-support/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("org.jetbrains.kotlin.plugin.serialization") +} + +dependencies { + implementation("org.slf4j:slf4j-api:2.0.7") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0-RC.2") +} \ No newline at end of file diff --git a/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLogger.kt b/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLogger.kt new file mode 100644 index 0000000..a5b4310 --- /dev/null +++ b/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLogger.kt @@ -0,0 +1,111 @@ +package io.initialcapacity.logging + +import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import org.slf4j.Marker +import org.slf4j.event.Level +import org.slf4j.helpers.LegacyAbstractLogger +import org.slf4j.helpers.MessageFormatter +import org.slf4j.spi.LocationAwareLogger +import java.time.Instant +import java.time.ZoneId +import java.time.format.DateTimeFormatter + + +class BasicJSONLogger(val desiredName: String) : LegacyAbstractLogger() { + init { + this.name = desiredName + } + + override fun isTraceEnabled(): Boolean { + return isLevelEnabled(LocationAwareLogger.TRACE_INT); + } + + override fun isDebugEnabled(): Boolean { + return isLevelEnabled(LocationAwareLogger.DEBUG_INT); + } + + override fun isInfoEnabled(): Boolean { + return isLevelEnabled(LocationAwareLogger.INFO_INT); + } + + override fun isWarnEnabled(): Boolean { + return isLevelEnabled(LocationAwareLogger.WARN_INT); + } + + override fun isErrorEnabled(): Boolean { + return isLevelEnabled(LocationAwareLogger.ERROR_INT); + } + + override fun getFullyQualifiedCallerName(): String? { + return null + } + + @Serializable + data class Entry( + val time: String, + val threadName: String, + val severity: String, + val loggerName: String, + val message: String + ) + + private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ") + + @Synchronized + override fun handleNormalizedLoggingCall( + level: Level?, + marker: Marker?, + messagePattern: String?, + arguments: Array?, + throwable: Throwable? + ) { + + val time = Instant.now().atZone(ZoneId.of("UTC")).format(formatter) + val threadName = Thread.currentThread().name + val severity = renderLevel(level!!.toInt()) + val loggerName = name + val message = MessageFormatter.basicArrayFormat(messagePattern, arguments) + + // %r [%t] %level %logger - %m%n + // val builder = StringBuilder(32) + // builder.append(time); + // builder.append(" ") + // builder.append("[") + // builder.append(threadName) + // builder.append("] ") + // builder.append(levelString) + // builder.append(" ") + // builder.append(loggetName).append(" - "); + // builder.append(message); + // val entry = builder.toString() + + val entry = Entry(time, threadName, severity, loggerName, message) + val encodeToString = Json.encodeToString(entry) + + System.err.println(encodeToString) + throwable?.printStackTrace() + System.err.flush() + } + + private fun isLevelEnabled(level: Int): Boolean { + return (level >= LocationAwareLogger.INFO_INT) + } + + private fun renderLevel(level: Int): String { + when (level) { + LocationAwareLogger.TRACE_INT -> return "TRACE" + LocationAwareLogger.DEBUG_INT -> return "DEBUG" + LocationAwareLogger.INFO_INT -> return "INFO" + LocationAwareLogger.WARN_INT -> return "WARN" + LocationAwareLogger.ERROR_INT -> return "ERROR" + } + throw IllegalStateException("Unrecognized level [$level]") + } + + private val json = Json { + isLenient = true + ignoreUnknownKeys = true + } +} diff --git a/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLoggerFactory.kt b/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLoggerFactory.kt new file mode 100644 index 0000000..aebbd56 --- /dev/null +++ b/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONLoggerFactory.kt @@ -0,0 +1,16 @@ +package io.initialcapacity.logging + +import org.slf4j.ILoggerFactory +import org.slf4j.Logger +import java.util.concurrent.ConcurrentHashMap + + +class BasicJSONLoggerFactory : ILoggerFactory { + private var loggerMap = ConcurrentHashMap(); + + override fun getLogger(name: String): Logger { + return loggerMap.computeIfAbsent(name) { + BasicJSONLogger(it) + } + } +} diff --git a/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONServiceProvider.kt b/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONServiceProvider.kt new file mode 100644 index 0000000..3477611 --- /dev/null +++ b/support/logging-support/src/main/kotlin/io/initialcapacity/logging/BasicJSONServiceProvider.kt @@ -0,0 +1,36 @@ +package io.initialcapacity.logging + +import org.slf4j.ILoggerFactory +import org.slf4j.IMarkerFactory +import org.slf4j.helpers.BasicMarkerFactory +import org.slf4j.helpers.NOPMDCAdapter +import org.slf4j.spi.MDCAdapter +import org.slf4j.spi.SLF4JServiceProvider + + +class BasicJSONServiceProvider : SLF4JServiceProvider { + var REQUESTED_API_VERSION: String = "2.0.99" + + private var loggerFactory = BasicJSONLoggerFactory() + private var markerFactory = BasicMarkerFactory() + private var mdcAdapter = NOPMDCAdapter() + + override fun getLoggerFactory(): ILoggerFactory { + return loggerFactory + } + + override fun getMarkerFactory(): IMarkerFactory { + return markerFactory + } + + override fun getMDCAdapter(): MDCAdapter { + return mdcAdapter + } + + override fun getRequestedApiVersion(): String { + return REQUESTED_API_VERSION + } + + override fun initialize() { + } +} \ No newline at end of file diff --git a/support/logging-support/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/support/logging-support/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider new file mode 100644 index 0000000..629197c --- /dev/null +++ b/support/logging-support/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider @@ -0,0 +1 @@ +io.initialcapacity.logging.BasicJSONServiceProvider \ No newline at end of file diff --git a/support/logging-support/src/test/kotlin/test/initialcapacity/logging/BasicJSONServiceProviderTest.kt b/support/logging-support/src/test/kotlin/test/initialcapacity/logging/BasicJSONServiceProviderTest.kt new file mode 100644 index 0000000..7f06bc1 --- /dev/null +++ b/support/logging-support/src/test/kotlin/test/initialcapacity/logging/BasicJSONServiceProviderTest.kt @@ -0,0 +1,13 @@ +package test.initialcapacity.logging + +import org.slf4j.LoggerFactory +import kotlin.test.Test + +class BasicJSONServiceProviderTest { + + @Test + fun test1() { + val logger = LoggerFactory.getLogger("test1") + logger.info("Hello world.") + } +} \ No newline at end of file diff --git a/support/logging-support/src/test/resources/logback.xml b/support/logging-support/src/test/resources/logback.xml new file mode 100644 index 0000000..ae071f6 --- /dev/null +++ b/support/logging-support/src/test/resources/logback.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file