Skip to content

Commit

Permalink
feat: logger class (#27)
Browse files Browse the repository at this point in the history
* feat(common): basic support for logger, development mode

* chore: use the 'Logger' class to log messages instead of using 'println' directly
  • Loading branch information
EchoEllet authored Jul 10, 2024
1 parent d9eaa46 commit 36332b7
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import minecraftAssetProviders.curseForge.models.CurseForgeModFileDownloadUrlRes
import minecraftAssetProviders.curseForge.models.CurseForgeModFileResponse
import services.HttpClient
import services.HttpResponse
import utils.Logger

class RemoteCurseForgeDataSource : CurseForgeDataSource {
companion object {
Expand All @@ -28,7 +29,7 @@ class RemoteCurseForgeDataSource : CurseForgeDataSource {
)
) {
is HttpResponse.Success -> {
println("\uFE0F Curse Forge Mod ($modId) File ($fileId) Json Response: ${response.body}")
Logger.info { "\uFE0F Curse Forge Mod ($modId) File ($fileId) Json Response: ${response.body}" }
Result.success(response.decodeJson<CurseForgeModFileResponse>())
}

Expand All @@ -52,7 +53,7 @@ class RemoteCurseForgeDataSource : CurseForgeDataSource {
)
return when (response) {
is HttpResponse.Success -> {
println("\uFE0F Curse Forge Mod ($modId) File ($fileId) Download URL Json Response: ${response.body}")
Logger.info { "\uFE0F Curse Forge Mod ($modId) File ($fileId) Download URL Json Response: ${response.body}" }
Result.success(response.decodeJson<CurseForgeModFileDownloadUrlResponse>())
}

Expand Down
2 changes: 2 additions & 0 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ val generateBuildConfig =
tasks.register<GenerateBuildConfigTask>("generateBuildConfig") {
// To allow overriding the current project version
val projectVersion: String? by project
val developmentMode: String? by project

val buildConfigDirectory = project.layout.buildDirectory.dir("generated")

classFullyQualifiedName.set("generated.BuildConfig")
generatedOutputDirectory.set(buildConfigDirectory)
fieldsToGenerate.put("PROJECT_VERSION", projectVersion ?: libs.versions.project.get())
fieldsToGenerate.put("DEVELOPMENT_MODE", developmentMode?.toBooleanStrictOrNull() ?: false)
}

sourceSets.main.configure {
Expand Down
13 changes: 7 additions & 6 deletions common/src/main/kotlin/gui/utils/GuiUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.formdev.flatlaf.themes.FlatMacLightLaf
import constants.SharedAssetConstants
import gui.theme.Theme
import gui.theme.ThemeMode
import utils.Logger
import utils.getResourceAsURLOrThrow
import utils.os.OperatingSystem
import java.awt.Component
Expand Down Expand Up @@ -152,14 +153,14 @@ object GuiUtils {
e.printStackTrace()

if (e is UnsupportedLookAndFeelException) {
println(
"⚠️ Couldn't switch to the selected theme \uD83C\uDFA8. It looks like this theme is not supported on your system.",
)
Logger.error {
"⚠️ Couldn't switch to the selected theme \uD83C\uDFA8. It looks like this theme is not supported on your system."
}
return
}
println(
"❌ Failed to switch to the selected theme \uD83C\uDFA8: ${e.message}",
)
Logger.error {
"❌ Failed to switch to the selected theme \uD83C\uDFA8: ${e.message}"
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions common/src/main/kotlin/gui/utils/ThemeDetector.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gui.utils

import utils.Logger
import utils.SystemInfoProvider
import utils.commandLine
import utils.os.LinuxDesktopEnvironment
Expand Down Expand Up @@ -48,20 +49,20 @@ object ThemeDetector {
SystemInfoProvider.getUserHomeDirectoryPath(),
".config/kdeglobals",
)
println(
Logger.info {
"\uD83D\uDCC4 Reading the following file to check if the KDE Plasma desktop environment " +
"is in dark mode: ${kdeGlobalsFile.pathString}",
)
"is in dark mode: ${kdeGlobalsFile.pathString}"
}
return try {
val lookAndFeelPackageName =
kdeGlobalsFile.bufferedReader().useLines { line ->
line.firstOrNull { it.startsWith("LookAndFeelPackage=") }?.substringAfter('=')
}
println("✨ The KDE Plasma look and feel package name: 🎨 $lookAndFeelPackageName")
Logger.info { "✨ The KDE Plasma look and feel package name: 🎨 $lookAndFeelPackageName" }
Result.success(lookAndFeelPackageName)
} catch (e: Exception) {
e.printStackTrace()
println("❌ Error while reading the file ${kdeGlobalsFile.name}: ${e.message}")
Logger.error { "❌ Error while reading the file ${kdeGlobalsFile.name}: ${e.message}" }
Result.failure(e)
}
}
Expand Down
12 changes: 8 additions & 4 deletions common/src/main/kotlin/utils/CommandLine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fun commandLine(
}
append(": ${args.joinToString(" ")}")
}
println(message)
Logger.info { message }
}
return try {
val process =
Expand All @@ -39,18 +39,22 @@ fun commandLine(
process.destroy()
val errorMessage = "⏰ Process timed out for the command: ${args.joinToString(" ")}"
if (isLoggingEnabled) {
println("$errorMessage")
Logger.error { "$errorMessage" }
}
return Result.failure(RuntimeException(errorMessage))
}
val result = process.inputStream.bufferedReader().use { it.readText() }
if (isLoggingEnabled) {
println("✅ Command executed successfully: '${args.joinToString(" ")}'. " + "📜 Output: ${result.trim()}")
Logger.info {
"✅ Command executed successfully: '${args.joinToString(" ")}'. " + "📜 Output: ${result.trim()}"
}
}
Result.success(result)
} catch (e: Exception) {
if (isLoggingEnabled) {
println("❌ Error executing command `${args.joinToString(" ")}`: ${e.message}")
Logger.error {
"❌ Error executing command `${args.joinToString(" ")}`: ${e.message}"
}
}
e.printStackTrace()
Result.failure(e)
Expand Down
60 changes: 60 additions & 0 deletions common/src/main/kotlin/utils/Logger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package utils

import generated.BuildConfig

/**
* A simple logger that doesn't require additional dependencies and is not compatible
* with known logging solutions. Most of the messages will be shown to the user
* in case they run the application in CLI mode either in command-line or using the launcher,
* which is why don't use something like `[main] INFO Main - The log message` in production mode.
* */
object Logger {
fun error(lazyMessage: () -> String) {
logMessage(lazyMessage = lazyMessage, logLevel = "Error")
}

fun debug(lazyMessage: () -> String) {
if (!BuildConfig.DEVELOPMENT_MODE) return
logMessage(lazyMessage = lazyMessage, logLevel = "Debug")
}

fun info(
extraLine: Boolean = false,
lazyMessage: () -> String,
) {
logMessage(
extraLine = extraLine,
lazyMessage = lazyMessage,
logLevel = "Info",
)
}

fun warning(lazyMessage: () -> String) {
logMessage(lazyMessage = lazyMessage, logLevel = "Warning")
}

fun trace(lazyMessage: () -> String) {
logMessage(lazyMessage = lazyMessage, logLevel = "Trace")
}

private fun logMessage(
/**
* Add an extra new line before printing the message
* */
extraLine: Boolean = false,
lazyMessage: () -> String,
logLevel: String,
) {
val message =
buildString {
if (extraLine) {
append("\n")
}
if (BuildConfig.DEVELOPMENT_MODE) {
append("$logLevel - ")
}
append(lazyMessage())
}
println(message)
}
}
41 changes: 22 additions & 19 deletions sync-script/src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import syncService.ResourcePacksSyncService
import syncService.ServersSyncService
import syncService.SyncService
import utils.ExecutionTimer
import utils.Logger
import utils.SystemInfoProvider
import utils.createFileWithParentDirectoriesOrTerminate
import utils.deleteRecursivelyWithLegacyJavaIo
Expand All @@ -49,8 +50,8 @@ suspend fun main(args: Array<String>) {

passedArgs = args

println("📋 Current project version: ${BuildConfig.PROJECT_VERSION}")
println("\uD83D\uDCC1 Current working directory: ${SystemInfoProvider.getCurrentWorkingDirectoryPath()}")
Logger.info { "📋 Current project version: ${BuildConfig.PROJECT_VERSION}" }
Logger.info { "\uD83D\uDCC1 Current working directory: ${SystemInfoProvider.getCurrentWorkingDirectoryPath()}" }

logSystemInfo()
handleTemporaryDirectory(isStart = true)
Expand Down Expand Up @@ -79,7 +80,7 @@ suspend fun main(args: Array<String>) {

GuiState.updateIsGuiEnabled()

println("\uFE0F Script Configuration: ${ScriptConfig.instance}")
Logger.info { "\uFE0F Script Configuration: ${ScriptConfig.instance}" }

// Switch to the themes specified by config
if (GuiState.isGuiEnabled) {
Expand Down Expand Up @@ -108,28 +109,28 @@ private fun logSystemInfo() {
OperatingSystem.MacOS -> "\uD83C\uDF4F You are using macOS \uF8FF. Welcome to the world of Apple \uD83C\uDF4E."
OperatingSystem.Windows -> "\uD83E\uDE9F You are using Windows. Be safe!"
OperatingSystem.Unknown -> "❓Your operating system couldn't be identified. Let's hope everything works smoothly."
}.also { println(it) }
}.also { Logger.info { it } }

if (!GraphicsEnvironment.isHeadless()) {
if (GuiUtils.isSystemInDarkMode) {
"🌙 Welcome to the dark side! Your system is in dark mode. Enjoy the soothing darkness! 🌃"
} else {
"☀️ Brighten up your day! Your system is in the light mode. Embrace the light! 🌅"
}.also { println(it) }
}.also { Logger.info { it } }
}
}

private fun handleTemporaryDirectory(isStart: Boolean) {
SyncScriptDotMinecraftFiles.SyncScriptData.Temp.path.apply {
if (exists()) {
println(
Logger.info {
if (isStart) {
"\uFE0F The temporary folder: $pathString exist. " +
"The script might not finished last time. Removing the folder."
} else {
"\uD83D\uDEAB Deleting the temporary folder: '$pathString' (no longer needed)."
},
)
}
}
deleteRecursivelyWithLegacyJavaIo()
}
}
Expand All @@ -139,10 +140,10 @@ private suspend fun loadScriptConfig(): ScriptConfig {
val scriptConfigFile = SyncScriptDotMinecraftFiles.SyncScriptData.ScriptConfig.path
if (!scriptConfigFile.exists()) {
if (GuiState.isGuiEnabled) {
println(
"Configuration Missing! ⚠\uFE0F. Since you're in GUI mode, we'll launch a quick " +
"dialog to gather the necessary information",
)
Logger.info {
"\uFE0F Configuration Missing. Since you're in GUI mode, we'll launch a quick " +
"dialog to gather the necessary information"
}

val scriptConfig = CreateScriptConfigDialog().showDialog()
runBlocking { scriptConfigDataSource.replaceConfig(scriptConfig) }
Expand Down Expand Up @@ -248,6 +249,8 @@ private suspend fun fetchSyncInfo() {
return
}

Logger.debug { "\uD83D\uDC1E Sync Info: ${SyncInfo.instance}" }

LoadingIndicatorDialog.instance?.updateComponentProperties(
title = "Synchronization",
infoText = "Performing initial checks and configurations...",
Expand Down Expand Up @@ -275,10 +278,10 @@ private suspend fun handleAdminTrustCheck() {
// If the user doesn't say he/she trusts the admin yet, then we will ask him
val doesUserTrustThisSource = TrustAdminDialog.showDialog()
if (!doesUserTrustThisSource) {
println(
Logger.info {
"\uD83D\uDD12 Script is closing because trust in the administration is lacking. " +
"Feel free to reach out if you have any concerns.",
)
"Feel free to reach out if you have any concerns."
}
terminateWithOrWithoutError()
}
runBlocking {
Expand Down Expand Up @@ -315,9 +318,9 @@ private fun finalize(applicationExecutionTimer: ExecutionTimer) {
// after finish syncing the contents successfully, we don't need it anymore.
handleTemporaryDirectory(isStart = false)

println(
"\n\uD83C\uDF89 The script has successfully completed in " +
"(${applicationExecutionTimer.getRunningUntilNowDuration().inWholeMilliseconds}ms)! \uD83D\uDE80",
)
Logger.info(extraLine = true) {
"\uD83C\uDF89 The script has successfully completed in " +
"(${applicationExecutionTimer.getRunningUntilNowDuration().inWholeMilliseconds}ms)! \uD83D\uDE80"
}
exitProcess(0)
}
Loading

0 comments on commit 36332b7

Please sign in to comment.