We love to use our favorite logging solutions as much as possible but if external storage or external services are involved we cannot guarantee that logging works in crisis situation. This blog post introduces wrapper or fallback logger that uses main one to log all the messages and secondary one when main logger fails. Implementation is easy but there’s a good chance that log messages doesn’t get completely lost when main logging service goes down.
NB! Source code shown here is taken from my TemperatureStation solution at Github. My loggers for Windows 10 IoT Core are in Loggers folder of Windows 10 IoT Core background service. To make ETW logging work on Windows 10 IoT Core, please read my blog post Using ETW tracing on Windows 10 IoT Core.
Why logger with fallback?
We want to use logger that is familiar to us and that puts its logs to some place we are familiar with. Here are some examples of loggers that write logs to external storage:
- SyslogLogger – logs events to external Syslog server,
- ApplicationInsightsLogger – logs events to Application Insights trace logs.
But what happens when network goes down or WiFi driver crashes and same time something interesting happens in our IoT solution? It’s possible we have to power RaspberryPi off to make it restart. With high probability the latest logs are gone forever. Fallback logger is here to help us out.
Architecture of fallback logger
All loggers in TemperatureStation background service use the same ILogger interface. It makes code easier to handle if ILogger is known and the concrete type of logger is just a matter of configuration.
FallbackLogger is a special case. It also follows the ILogger interface but it also uses two loggers:
- Main logger – this is the logger that is tried first,
- Secondary logger – this logger is used when main one failed.
To illustrate fallback logger better here the example. Main logger is SyslogLogger that logs events to Syslog server in local network. If network goes down or Syslog server is not available for any other reason then ETW trace logger is used because it works locally and doesn’t need any external resources.
Implementation of fallback logger
Here is the raw and unpolished implementation of FallbackLogger. I know the code can be better and more compact because of repeating try-catch pattern but let’s stick with this implementation as it is easier to understand.
internal class FallbackLogger : ILogger
{
private readonly ILogger _mainLogger;
private readonly ILogger _fallbackLogger;
public FallbackLogger(ILogger mainLogger, ILogger fallbackLogger)
{
_mainLogger = mainLogger;
_fallbackLogger = fallbackLogger;
}
public void Debug(string message)
{
try
{
_mainLogger.Debug(message);
}
catch (Exception ex)
{
_fallbackLogger.Debug(message);
_fallbackLogger.Critical(ex.ToString());
}
}
public void Info(string message)
{
try
{
_mainLogger.Info(message);
}
catch (Exception ex)
{
_fallbackLogger.Info(message);
_fallbackLogger.Critical(ex.ToString());
}
}
public void Warn(string message)
{
try
{
_mainLogger.Warn(message);
}
catch (Exception ex)
{
_fallbackLogger.Warn(message);
_fallbackLogger.Critical(ex.ToString());
}
}
public void Error(string message)
{
try
{
_mainLogger.Error(message);
}
catch (Exception ex)
{
_fallbackLogger.Error(message);
_fallbackLogger.Critical(ex.ToString());
}
}
public void Critical(string message)
{
try
{
_mainLogger.Critical(message);
}
catch (Exception ex)
{
_fallbackLogger.Critical(message);
_fallbackLogger.Critical(ex.ToString());
}
}
}
Actually simple code that makes sure that logging works also when main logger we all love can’t do its job for some reason.
Wrapping up
Monitoring IoT solutions is important specially when custom hardware is involved and we must be ready to react to problems we were not ready to expect at first place. Still we want to use familiar logging systems and services. But some problems like network problems and service outages may end up with situation where our solution is not able to log down important information. This is where fallback logger comes in with some logger that works locally and that doesn’t use any external resources. Although fallback logger implementation here is primitive, it still works well in practice.