-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Unity doesn't offer any in-game logging console by default. You can create your own, if you want. And if you're a mod developer, you may end up in a situation when there is no logging abilities at all, because the devs didn't bother to create one! This plugin covers this pitfall.
IMPORTANT. This Wiki covers only the basic logic of the plugin. Based on the game branch, extra abilities can be introduced or some existing being
removed. Checkout README.md in the relevant branch to know the difference.
This console is aimed to highlight the logs you need, rather just spitting out whatever happens in the game.
- Full screen in-game window that you can bring up by hitting a hotkey (usually a
backquote, but may change based on the game). - Advanced system of logs filtering. You can blacklist logs you don't want to see.
- Check the
silences.cfgfile to adjust or discard the silences. - You can add silences from GUI, but to remove them, you need to edit the file.
- Check the
- Stack trace for any log record allows you figuring out the source module.
- Click any record in the on-screen log and see where exactly it came form.
- Use the file resolution button to determine which DLL holds the code that brought you to the log point.
- Each log record has a "source", a short version of full stack trace that says where this record came from. It's a fully qualified method name, which
usually is enough to get the context:
- Sometimes, there are common modules that do the logging stuff, like
MyMod.DoLog. It can be solved via the config! - You can setup a filter by the source to only see logs from the mod you need.
- Sometimes, there are common modules that do the logging stuff, like
- Log records has timestamps which helps in the retrospective analysis of the events.
- Ability to save the logs into files for even better retrospective analysis.
- The logs files are separately saved into INFO, WARNING and ERROR categories. You can configure it.
- Old log files are deleted automatically saving you from being spammed!
- The on-screen console lets filtering the logs by the specific type: INFO, WARNING, ERROR or EXCEPTION.
- Pause mode to freeze the view when logs records are added too fast.
- Smart modes of grouping repeated events when they come too fast: Condensed and Smart.
See example screenshots here.
There are three settings file that control the plugin's behavior:
-
settings.cfgis a static configuration. It can only be adjusted manually (see below). -
silences.cfgdefines sources that should be ignored by the console. This file may not be existing in your setup. If it doesn't then yor don't have any silences setup. If you need to silences e alog, you can do it via GUI. However, if you need to remove anything, you need to do it manually by changing this file and restarting the game. -
session.cfgthis file is dynamically created to remember your in-game settings. You can change it, but will only work till your next interaction with the console.
Customizes UI representation and user interaction.
UI
{
consoleToggleKey = BackQuote
errorLogColor = 1,0,0,1
exceptionLogColor = 1,0,1,1
infoLogColor = 1,1,1,1
warningLogColor = 1,1,0,1
}
-
consoleToggleKey. Specifies a key that toggles console on/off. Any KeyCode value can be used. - The fields with suffix "color" hold the color definitions for each of the log levels. Color value consists of four float components:
RGBA.
Configures main module that accepts and sorts all the incoming log records. This module is responsible for detecting log record stack trace and the source name.
Source name is a full name of the method from which the log was written. Though, in many cases log records are written via wrapper methods or via the standard libraries, so picking up the first entry from the calling stack is not a good idea. The interceptor uses the override rules to skip the meaningless names in favor of the next value(s) deeper in the stack.
E.g. a standard Unity way to emit a debug log is calling the Debug.Log() method, and this method name will always be the top entry on the stack.
That's why the interceptor by default is configured to skip all sources started from UnityEngine.Debug.: the next entry in the stack is likely to be
the real place that requested the log write.
LogInterceptor
{
enableInterception = True
exactMatchOverride = <some string>
prefixMatchOverride = <some prefix>
}
-
enableInterception. Turns on/off the whole intercepting logic. It's a quick way to disable the plugin without uninstalling it. -
exactMatchOverride. Specifies a list of the source names to ignore. The full case-sensitive match is expected. -
prefixMatchOverride. Specifies a list of the source name prefixes to ignore. The full case-sensitive match is expected. Prefix doesn't need to end with.(period), but it's a good idea to have it there since this will help denoting the namespace.
This filter specifies what records the aggregators should consider during the aggregation. It's a low level filter, which drops the records before they can impact performance in the downstream aggregators. Whatever is filtered out at this level, will never reach any aggregator in the console!
LogFilter
{
exactMatch = <some string>
prefixMatch = <some prefix>
}
-
exactMatch. Specifies a list of the source names to ignore. The full case-sensitive match is expected. -
prefixMatch. Specifies a list of the source name prefixes to ignore. The full case-sensitive match is expected.
LogConsole introduces a concept of "aggregator", a custom class that accepts logs from LogInterceptor and somehow handles them. Usually, the purpose
of this handling is reducing the amount of the records but it's not obligatory.
There are four standard aggregators implemented in the LogConsole plugin.
-
PlainLogAggregator. A simple aggregator which spits every single record to UI, organizing the records by the date in the reverse order. This mode is useful when the exact order and timing of the log events is important. Though, it may get flooded easily by the repeating records. -
CollapseLogAggregator. An aggregator that does simple condensing of the records by joining multiple sequental records into one (grouped by the the severity). The aggregated record will report the number of the repetitions and will have the timestamp of the latest occurrence. This mode allows dealing with the simple cases of the repeated records. -
SmartLogAggregator. An aggregator that does condensing globally. I.e. the repeated records don't need to be sequential in order to be grouped into one record. The aggreghated record gets the timestamp of the most recent event happen. It means that the events that happen frequently stay on top, and the least frequent events go down. -
PersistentLog. This is not actually an aggregator as it outputs every single record (afterLogFilter). The difference is that it writes logs into the disk files. For better logs readability, it can be setup to write three files simultaneously:INFO,WARNING, andERROR. See more information inPersistentLog. This aggregator ignores the silences.
All the aggregators have two main config settings that defines their performance:
-
maxLogRecords. Number of records of each level to keep in memory. It's only important for the aggregators that present their content in UI. The higher values will increase the history length, but will also increase the memory footprint. -
rawBufferSize. It's the size of the aggregator cache. When the records are not immediately required (e.g. for the disk writes or UI presentation) they are not aggregated, they are just stored in a plain memory list, which is a very cheap operation performance wise. However, once the cache is full the aggregation will trigger. This may result in a spiky load increase and, hence, dropping the FPS. Be wise with this setting: the too low and too high values are equally bad.
To setup settings for a particular aggregator add the relevant section into the settings.cfg. E.g. for SmartLogAggregator it would be:
SmartLogAggregator
{
maxLogRecords = 300
rawBufferSize = 1000
}
This aggregator defines how, where and what log files to write. A regular game log usually has just basic information, if exposed at all. And this log file almost always is overwritten on the next game start. The persistent log aggregator ensures you have some history of the logs.
PersistentLog
{
maxLogRecords = 300
rawBufferSize = 1000
enableLogger = True
logFilePrefix = KSPDev-LOG
logFilesPath = GameData/KSPDev/logs
logTsFormat = yyMMddTHHmmss
writeInfoFile = True
writeWarningFile = True
writeErrorFile = True
cleanupPolicy
{
totalFiles = 30
totalSizeMb = 100
maxAgeHours = 168 // 7 days
}
}
-
enableLogger. A simple and quick way to disable the disk writes. -
logFilePrefix. The prefix of every log file. It affects how cleanup policy will work (see below). -
logFilesPath. The absolute or relative path to the folder where the logs need to be stored. If it's relative then it will be counted from the game's root folder. If you set an absulute path, ensure the game has access to it. -
logTsFormat. Specifies how the creation date should be represented in the log file name. It's a regular C# date/time formatting pattern. -
writeInfoFile. Indicates if<logFilePrefix>.<timestamp>.INFO.txtlog file needs to be written. This file will have virtually any log record emitted during the game. It's usually hard to analyse and may impact the performance when writing on a slow disk. However, sometimes it's the only way to track the problem down. -
writeWarningFile. Indicates if<logFilePrefix>.<timestamp>.WARNING.txtlog file needs to be written. This file will only have the log records of the following levels: WARNING, ERROR, and EXCEPTION. Any INFO records will be skipped. -
writeErrorFile. Indicates if<logFilePrefix>.<timestamp>.ERROR.txtlog file needs to be written. This file will only have the log records of the following levels: ERROR and EXCEPTION. Any other records will be skipped.
To not flood logs folder with the outdated sessions, the PersistentLog aggregator allows setting up a cleanup policy. These settings are defined
under CleanupPolicy key. When any limit is hit, the oldest files will be deleted.
-
totalFiles. The maximum allowed number of the log files in the folder. -
totalSizeMb. The maximum allowed total size in megabytes of all the log files in the folder. -
maxAgeHours. The maximum allowed age of the of the files in hours measured from the current date/time.
Important note. The cleanup procedure only affects the files which names start with logFilePrefix. The limits will not be counted against any
other files in the folder.
Custom aggregators won't show up in LogConsole UI, but they can use the existing aggregation framework to do an own logs processing. In order to
implement an own aggregatorm just inherit from BaseLogAggregator, implement abstract
methods, and call StartCapture() when the time is right.