mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-17 16:20:03 +00:00
Add seperate root log level config property
Adjust logging behaviour of Gameyfin
This commit is contained in:
@@ -46,7 +46,8 @@ function LogManagementLayout({getConfig, formik}: any) {
|
|||||||
<div className="flex flex-row gap-4">
|
<div className="flex flex-row gap-4">
|
||||||
<ConfigFormField configElement={getConfig("logs.folder")}/>
|
<ConfigFormField configElement={getConfig("logs.folder")}/>
|
||||||
<ConfigFormField configElement={getConfig("logs.max-history-days")}/>
|
<ConfigFormField configElement={getConfig("logs.max-history-days")}/>
|
||||||
<ConfigFormField configElement={getConfig("logs.level")}/>
|
<ConfigFormField configElement={getConfig("logs.level.gameyfin")}/>
|
||||||
|
<ConfigFormField configElement={getConfig("logs.level.root")}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
@@ -86,7 +87,10 @@ const validationSchema = Yup.object({
|
|||||||
logs: Yup.object({
|
logs: Yup.object({
|
||||||
folder: Yup.string().required("Required"),
|
folder: Yup.string().required("Required"),
|
||||||
"max-history-days": Yup.number().required("Required"),
|
"max-history-days": Yup.number().required("Required"),
|
||||||
level: Yup.string().required("Required")
|
level: Yup.object({
|
||||||
|
gameyfin: Yup.string().required("Required"),
|
||||||
|
root: Yup.string().required("Required")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -224,13 +224,23 @@ sealed class ConfigProperties<T : Serializable>(
|
|||||||
30
|
30
|
||||||
)
|
)
|
||||||
|
|
||||||
data object Level : ConfigProperties<LogLevel>(
|
sealed class Level {
|
||||||
|
data object Gameyfin : ConfigProperties<LogLevel>(
|
||||||
LogLevel::class,
|
LogLevel::class,
|
||||||
"logs.level",
|
"logs.level.gameyfin",
|
||||||
"Log level",
|
"Log level (Gameyfin)",
|
||||||
LogLevel.INFO,
|
LogLevel.INFO,
|
||||||
LogLevel.entries
|
LogLevel.entries
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data object Root : ConfigProperties<LogLevel>(
|
||||||
|
LogLevel::class,
|
||||||
|
"logs.level.root",
|
||||||
|
"Log level (Root)",
|
||||||
|
LogLevel.INFO,
|
||||||
|
LogLevel.entries
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class ConfigService(
|
|||||||
*/
|
*/
|
||||||
fun getAll(prefix: String?): List<ConfigEntryDto> {
|
fun getAll(prefix: String?): List<ConfigEntryDto> {
|
||||||
|
|
||||||
log.info { "Getting all config values for prefix '$prefix'" }
|
log.debug { "Getting all config values for prefix '$prefix'" }
|
||||||
|
|
||||||
var configProperties = ConfigProperties::class.sealedSubclasses.flatMap { subclass ->
|
var configProperties = ConfigProperties::class.sealedSubclasses.flatMap { subclass ->
|
||||||
subclass.objectInstance?.let { listOf(it) } ?: listOf()
|
subclass.objectInstance?.let { listOf(it) } ?: listOf()
|
||||||
@@ -91,7 +91,7 @@ class ConfigService(
|
|||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <T : Serializable> set(key: String, value: T) {
|
fun <T : Serializable> set(key: String, value: T) {
|
||||||
log.info { "Set config value '$key'" }
|
log.debug { "Set config value '$key'" }
|
||||||
|
|
||||||
val configProperty = findConfigProperty(key)
|
val configProperty = findConfigProperty(key)
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ class ConfigService(
|
|||||||
*/
|
*/
|
||||||
fun deleteConfig(key: String) {
|
fun deleteConfig(key: String) {
|
||||||
|
|
||||||
log.info { "Delete config value '$key'" }
|
log.debug { "Delete config value '$key'" }
|
||||||
|
|
||||||
val configKey = findConfigProperty(key)
|
val configKey = findConfigProperty(key)
|
||||||
appConfigRepository.deleteById(configKey.key)
|
appConfigRepository.deleteById(configKey.key)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package de.grimsi.gameyfin.logs
|
package de.grimsi.gameyfin.core.logging
|
||||||
|
|
||||||
import com.vaadin.flow.server.auth.AnonymousAllowed
|
import com.vaadin.flow.server.auth.AnonymousAllowed
|
||||||
import com.vaadin.hilla.Endpoint
|
import com.vaadin.hilla.Endpoint
|
||||||
+12
-8
@@ -1,10 +1,10 @@
|
|||||||
package de.grimsi.gameyfin.logs
|
package de.grimsi.gameyfin.core.logging
|
||||||
|
|
||||||
import ch.qos.logback.classic.LoggerContext
|
import ch.qos.logback.classic.LoggerContext
|
||||||
import ch.qos.logback.classic.joran.JoranConfigurator
|
import ch.qos.logback.classic.joran.JoranConfigurator
|
||||||
import de.grimsi.gameyfin.config.ConfigProperties
|
import de.grimsi.gameyfin.config.ConfigProperties
|
||||||
import de.grimsi.gameyfin.config.ConfigService
|
import de.grimsi.gameyfin.config.ConfigService
|
||||||
import de.grimsi.gameyfin.logs.util.AsyncFileTailer
|
import de.grimsi.gameyfin.core.logging.util.AsyncFileTailer
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.boot.context.event.ApplicationStartedEvent
|
import org.springframework.boot.context.event.ApplicationStartedEvent
|
||||||
@@ -41,18 +41,20 @@ class LogService(
|
|||||||
return configureFileLogging(
|
return configureFileLogging(
|
||||||
config.get(ConfigProperties.Logs.Folder)!!,
|
config.get(ConfigProperties.Logs.Folder)!!,
|
||||||
config.get(ConfigProperties.Logs.MaxHistoryDays)!!,
|
config.get(ConfigProperties.Logs.MaxHistoryDays)!!,
|
||||||
config.get(ConfigProperties.Logs.Level)!!
|
config.get(ConfigProperties.Logs.Level.Gameyfin)!!,
|
||||||
|
config.get(ConfigProperties.Logs.Level.Root)!!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun configureFileLogging(folder: String, maxHistoryDays: Int, level: LogLevel) {
|
fun configureFileLogging(folder: String, maxHistoryDays: Int, levelGameyfin: LogLevel, levelRoot: LogLevel) {
|
||||||
val context = LoggerFactory.getILoggerFactory() as LoggerContext
|
val context = LoggerFactory.getILoggerFactory() as LoggerContext
|
||||||
val configurator = JoranConfigurator()
|
val configurator = JoranConfigurator()
|
||||||
configurator.context = context
|
configurator.context = context
|
||||||
context.reset()
|
context.reset()
|
||||||
|
|
||||||
generateLogConfigXml(folder.removeSuffix("/"), maxHistoryDays, level).use {
|
generateLogConfigXml(folder.removeSuffix("/"), maxHistoryDays, levelGameyfin, levelRoot).use {
|
||||||
log.info { "Setting log level to $level" }
|
log.info { "Setting log level for Gameyfin to $levelGameyfin" }
|
||||||
|
log.info { "Setting log level for Root to $levelRoot" }
|
||||||
log.info { "Setting log retention to $maxHistoryDays days" }
|
log.info { "Setting log retention to $maxHistoryDays days" }
|
||||||
configurator.doConfigure(it)
|
configurator.doConfigure(it)
|
||||||
|
|
||||||
@@ -74,7 +76,8 @@ class LogService(
|
|||||||
private fun generateLogConfigXml(
|
private fun generateLogConfigXml(
|
||||||
folder: String,
|
folder: String,
|
||||||
maxHistoryDays: Int,
|
maxHistoryDays: Int,
|
||||||
level: LogLevel
|
levelGameyfin: LogLevel,
|
||||||
|
levelRoot: LogLevel
|
||||||
): InputStream {
|
): InputStream {
|
||||||
val template = javaClass.classLoader.getResourceAsStream(LOG_CONFIG_TEMPLATE)
|
val template = javaClass.classLoader.getResourceAsStream(LOG_CONFIG_TEMPLATE)
|
||||||
?: throw IllegalStateException("Log config template not found")
|
?: throw IllegalStateException("Log config template not found")
|
||||||
@@ -84,7 +87,8 @@ class LogService(
|
|||||||
.replace("{LOG_FOLDER}", folder)
|
.replace("{LOG_FOLDER}", folder)
|
||||||
.replace("{LOG_FILE_NAME}", LOG_FILE_NAME)
|
.replace("{LOG_FILE_NAME}", LOG_FILE_NAME)
|
||||||
.replace("{LOG_MAX_HISTORY_DAYS}", maxHistoryDays.toString())
|
.replace("{LOG_MAX_HISTORY_DAYS}", maxHistoryDays.toString())
|
||||||
.replace("{LOG_LEVEL}", level.toString())
|
.replace("{LOG_LEVEL_GAMEYFIN}", levelGameyfin.toString())
|
||||||
|
.replace("{LOG_LEVEL_ROOT}", levelRoot.toString())
|
||||||
.byteInputStream()
|
.byteInputStream()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package de.grimsi.gameyfin.logs.dto
|
package de.grimsi.gameyfin.core.logging.dto
|
||||||
|
|
||||||
import org.springframework.boot.logging.LogLevel
|
import org.springframework.boot.logging.LogLevel
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package de.grimsi.gameyfin.logs.util
|
package de.grimsi.gameyfin.core.logging.util
|
||||||
|
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
+4
-4
@@ -15,7 +15,7 @@ class PluginConfigService(
|
|||||||
private val log = KotlinLogging.logger {}
|
private val log = KotlinLogging.logger {}
|
||||||
|
|
||||||
fun getConfigMetadata(pluginId: String): List<PluginConfigElement> {
|
fun getConfigMetadata(pluginId: String): List<PluginConfigElement> {
|
||||||
log.info { "Getting config metadata for plugin $pluginId" }
|
log.debug { "Getting config metadata for plugin $pluginId" }
|
||||||
|
|
||||||
val plugin = try {
|
val plugin = try {
|
||||||
pluginManager.getPlugin(pluginId).plugin
|
pluginManager.getPlugin(pluginId).plugin
|
||||||
@@ -29,19 +29,19 @@ class PluginConfigService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getConfig(pluginId: String): Map<String, String?> {
|
fun getConfig(pluginId: String): Map<String, String?> {
|
||||||
log.info { "Getting config for plugin $pluginId" }
|
log.debug { "Getting config for plugin $pluginId" }
|
||||||
return pluginConfigRepository.findAllById_PluginId(pluginId).associate { it.id.key to it.value }
|
return pluginConfigRepository.findAllById_PluginId(pluginId).associate { it.id.key to it.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setConfigEntries(pluginId: String, config: Map<String, String>) {
|
fun setConfigEntries(pluginId: String, config: Map<String, String>) {
|
||||||
log.info { "Setting config entries for plugin $pluginId" }
|
log.debug { "Setting config entries for plugin $pluginId" }
|
||||||
val entries = config.map { PluginConfigEntry(PluginConfigEntryKey(pluginId, it.key), it.value) }
|
val entries = config.map { PluginConfigEntry(PluginConfigEntryKey(pluginId, it.key), it.value) }
|
||||||
pluginConfigRepository.saveAll(entries)
|
pluginConfigRepository.saveAll(entries)
|
||||||
pluginManager.restart(pluginId)
|
pluginManager.restart(pluginId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setConfigEntry(pluginId: String, key: String, value: String) {
|
fun setConfigEntry(pluginId: String, key: String, value: String) {
|
||||||
log.info { "Setting config entry $key for plugin $pluginId" }
|
log.debug { "Setting config entry $key for plugin $pluginId" }
|
||||||
val entry = PluginConfigEntry(PluginConfigEntryKey(pluginId, key), value)
|
val entry = PluginConfigEntry(PluginConfigEntryKey(pluginId, key), value)
|
||||||
pluginConfigRepository.save(entry)
|
pluginConfigRepository.save(entry)
|
||||||
pluginManager.restart(pluginId)
|
pluginManager.restart(pluginId)
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class GameService(
|
|||||||
|
|
||||||
val bestMatchingTitle = FuzzySearch.extractOne(originalQuery, providerToTitle.values).string
|
val bestMatchingTitle = FuzzySearch.extractOne(originalQuery, providerToTitle.values).string
|
||||||
|
|
||||||
log.info {
|
log.debug {
|
||||||
"Best matching title: '$bestMatchingTitle' (${
|
"Best matching title: '$bestMatchingTitle' (${
|
||||||
providerToTitle.count { it.value.fuzzyMatchTitle(bestMatchingTitle) }
|
providerToTitle.count { it.value.fuzzyMatchTitle(bestMatchingTitle) }
|
||||||
}/${providerToTitle.size} matches) for '$originalQuery' determined from $providerToTitle"
|
}/${providerToTitle.size} matches) for '$originalQuery' determined from $providerToTitle"
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ class LibraryService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val progress = completedMetadata.incrementAndGet()
|
val progress = completedMetadata.incrementAndGet()
|
||||||
log.info { "${progress}/${totalPaths} metadata matched" }
|
log.debug { "${progress}/${totalPaths} metadata matched" }
|
||||||
|
|
||||||
return@Callable game
|
return@Callable game
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -225,7 +225,7 @@ class LibraryService(
|
|||||||
completedImageDownload.andIncrement
|
completedImageDownload.andIncrement
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info { "${completedImageDownload}/${totalImages} images downloaded" }
|
log.debug { "${completedImageDownload}/${totalImages} images downloaded" }
|
||||||
|
|
||||||
game
|
game
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -239,7 +239,7 @@ class LibraryService(
|
|||||||
|
|
||||||
// 3. Persist new games
|
// 3. Persist new games
|
||||||
val persistedGames = gameService.create(gamesWithImages)
|
val persistedGames = gameService.create(gamesWithImages)
|
||||||
log.info { "${persistedGames.size}/${totalPaths} saved to database" }
|
log.debug { "${persistedGames.size}/${totalPaths} saved to database" }
|
||||||
|
|
||||||
// 4. Add new games to library
|
// 4. Add new games to library
|
||||||
addGamesToLibrary(persistedGames, library)
|
addGamesToLibrary(persistedGames, library)
|
||||||
|
|||||||
+4
-4
@@ -20,7 +20,7 @@ class MessageTemplateService {
|
|||||||
private val log = KotlinLogging.logger {}
|
private val log = KotlinLogging.logger {}
|
||||||
|
|
||||||
fun getMessageTemplates(): List<MessageTemplateDto> {
|
fun getMessageTemplates(): List<MessageTemplateDto> {
|
||||||
log.info { "Getting all message templates" }
|
log.debug { "Getting all message templates" }
|
||||||
val messageTemplates = MessageTemplates::class.sealedSubclasses.flatMap { subclass ->
|
val messageTemplates = MessageTemplates::class.sealedSubclasses.flatMap { subclass ->
|
||||||
subclass.objectInstance?.let { listOf(it) } ?: listOf()
|
subclass.objectInstance?.let { listOf(it) } ?: listOf()
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ class MessageTemplateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getMessageTemplateContent(key: String, type: TemplateType): String {
|
fun getMessageTemplateContent(key: String, type: TemplateType): String {
|
||||||
log.info { "Reading message template content for '$key.${type.extension}'" }
|
log.debug { "Reading message template content for '$key.${type.extension}'" }
|
||||||
return getTemplateFile(key, type).readText()
|
return getTemplateFile(key, type).readText()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ class MessageTemplateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setMessageTemplateContent(key: String, type: TemplateType, content: String) {
|
fun setMessageTemplateContent(key: String, type: TemplateType, content: String) {
|
||||||
log.info { "Saving message template content for key '$key'" }
|
log.debug { "Saving message template content for key '$key'" }
|
||||||
getOrCreateTemplateFile(key, type).writeText(content)
|
getOrCreateTemplateFile(key, type).writeText(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ class MessageTemplateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getDefaultTemplateFile(key: String, type: TemplateType): Path {
|
private fun getDefaultTemplateFile(key: String, type: TemplateType): Path {
|
||||||
log.info { "No custom message template found for '$key.${type.extension}', returning default" }
|
log.debug { "No custom message template found for '$key.${type.extension}', returning default" }
|
||||||
val resourceUrl = javaClass.classLoader.getResource("$DEFAULT_TEMPLATE_PATH/$key.${type.extension}")
|
val resourceUrl = javaClass.classLoader.getResource("$DEFAULT_TEMPLATE_PATH/$key.${type.extension}")
|
||||||
?: throw IllegalStateException("Default template file not found for '$key.${type.extension}'")
|
?: throw IllegalStateException("Default template file not found for '$key.${type.extension}'")
|
||||||
return Paths.get(resourceUrl.toURI())
|
return Paths.get(resourceUrl.toURI())
|
||||||
|
|||||||
+3
-3
@@ -21,7 +21,7 @@ class UserPreferencesService(
|
|||||||
* @return The current value if set or the default value or null if no value is set and no default value exists
|
* @return The current value if set or the default value or null if no value is set and no default value exists
|
||||||
*/
|
*/
|
||||||
fun <T : Serializable> get(userPreference: UserPreferences<T>): T? {
|
fun <T : Serializable> get(userPreference: UserPreferences<T>): T? {
|
||||||
log.info { "Getting user preference '${userPreference.key}'" }
|
log.debug { "Getting user preference '${userPreference.key}'" }
|
||||||
|
|
||||||
val id = id(userPreference.key)
|
val id = id(userPreference.key)
|
||||||
val appConfig = userPreferenceRepository.findById(id).orElse(null)
|
val appConfig = userPreferenceRepository.findById(id).orElse(null)
|
||||||
@@ -42,7 +42,7 @@ class UserPreferencesService(
|
|||||||
*/
|
*/
|
||||||
fun get(key: String): String? {
|
fun get(key: String): String? {
|
||||||
|
|
||||||
log.info { "Getting user preference '$key'" }
|
log.debug { "Getting user preference '$key'" }
|
||||||
|
|
||||||
val userPreference = findUserPreference(key)
|
val userPreference = findUserPreference(key)
|
||||||
val id = id(key)
|
val id = id(key)
|
||||||
@@ -75,7 +75,7 @@ class UserPreferencesService(
|
|||||||
* @throws IllegalArgumentException if the value can't be cast to the type defined for the user preference
|
* @throws IllegalArgumentException if the value can't be cast to the type defined for the user preference
|
||||||
*/
|
*/
|
||||||
fun <T : Serializable> set(key: String, value: T) {
|
fun <T : Serializable> set(key: String, value: T) {
|
||||||
log.info { "Set user preference '$key'" }
|
log.debug { "Set user preference '$key'" }
|
||||||
|
|
||||||
val userPreferenceKey = findUserPreference(key)
|
val userPreferenceKey = findUserPreference(key)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
logging.level.de.grimsi.gameyfin: DEBUG
|
|
||||||
logging.level.org.hibernate.SQL: DEBUG
|
|
||||||
logging.level.org.hibernate.type: TRACE
|
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:h2:file:./db/${spring.datasource.db-name};AUTO_SERVER=TRUE
|
url: jdbc:h2:file:./db/${spring.datasource.db-name};AUTO_SERVER=TRUE
|
||||||
@@ -15,10 +15,9 @@
|
|||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- Spams the logs on DEBUG due to a loop (log -> push to client -> log the push -> repeat) -->
|
<logger name="de.grimsi.gameyfin" level="{LOG_LEVEL_GAMEYFIN}"/>
|
||||||
<logger name="com.vaadin.hilla.push.PushEndpoint" level="INFO"/>
|
|
||||||
|
|
||||||
<root level="{LOG_LEVEL}">
|
<root level="{LOG_LEVEL_ROOT}">
|
||||||
<appender-ref ref="CONSOLE"/>
|
<appender-ref ref="CONSOLE"/>
|
||||||
<appender-ref ref="FILE"/>
|
<appender-ref ref="FILE"/>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
Reference in New Issue
Block a user