Skip to content

Commit

Permalink
Implement Logger.kt (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
uniumuniu authored Oct 13, 2023
1 parent 2f2497b commit 9ecf32d
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 1 deletion.
17 changes: 16 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ dependencies {
api("org.apache.commons:commons-math3:3.6.1")

// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation("com.google.guava:guava:31.1-jre")
implementation("net.swiftzer.semver:semver:1.3.0")
implementation("com.goncalossilva:murmurhash:0.4.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
}

// Apply a specific Java toolchain to ease working on different environments.
Expand All @@ -80,3 +80,18 @@ tasks.named<Test>("test") {
showStandardStreams = true
}
}

// TODO: Remove excludes when Instance.kt is ready
sourceSets {
main {
kotlin {
exclude("com/featurevisor/sdk/Instance.kt")
exclude("com/featurevisor/sdk/InstanceOptions.kt")
}
}
test {
kotlin {
exclude("com/featurevisor/sdk/InstanceTest.kt")
}
}
}
52 changes: 52 additions & 0 deletions src/main/kotlin/com/featurevisor/sdk/Logger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.featurevisor.sdk

import com.featurevisor.sdk.LogLevel.*

typealias LogMessage = String
typealias LogDetails = Map<String, Any>
typealias LogHandler = (level: LogLevel, message: LogMessage, details: LogDetails?) -> Unit

enum class LogLevel(val value: String) {
ERROR("error"),
WARN("warn"),
INFO("info"),
DEBUG("debug")
}

class Logger(
private var levels: List<LogLevel>,
private val handle: LogHandler,
) {

companion object {
private val defaultLogLevels: List<LogLevel> = listOf(ERROR, WARN)
private val defaultLogHandler: LogHandler = { level, message, _ ->
println("[${level.value}] $message")
}

fun createLogger(levels: List<LogLevel> = defaultLogLevels, handle: LogHandler = defaultLogHandler): Logger =
Logger(levels, handle)
}

fun setLevels(levels: List<LogLevel>) {
this.levels = levels
}

fun debug(message: LogMessage, details: LogDetails? = null) =
log(DEBUG, message, details)

fun info(message: LogMessage, details: LogDetails? = null) =
log(INFO, message, details)

fun warn(message: LogMessage, details: LogDetails? = null) =
log(WARN, message, details)

fun error(message: LogMessage, details: LogDetails? = null) =
log(ERROR, message, details)

private fun log(level: LogLevel, message: LogMessage, details: LogDetails? = null) {
if (level in levels) {
handle(level, message, details)
}
}
}
108 changes: 108 additions & 0 deletions src/test/kotlin/com/featurevisor/sdk/LoggerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.featurevisor.sdk

import com.featurevisor.sdk.LogLevel.DEBUG
import com.featurevisor.sdk.LogLevel.ERROR
import com.featurevisor.sdk.LogLevel.INFO
import com.featurevisor.sdk.LogLevel.WARN
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.Test

class LoggerTest {

private val mockLogMessage = "test message"
private val mockLogDetails: Map<String, Any> = emptyMap()
private val mockLogHandler: LogHandler = mockk {
every { this@mockk(any(), any(), any()) } answers { nothing }
}

private val systemUnderTest = Logger.createLogger(
handle = mockLogHandler,
)

@Test
fun `log DEBUG message when level DEBUG is set`() {
systemUnderTest.setLevels(listOf(DEBUG))

systemUnderTest.debug(
message = mockLogMessage,
details = mockLogDetails,
)

verify(exactly = 1) {
mockLogHandler(DEBUG, mockLogMessage, mockLogDetails)
}
}

@Test
fun `log INFO message when level INFO is set`() {
systemUnderTest.setLevels(listOf(INFO))

systemUnderTest.info(
message = mockLogMessage,
details = mockLogDetails,
)

verify(exactly = 1) {
mockLogHandler(INFO, mockLogMessage, mockLogDetails)
}
}

@Test
fun `log WARN message when level WARN is set`() {
systemUnderTest.setLevels(listOf(WARN))

systemUnderTest.warn(
message = mockLogMessage,
details = mockLogDetails,
)

verify(exactly = 1) {
mockLogHandler(WARN, mockLogMessage, mockLogDetails)
}
}

@Test
fun `log ERROR message when level ERROR is set`() {
systemUnderTest.setLevels(listOf(ERROR))

systemUnderTest.error(
message = mockLogMessage,
details = mockLogDetails,
)

verify(exactly = 1) {
mockLogHandler(ERROR, mockLogMessage, mockLogDetails)
}
}

@Test
fun `do not log any message when not set in log levels`() {
systemUnderTest.setLevels(listOf())

systemUnderTest.info(
message = mockLogMessage,
details = mockLogDetails,
)
systemUnderTest.warn(
message = mockLogMessage,
details = mockLogDetails,
)
systemUnderTest.debug(
message = mockLogMessage,
details = mockLogDetails,
)
systemUnderTest.error(
message = mockLogMessage,
details = mockLogDetails,
)

verify(exactly = 0) {
mockLogHandler(INFO, any(), any())
mockLogHandler(WARN, any(), any())
mockLogHandler(DEBUG, any(), any())
mockLogHandler(ERROR, any(), any())
}
}
}

0 comments on commit 9ecf32d

Please sign in to comment.