COLOTOK; Cocoa LogTool for Kotlin
âś… Print log with color
âś… Formatter
âś… Print log where you want
 🌟 ConsoleProvider
 🌟 FileProvider
 🌟 StreamProvider
âś… Log Rotation
 🌟 SizeBaseRotation
 🌟 DateBaseRotation(; DurationBase)
âś… Customize output location
 🌟 example print log into slack
âś… Structure Logging
basic dependency
repositories {
mavenCentral()
// add this line
maven(url = "https://jitpack.io" )
}
dependencies {
// add this line
implementation("com.github.milkcocoa0902:colotok:0.1.9")
}
if you use structure logging or create your own provider, you need to add kotlinx-serialization
plugins {
// add this.
// set version for your use
kotlin("plugin.serialization") version "1.9.21"
}
dependencies {
// add this line to use KSerializer<T> and @Serializable
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.0")
}
configure colotok with code.
see below.
val logger = LoggerFactory()
.addProvider(ConsoleProvider())
.addProvider(FileProvider(Path.of("./test.log")))
.getLogger()
more details config
val fileProvider: FileProvider
val logger = LoggerFactory()
.addProvider(ConsoleProvider{
// show above info level in console
level = LogLevel.INFO
})
.addProvider(FileProvider(Path.of("./test.log")){
// write above trace level for file
level = LogLevel.TRACE
// memory buffering to save i/o
enableBuffer = true
// memory buffer size, if buffer excced this, append to file
bufferSize = 2048
// use size base rotation
rotation = SizeBaseRotation(size = 4096)
}.apply {
fileProvider = this
})
.getLogger()
logger.trace("TRACE LEVEL LOG")
logger.debug("DEBUG LEVEL LOG")
logger.info("INFO LEVEL LOG")
logger.warn("WARN LEVEL LOG")
logger.error("ERROR LEVEL LOG")
now, you can print log into your space.
logger.trace("TRACE LEVEL LOG")
logger.debug("DEBUG LEVEL LOG")
logger.info("INFO LEVEL LOG")
logger.warn("WARN LEVEL LOG")
logger.error("ERROR LEVEL LOG")
logger.atInfo {
print("in this block")
print("all of logs are printed out with INFO level")
}
// or you can add additional parameters
logger.info("INFO LEVEL LOG", mapOf("param1" to "a custom attr"))
// you may need to flash, if log cache is enabled for `FileProvider`
fileProvider.flush()
colotok has builtin text formatter.
- PlainTextFormatter
- SimpleTextFormatter
- DetailTextFormatter
this formatter shows as below style's log
logger.info("message what happen")
// message what happen
this formatter shows as below style's log
logger.info("message what happen")
// 2023-12-29 12:23:14.220383 [INFO] - message what happen
this formatter shows as below style's log
logger.ingo("message what happen", mapOf("param1" to "a custom attribute"))
// 2023-12-29T12:21:13.354328+09:00 (main)[INFO] - message what happen, additional = {param1=a custom attribute}
colotok has builtin structured formatter.
- SimpleStructureFormatter
- DetailStructureFormatter
if you has a class
@Serializable
class LogDetail(val scope: String, val message: String): LogStructure
@Serializable
class Log(val name: String, val logDetail: LogDetail): LogStructure
this formatter shows bellow style's log
logger.info(
Log(
name = "illegal state",
LogDetail(
"args",
"argument must be greater than zero"
)
),
Log.serializer()
)
// // {"message":{"name":"illegal state","logDetail":{"scope":"args","message":"argument must be greater than zero"}},"level":"INFO","date":"2023-12-29"}
logger.info("message what happen")
// {"msg":"message what happen","level":"INFO","date":"2023-12-29"}
this formatter shows bellow style's log
logger.info(
Log(
name = "illegal state",
LogDetail(
"args",
"argument must be greater than zero"
)
),
Log.serializer(),
// you can pass additional attrs
mapOf("additional" to "additional param")
)
// {"message":{"name":"illegal state","logDetail":{"scope":"args","message":"argument must be greater than zero"}},"level":"INFO","additional":"additional param","date":"2023-12-29T12:34:56+09:00"}
logger.info("message what happen")
// {"message":"message what happen","level":"INFO","thread":"main","date":"2023-12-29T12:27:22.5908+09:00"}
colotok has builtin provider. Provider is used for output log.
- ConsoleProvider
- FileProvider
- StreamProvider
this provider outputs log into console with ansi-color
this provider output log into file without ansi-color.
this provider output log into stream where you specified.
you can also output to remote or sql or others by create own provider.
example
if you want to write log into slack, you create a SlackProvider like this
class SlackProvider(config: SlackProviderConfig): Provider {
constructor(config: SlackProviderConfig.() -> Unit): this(SlackProviderConfig().apply(config))
class SlackProviderConfig() : ProviderConfig {
var webhook_url: String = ""
override var level: level = LogLevel.DEBUG
override var formatter: Formatter = DetailTextFormatter
}
private val webhookUrl = config.webhook_url
private val logLevel = config.level
private val formatter = config.formatter
override fun write(name: String, msg: String, level: LogLevel, attr: Map<String, String>) {
if(level.isEnabledFor(logLevel).not()){
return
}
kotlin.runCatching {
webhookUrl.httpPost()
.appendHeader("Content-Type" to "application/json")
.body("""
{"text": "${formatter.format(msg, level, attr)}"}
""".trimIndent())
.response()
}.getOrElse { println(it) }
}
override fun <T : LogStructure> write(
name: String,
msg: T,
serializer: KSerializer<T>,
level: LogLevel,
attr: Map<String, String>
) {
if(level.isEnabledFor(logLevel).not()){
return
}
kotlin.runCatching {
webhookUrl.httpPost()
.appendHeader("Content-Type" to "application/json")
.body("""
{"text": "${formatter.format(msg, serializer, level, attr)}"}
""".trimIndent())
.response()
}.getOrElse { println(it) }
}
}
now you can use SlackProvider to write the log into slack.
val logger = LoggerFactory()
.addProvider(ConsoleProvider{
formatter = DetailTextFormatter
level = LogLevel.DEBUG
})
.addProvider(SlackProvider{
webhook_url = "your slack webhook url"
formatter = SimpleTextFormatter
level = LogLevel.WARN
})
.getLogger()
logger.info("info level log")
// written the log only console
logger.error("error level log")
// written the log both of console and slack
- TRACE (all log)
- DEBUG (ignore TRACE)
- INFO (ignore DEBUG and TRACE)
- WARN (only WARN or ERROR)
- ERROR (only one)
https://milkcocoa0902.github.io/colotok/01-colotok-introduce.html