Use Log4Net for efficient logging in Unity3D

Development with Unity3D can be fun with the right tools. But debugging a loosely coupled system like Unity’s gameobjects and monobehaviours is not the most fun thing to do.

Proper logging is crucial for virtually every application. Logs allow you to record the state of your application while it is running. If something goes wrong, you these logs can help you trace the error to its cause or at least give you some hints on why it has happened in the first place. Logging is not just for development – keep your log statements in the code and you can react better to bug reports from your users. Got bugs that you can’t replicate on your side? Ask for the log file, it may give you exactly the input you need.

When it comes to logging, you want logs to be as complete as reasonably possible. The logs need to be readable and clear. At the same time, you want logging to be fast. Logging cannot be that important to justify noticeable lags or performance drops. And last but not least: ideally you want to be able to configure logging within the game. This way, if there are bugs, you can just reconfigure the logging to show more detail.

Unity’s logging (or lack of)

Unity itself comes with a minimal logging system for developers to use. The class Debug comes with a few helper methods, but honestly, it is nothing to write home about. The log methods are incredible slow, causing noticeable delays when you start logging more than a few statements. Logs cannot be filtered and are not written to disk. And did I mention that logging is slow? Damn, it is so slow that it is unusable for any serious work.

Luckily, the Java community solved the logging problem years ago with Log4J. For the .NET communities, a port of this code exists as Log4Net. Log4Net comes with all the necessary features needed from a logging system:

  • it logs to files, with log rotation if needed
  • it has a low overhead for unused log statements
  • logging itself is fast and well optimized
  • runtime configurable
  • implementing your own logger is easy

Log4Net patched for Unity

Using Log4Net is not straight forward. Access the wrong features and you end up with lots of errors and hard-to-trace bugs. Our new role-playing game Valion requires stable logging, and thus I took the Log4Net source code and imported it into Unity3D. (Note: I always prefer source versions over binary DLLs. With sources you can look into problems, no need to guess, no need to pray.) This version is based on Log4Net 1.2.11, with just minor adjustments to the preprocessor directives and some platform specific code kicked out. This version runs both in standalone mode and the web-player. When running in the web-player, you cannot log to files, as the sandbox prohibits that. But you can log to a memory buffer or the normal console just fine.

Using Log4net for Unity

Before you can use Log4Net, you have to configure the log system. The configuration defines where log entries get written and sets the various filters. With a proper log system, you dont have to change your code each time you want to enable or disable logging for certain components. All you need to do is change the configuration and your loggers will write out more information.

Logging is done via a single interface called “ILog” and instances of these loggers are acquired via the LogManager. You can then write your log messages to these loggers. For performance reasons it is wise to test whether a logger is enabled before you construct your log message.

using log4net;
using UnityEngine;

public class MyBehaviour: MonoBehaviour
{
  // get a log instance
  private static ILog logger = LogManager.GetLogger(typeof(MyBehaviour));

  public void Update()
  {
     if (logger.IsDebugEnabled)
     {
       logger.Debug ("Some important debug messages here");
     }
  }
}

Initializing the log system in Unity3D

To initialize the logging in your Unity project, import the “LogManager for Unity3D” unitypackage into your project. Inside this package, you find three classes:

  • ValionLog – configures the log system
  • ValionLogAppender – a in memory appender used by the log console
  • ValionLogWindow – a simple GUI showing the messages received by the ValionLogAppender

The ValionLog must be added to a empty game object. You can add the ValionLogWindow component as well to get a instant log console for your game.

When starting up, the log manager configures the logging system. If you are running a standalone player, the logs will be stored in your platform’s default locations. When your application shuts down, ValionLog also ensures that all log files are closed properly.

The log files are stored at the following locations:

Mac OS X  ~/Library/Logs/Application/log.txt
Windows XP  C:\Documents and Settings\username\Local Settings\Application Data\Unity\Application\log.txt
Windows Vista/7  C:\Users\username\AppData\Local\Unity\Application\log.txt

“Application” is a placeholder. You can configure your own application name in the inspector for the ValionLog object.

I release the classes “ValionLog”, “ValionLogAppender” and “ValionLogWindow” as public domain. Feel free to use these classes in your own projects. Drop me a comment or e-mail if you find this useful or in case you encounter any problems using these classes. Log4Net is licensed under the Apache License 2.0 license.

Comments



Hi, I’m trying out the log4Net for Unity and I’m getting the following error in the editor after I imported the log4net 1.2.11 plugin.

Assets/Plugins/log4net/Config/Log4NetConfigurationSectionHandler.cs(51,59): error CS0246: The type or namespace name `IConfigurationSectionHandler’ could not be found. Are you missing a using directive or an assembly reference?

I’ve tried adding a reference to System.configuration into the assembly, but that doesn’t clear it. Any suggestions?


This error is caused by a Unity setting. Your player’s API compatibility level is currently set to “.NET 2.0 subset”. Set it to “.NET 2.0″ (without the subset) and it works.

The subset setting cuts out quite a few core APIs (including System.Configuration) which Log4net depends on. So far I went the easy route and just kicked out whatever is incompatible with the full Unity set.

Well, I do PC/Mac deployments and just adding one high-quality texture adds more to the size of the project than any of the stripped out code. So I haven’t had the need to strip out more code.


PS: The setting is under “Edit->Project Settings->Player” and then “Per-Platform settings”.

Ahh, and one more thing: Unity does not pick up the changes, you have to Reimport (via context-menu) your log4net script directory after making that change.




Add a comment


* mandatory fields