FieldLog
Fast and comprehensive logging tool for .NET applications. Designed for high-performance, storage-efficient, always-on logging and comes with a useful log viewer application.
Please bring about 8 minutes to read this page in peace.
tl;dr: Overview of the advantages and features:
FieldLog is a fast and comprehensive logging tool for .NET applications. It allows applications to write events, data and errors to managed and efficient log files. The logging methods are optimised for high performance multi-threaded operation and a single log method call takes as little as half a microsecond on modern hardware. There’s no comparison to OutputDebugString, Debug.WriteLine or appending to a file each time! This logging can be used in performance-critical loops without noticeably slowing down the application.
Compatibility:
Always-on logging
The general idea is to always leave debug logging enabled to be able to analyse it in case of an application failure. Traditional log systems can only append to log files but never delete old data. This leads to constantly increasing log size with the debug level enabled. FieldLog can manage its log files and only keep items of each priority for a specific time, then delete it to save space and remove unnecessary data. The low latency and good storage efficiency allow you to keep logging enabled. When an error occurs, all the relevant information is already here to be analysed.
You don’t need to instruct your users to enable logging by tinkering with hidden XML files and wait for the error to happen again. Instead, the user is guided through collecting the relevant logs and submitting them directly to the developer.
File compression
The log items are written in a binary format that minimises the amount of bytes per information and reuses any previous text strings for storage efficiency. If the same message string is logged over and over again, it will hardly increase the log size. The files are separated by log priority and a new file is started after a certain file size or time. If available, NTFS compression is used and considered in file size decisions. Old log items are automatically deleted. The maximum log size and keep time is configurable by an easy to understand and robust text file in the application directory.
Log viewer
The log viewer application, FieldLogViewer, loads a set of related log files and displays the log items in a list. The user can select any item to view all the details like thread ID, additional exception data, stack traces or system environment data at that time. Items are colour-coded by their priority and icons display the type of event.
A powerful filter editor allows you to quickly find the interesting events and concentrate on what matters. The viewer can even keep reading at the end of the log files and show new log items as they are written by the running application. This allows a developer to monitor the application in real-time. The selected filter remains in effect.
You can also use FieldLogViewer as a DebugOutputString listener (like Sysinternals’ DbgView) and read limited debug output from other processes as well.
Submit tool
An easy to use log sumit tool guides the user through the process of selecting the relevant log files and screenshots, packaging them for transport and choosing a suitable transport method. The transport methods are currently HTTP webservice upload, sending an e-mail and copying the package to a local directory like a USB flash drive. Future methods are using an FTP server and sending to Bluetooth devices. This tool can be started in response to an unhandled or unrecoverable application error (crash reporting) so that the user is prompted with the right information and can submit trace logs while they’re fresh.
Example
The following C# example shows several usage possibilities of FieldLog.
class Program
{
static void Main(string[] args)
{
// Indicate that we're not waiting for a custom log path to be configured.
// If one is provided by the Program.flconfig file, it will be used first.
// Otherwise, the default path strategy is applied.
FL.AcceptLogFileBasePath();
// Write out a first trace message that tells what's about to happen in the
// application.
FL.Trace("Initialising database");
// Do the actual initialisation for the application
try
{
InitializeApp();
}
catch (IOException ex)
{
// An Error event means that something has severely failed but the
// situation could be handled.
FL.Error(ex, "App initialisation");
}
if (!Initialized())
{
// A Critical event is when the application cannot continue to work.
FL.Critical("Application was not initialised");
return;
}
// A Checkpoint is a more important Trace message.
FL.Checkpoint("Initialisation complete");
// Another way to log messages
FL.Text(FieldLogPriority.Notice, "A notice message");
// Main application logic here...
// Measure how long a function takes, averaging multiple iterations
foreach (var record in GetRecords())
{
PrepareSomething();
// ...
using (FL.Timer("Long operation"))
{
LongOperation();
}
}
// Some bonus features:
// Information about the application (reading assembly attributes)
Console.WriteLine("I am " + FL.AppName + " version " + FL.AppVersion);
// Current time using high-precision timer
Console.WriteLine("Now it's precisely " + FL.UtcNow + " (UTC)");
// App uptime using high-precision timer
Console.WriteLine("App is running for " + FL.AppUptime);
// System information: Windows version and edition
Console.WriteLine(OSInfo.Version + " " + OSInfo.Edition);
// System information: Windows installed language
Console.WriteLine(OSInfo.Language);
// System information: User is administrator (does not show UAC dialog)
if (OSInfo.IsCurrentUserLocalAdministrator())
{
// Write something to the system settings
}
}
static void SectionA()
{
// Log the scope of this method. The method name is set automatically.
using (FL.NewScope())
{
// Do interesting stuff here.
int count = 23;
SectionB(count);
// ...
}
}
static void SectionB(int count)
{
// Log the scope of this method. The method name is set automatically.
using (FL.NewScope())
{
// Log the variable name and value with Trace priority.
FL.TraceData("count", count);
// ...
}
}
static void LongOperation()
{
// ...
}
}
You can also take a look at and play with the ConsoleDemo application included in the source code to learn about the logging API.
Screenshots
Here are several screenshots of the FieldLogViewer application:
Download
Note: Releases after 2016-01-09 are no longer digitally signed because there are no more free code signing certificates available for open source developers. A commercial certificate from 200 € per year doesn’t pay for me. I’m sorry for the confusion this may cause with your next download.
FieldLogChanges.txt6.9 KiBChange log of published versions
master.zipLatest source code directly from GitHub
Previous versionsFieldLogSetup-1.525.41_5ab537.exe1.0 MiBVersion 1.525.41 of 2016-06-09, Commit 5ab537
FieldLogSetup-1.481.54_5f3e57.exe1.0 MiBVersion 1.481.54 of 2016-04-26, Commit 5f3e57
FieldLogSetup-1.433.85_17032a.exe1.0 MiBVersion 1.433.85 of 2016-03-09, Commit 17032a
FieldLogSetup-1.415.87_d327d0.exe1.0 MiBVersion 1.415.87 of 2016-02-20, Commit d327d0
FieldLogSetup-1.395.92_5af04a.exe1.0 MiBVersion 1.395.92 of 2016-01-31, Commit 5af04a
FieldLogSetup-1.383.75_4097f2.exe1.0 MiBVersion 1.383.75 of 2016-01-19, Commit 4097f2
FieldLogSetup-1.336.83_5cd1bb.exe1.0 MiBVersion 1.336.83 of 2015-12-03, Commit 5cd1bb
FieldLogSetup-1.334.92_0fb50c.exe1.0 MiBVersion 1.334.92 of 2015-12-01, Commit 0fb50c
FieldLogSetup-1.241.60_ad1f66.exe1.0 MiBVersion 1.241.60 of 2015-08-30, Commit ad1f66
FieldLogSetup-1.208.64_6e1888.exe1.0 MiBVersion 1.208.64 of 2015-07-28, Commit 6e1888
FieldLogSetup-1.200.38_c9395e.exe1.0 MiBVersion 1.200.38 of 2015-07-20, Commit c9395e
FieldLogSetup-1.194.66_9ffa01.exe1.0 MiBVersion 1.194.66 of 2015-07-14, Commit 9ffa01
FieldLogSetup-1.173.83_5e352f.exe1.0 MiBVersion 1.173.83 of 2015-06-23, Commit 5e352f
FieldLogSetup-1.172.86_e0c86e.exe1.0 MiBVersion 1.172.86 of 2015-06-22, Commit e0c86e
FieldLogSetup-1.171.75_b76c5b.exe1.0 MiBVersion 1.171.75 of 2015-06-21, Commit b76c5b
FieldLogSetup-1.116.62_2c0da0.exe1.0 MiBVersion 1.116.62 of 2015-04-27, Commit 2c0da0
FieldLogSetup-1.113.77_6e7f5d.exe1.0 MiBVersion 1.113.77 of 2015-04-24, Commit 6e7f5d
FieldLogSetup-1.38.77_06b662.exe0.9 MiBVersion 1.38.77 of 2015-02-08, Commit 06b662
FieldLogSetup-1.38.51_031fd0.exe911 KiBVersion 1.38.51 of 2015-02-08, Commit 031fd0
FieldLogSetup-17yn.5da7e5.exe916 KiBVersion 17yn of 2015-01-27, Commit 5da7e5
FieldLogSetup-1775.7541b5.exe910 KiBVersion 1775 of 2015-01-19, Commit 7541b5
FieldLogSetup-0v66.4f5b47.exe889 KiBVersion 0v66 of 2014-09-21, Commit 4f5b47
FieldLogSetup-0rq7.71cdec.exe879 KiBVersion 0rq7 of 2014-09-05, Commit 71cdec
FieldLogSetup-0hcn.9d63ee.exe1.0 MiBVersion 0hcn of 2014-06-17, Commit 9d63ee
You can also head over to GitHub to download any previous revision or check the issue tracker:
This package is also available through NuGet. That way, it can be integrated and updated in a Visual Studio project very quickly. This package only includes the FieldLog assembly for all .NET versions. For installing FieldLogViewer you need to download the setup program above.
Unclassified.FieldLog package on NuGet
Current development state
FieldLog and the log file format are stable but could use some more testing. There are plans for future additional features that may change the API and file format. The file format is versioned so it is possible to continue reading old files, even in the same log file set.
FieldLogViewer is pretty stable by now. There are still lots of features and improvements planned and this is where the most changes happen now. See the Git change log for details.
The log submit tool is usable but still new and does not support all planned transport methods yet. If you need to translate it to more languages, please send me the dictionary file so I can include it. You can also keep it to yourself and use a private build.
The documentation is currently limited to the FieldLog code documentation and the developer guide page (German only). The source code reference is not ready for the public yet, use the inline comments through IntelliSense instead (original source code or .xml file as included in the NuGet package).
Changes
- FieldLog: Don't log WPF "Cannot find governing FrameworkElement" messages
- FieldLog: High-resolution system time using the GetSystemTimePreciseAsFileTime method (Windows 8 or later)
- FieldLog: README file in the log directory explains that all files are necessary when copying
- FieldLogViewer: Improved 200% high DPI image scaling (like Visual Studio once did)
- FieldLogViewer: Added Windows 10 theme (incomplete) besides Windows 8 theme
- FieldLogViewer: Make use of WPF 4.6 high-DPI layout improvements (App.config)
- FieldLogViewer: Fixed: Prevent windows stuck invisible on now disconnected monitors
- LogSubmit: Finds log files directly in the current directory
- LogSubmit: Validates e-mail address if provided
- LogSubmit: Saves last entered user e-mail address for the next report
- FieldLog: Simplified exception message formatting (without namespace, not for obfuscated names)
- AppErrorDialog: Increased height for localised titles
- AppErrorDialog supports High DPI screens
- Entity Framework: EntityValidationErrors logging support
- FieldLogViewer: Fixed problems around filter exceptions
- FieldLogViewer: Fixed display of underscores in menu with recently loaded files
- Don't log time recalibration if there was no log item recently
- Fixed: Dynamic methods have no metadata token, so FieldLogStackFrame can't retrieve it
- FieldLogViewer: Little UI enhancements (added details indicator, new enter/leave images)
- Fixed exception logging (and source resolving, deobfuscation) with dynamic or unknown modules and global functions
- Fixed AppErrorDialog message showing horizontal scrollbar when not necessary
- FieldLogViewer: Fixed loading of compressed obfuscation map file
- FieldLogViewer: Optional separator line between log items that represents the time passed between two items
- FieldLogViewer: Limited MRU items list to 15 log base paths
- FieldLogViewer: Do not add temporary log files to the MRU list
- Ignore more WPF trace messages about CanFreeze. These are a WPF bug and not interesting at all.
- Shared code and build script update
- Add new .mapz extension for compressed obfuscation map files
- Improved PdbConvert /optimize performance through parallelisation
- Fixed NullReferenceException when creating a screenshot for no window
- FieldLogViewer: Improved error handling for stack frame module names
- Don't write log files until something relevant happens
- Never try to write log files to a protected service account directory
- Updated build script for Git for Windows 2.x
- Obfuscation compatibility
- FieldLogViewer: Fixed unhandled ArgumentException at Path.GetFileNameWithoutExtension
- FieldLog: Added TextRetainedAppend method
Older versions are contained in the change log file. For a full list of changes please refer to the Git repository commit history.
What’s yet to come…
This is an unsorted list of things that are on my to-do list. There is no time schedule but I intend to implement all of these as soon as I have the time for it.
The name
The name “FieldLog” was originally supposed to refer to “out in the field logging” which is where your applications run. It does everything it can to maintain itself out there and to provide the developer with all relevant information about any problems that might occur. The developer does not need to go where the application runs if users have sufficient internet connectivity or remote hands to submit logs and install updates.
Another interpretation might refer to the structured log items that distinguishes FieldLog from plain text log files that actually only store a single line of raw text about each event. Being able to access and understand each bit of information allows for filtering the data masses to actually see the interesting parts.
The logo merges the capital letters F and L into a combined shape (which happens to look like an E), using different colours for the parts distinct from both letters and the shared part. The horizontal bars also depict “good” and “error” rows in a log list, which is basically what you can see with FieldLog.
Licence and terms of use
The FieldLog library, which is used in applications, is released under the terms of the GNU LGPL licence, version 3. The other projects (FieldLogViewer, demos and tools) are released under the terms of the GNU GPL licence, version 3. You can find the detailed terms and conditions in the download or on the GNU website (LGPL, GPL).
Statistic data
- Created on 2013-06-30, updated on 2017-02-14.
- Ca. 27 000 lines of code, estimated development costs: 27 000 - 110 000 €