-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Welcome to the UnityDev_LogConsole wiki!
Standard in-game debugging console (Alt+F12) is not very convenient when many third-party mods are installed in the game. There is a lot of flood, and it's hard to understand what mod produced which records. It becomes even harder to work with the console when records are being added at a high rate. This mod presents logs in a better organized form:
- Full screen window improves visibility.
- Advanced system of logs filtering. You can blacklist logs you don't want to see.
- Stack trace for any log record allows you figuring out the source module.
- Each log record has a "source", a short version of full stack trace that says where this record came from.
- Log records has timestamps which help in retrospective analysis of the events.
- Ability to save the logs into files for even better retrospective analysis.
- A quick filter can be applied to see logs of the specific types only: INFO, WARNING, ERROR or EXCEPTION.
- Pause mode to freeze the view when logs records are added too fast.
- Two special modes for handling high frequency logs (e.g. when logging from
Update()method). In Condensed and Smart modes multiple repeated records are collapsed into just one line. - Console settings can be adjusted via
settings.cfgfile.
See example shcreenshots here.
At this moment none of the global settings below can be adjusted via UI (see
issue #9). In order to change them a direct editing
of settings.cfg file should be made. In release this file is located in
GameData/KSPDev/LogConsole/Plugins/PluginData folder.
Customizes UI representation and user interaction.
UI
{
consoleToggleKey = BackQuote
ColorSchema
{
errorLog = 1,0,0,1
exceptionLog = 1,0,1,1
infoLog = 1,1,1,1
warningLog = 1,1,0,1
}
}
-
consoleToggleKey. Specifies a key that toggles console on/off. Any KeyCode value can be used. -
ColorSchema. Holds color definition for each log level. Color value consists of four components:R,G,B, andA.
Configures main module that accepts and sorts all incoming log records. This module is responsible for detecting log record stack trace and 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 standard libraries, so picking up the first entry from the calling stack is not a good idea. Interceptor uses override rules to skip meaningless names in favor of the next value(s) deeper in the stack.
E.g. standard Unity way to emit a debug log is calling Debug.Log() method, and this method name
will always be the top entry on the stack. That's why interceptor by default is configured to skip
all sources started from UnityEngine.Debug.: the next entry in the stack is likely the real place
that requested log write.
LogInterceptor
{
enableInterception = True
ExactMatchOverride
{
source = <some string>
}
PrefixMatchOverride
{
sourcePrefix = <some string>
}
}
-
enableInterception. Turns on/off the whole intercepting logic. It's a quick way to rollback to the natural log handling without removing mod from the game. -
ExactMatchOverride. Specifies list of source names to ignore. The full case-sensitive match is expected. -
PrefixMatchOverride. Specifies list of source name prefixes to ignore. The full case-sensitive match is expected. Prefix doesn't need to end with.(period) but it's good idea to have it since this will help denoting namespace.
This filter specifies what records aggregators consider during aggregation. The filter is common for all aggregators but it's up to the aggregator implementation whether to consider the filter or not. Filter values can be added via console UI but in order to remove them the settings file needs to be edited directly.
LogFilter
{
ExactMatchFilter
{
source = <some string>
}
PrefixMatchFilter
{
sourcePrefix = <some string>
}
}
-
ExactMatchFilter. Specifies list of source names to ignore. The full case-sensitive match is expected. -
PrefixMatchFilter. Specifies list of source name prefixes to ignore. The full case-sensitive match is expected.
Note that when silencing sources thru the UI values in the lists may have non-ASCII symbols. That's okay since many internally generated classes and methods in C# have non-ASCII format. Be careful when editing settings file with these values since many editors just ignore such symbols.
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 records but it's
not obligatory.
There are four standard aggregators implemented in LogConsole mod. All but the last one can be seen in UI.
They respect filter set thru LogFilter and won't consider silenced sources.
-
PlainLogAggregator. Simple aggregator which spits every single record on UI organizing records by the date in the reverse order. It's almost the same as the stock logger except the sorting order. This mode is useful when exact order and timing of the log events is important. Though, it may get flooded easily by the repeating records (as it happens with the stock logger). -
CollapseLogAggregator. Aggregator that does simple condensing by joining of the repeated records into just one. The aggregated record will report number of repetitions and will have timestamp of the latest occurrence. This mode allows dealing with simple cases of repeated records (e.g. repeated errors during scene loading orUpdatemethod throws). Though, when repeated records alternate with other records (possibly repeated too) the condensing has not effect. -
SmartLogAggregator. Aggregator that does condensing globally. I.e. the repeated records don't need to be sequential in order to be grouped into one record. Due to each aggregation does update to the timestamp the last changed record will always show up at the top of the list. Some practice may be needed to read such logs. This mode is the best to deal with multiple repeating log records (e.g. when multiple components throw from theUpdatemethod). -
PersistentLog. This is not actually an aggregator as it outputs every single record. 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, and ERROR. See more information inPersistentLog. This aggregator ignores silences and outputs all incoming records into file(s).
All aggregators have two main config settings that defines their performance:
-
maxLogRecords. Number of records of each level to remember and present in UI when requested. It's only important for the aggregators that present their content on UI. Higher values will increase history length but also increase memory footprint. Moreover, too long history may make logs less readable. -
rawBufferSize. That's the size of the aggregator cache. When records are not immediately required (e.g. for 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). Though, once the cache is full the aggregation will trigger regardless. This may result in a spiky load increase and, hence, dropping in FPS. Be wise with this setting: too low and too high values are equally bad.
To setup settings for a particular aggregator add the relevant structure into settings.cfg. E.g. for
SmartLogAggregator it would be:
SmartLogAggregator
{
maxLogRecords = 300
rawBufferSize = 1000
}
Defines how, where and what log files to write. In spite of standard KSP.log file which is overwritten on
every game start LogConsole doesn't overwrite its logs. It allows getting back in time to track the issue.
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 disk writes of the logs. -
logFilePrefix. Prefix of every log file. It affects how cleanup policy will work (see below). -
logFilesPath. 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. -
logTsFormat. Specifies how creation date should be represented in the log file name. It's a regular C# date/time formatting pattern. If pattern results into a name used in one of the previous sessions the file will be overwritten. -
writeInfoFile. Tells 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 performance when writing on a slow disk. Though, sometimes it's the only way to track the problem down. -
writeWarningFile. Tells if<logFilePrefix>.<timestamp>.WARNING.txtlog file needs to be written. This file will only have log records of the following levels: WARNING, ERROR, and EXCEPTION. Any INFO records will be skipped. So this file is useful to debug potentially unsafe situations. -
writeErrorFile. Tells if<logFilePrefix>.<timestamp>.ERROR.txtlog file needs to be written. This file will only have log records of the following levels: ERROR and EXCEPTION. Any other records will be skipped. So this file is useful to debug indeed error situations.
To not flood logs folder with outdated sessions PersistentLog allows setting up a cleanup policy. These
settings are defined under cleanupPolicy key. When any limit is hit the oldest files will be deleted until
the limit is satisfied.
-
totalFiles. Maximum allowed number of log files in the folder. -
totalSizeMb. Maximum allowed total size in megabytes of all log files in the folder. -
maxAgeHours. Maximum allowed age of the of files in hours measured from the current date/time.
Important note. The cleanup procedure only affects 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 existing aggregation framework to do
own logs processing. In order to implement own aggregator just inherit from
BaseLogAggregator, implement abstract
methods, and call StartCapture() when the time is right. Performance settings handling will come for free.