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

Error log is slower than others #344

Closed
NitrinCloud opened this issue Dec 28, 2022 · 4 comments
Closed

Error log is slower than others #344

NitrinCloud opened this issue Dec 28, 2022 · 4 comments
Labels

Comments

@NitrinCloud
Copy link

Describe the bug
When logging an error at the end of a while loop and logging info at the beginning the info message get's displayed first if the loop continues

2022-12-28 14:06:14 [main] -> DEBUG: Input['asfd'] was issued
2022-12-28 14:06:14 [main] -> INFO: Select a version [PROXY, GAME_SERVER]
af
2022-12-28 14:06:15 [main] -> DEBUG: Input['af'] was issued
2022-12-28 14:06:15 [main] -> INFO: Select a version [PROXY, GAME_SERVER]
2022-12-28 14:06:15 [main] -> ERROR: Couldn't verify input
adf
2022-12-28 14:06:15 [main] -> DEBUG: Input['adf'] was issued
2022-12-28 14:06:15 [main] -> INFO: Select a version [PROXY, GAME_SERVER]
2022-12-28 14:06:15 [main] -> ERROR: Couldn't verify input

To Reproduce
Steps to reproduce the behavior:

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.tinylog.kotlin.Logger
import kotlin.reflect.KClass
import kotlin.reflect.cast

class Question<T: Any>(private val text: String, private val type: KClass<T>, private val answers: List<T> = emptyList()) {

    init {
        if (!(type == String::class || type == Boolean::class || type == Char::class ||
                    type == Short::class || type == Int::class || type == Long::class ||
                    type == Float::class || type == Double::class || type.isEnum)) {
            throw UnsupportedOperationException("Question only supports primitives, but was $type")
        }
    }

    @Suppress("MemberVisibilityCanBePrivate")
    lateinit var answer: T
        private set

    suspend fun askConsole(): Question<T> {
        do {
            Logger.info(text + if (answers.isNotEmpty()) answers.joinToString(prefix = " [", postfix = "]", separator = ", ") else "")
            val input = withContext(Dispatchers.IO) {
                readln()
            }
            Logger.debug("Input['$input'] was issued")
            try {
                val cast = type.cast(when (type) {
                    String::class -> input
                    Boolean::class -> input.toBooleanStrict()
                    Char::class -> {
                        val charArray = input.toCharArray()
                        if (charArray.size > 1) {
                            throw IllegalArgumentException()
                        }
                        charArray.first()
                    }

                    Short::class -> input.toShort()
                    Int::class -> input.toInt()
                    Long::class -> input.toLong()
                    Float::class -> input.toFloat()
                    Double::class -> input.toDouble()
                    else -> {
                        if (!type.isEnum) {
                            throw UnsupportedOperationException()
                        }

                        type.enumConstants.find {
                            (it as Enum<*>).name.equals(input, ignoreCase = true)
                        } ?: throw IllegalArgumentException()
                    }
                })

                if (answers.isNotEmpty() && !answers.contains(cast)) {
                    Logger.error("Wrong answer")
                } else {
                    answer = cast
                }
            } catch (e: Exception) {
                Logger.error("Couldn't verify input")
            }
        } while (!::answer.isInitialized)

        return this
    }
}

Environment
tinylog version: 2.5.0
Kotlin version: 1.7.21

@pmwmedia
Copy link
Member

What is your tinylog configuration?

@NitrinCloud
Copy link
Author

writerFile          = rolling file
writerFile.level    = info
writerFile.format   = {date} [{thread}] -> {level}: {message}
writerFile.file     = logs/log_{count}.txt
writerFile.latest   = logs/latest.log
writerFile.charset  = UTF-8
writerFile.buffered = true
writerFile.policies = startup, daily: 03:00
writerFile.backups  = 10
writerFile.convert  = gzip

writerConsole          = console
writerConsole.level    = debug
writerConsole.format   = {date} [{thread}] -> {level}: {message}
writerConsole.writingthread = true

Here is my configuration. I tried with enabled and disabled writingthread

@NitrinCloud
Copy link
Author

Okay, I just got to the point where I tested my project outside of IntelliJ. Seems like the "bug" only occurs in IntelliJ's console.

@pmwmedia
Copy link
Member

pmwmedia commented Jan 4, 2023

Yes, the console of IntelliJ (and also some other consoles) have this behavior. The standard output stream and the error stream are two independent asynchronous streams. Therefore, it is possible that the output to one of these both streams can overtake the other. tinylog nor any other Java library can change this behavior.

However, you reconfigure the console writer to use only the standard output stream or the error stream for all severity levels:

writer        = console
writer.stream = out      # or err

Please be aware that this has the disadvantage that all severity levels will have the same color in the console of IntelliJ.

By the way, the writing thread can only be enabled globally for all writers. It is not possible to enable it only for a certain writer.

writingthread = true

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests

2 participants