Hello again!
Let’s jump straight into the guts of this post and talk about NuCache and Umbraco V8+
What is NuCache
Well that is a harder topic for me to explain and is probably best explained by the creator himself, Stephan. Fast forward to 22m:47s to learn all about NuCache
What is NuCache Explorer?
It’s a small desktop application that I have built to help you explore and view documents inside NuCache with a JSON representation of what is stored for a document in the NuCache.
I saw a need for this because unlike previous versions of Umbraco the cache of the website was stored in an XML file that could be opened in a simple text editor, with NuCache the files are generated with a dictionary package that saves binary files to disk. So trying to open a NuCache file in a text editor would not allow you to see what is inside your website cache.
I wanted a way to see and confirm what values are being published to variants so hence the need for this tool was born.
Features
OK so here is a quick lowdown of features:
Drag and Drop to open NuCache files
Native Windows file association to NuCache .db files
View document as JSON
Save/export all documents to JSON
Find/goto document by its integer ID or unique guid
Goto line, find, find next and find previous in JSON document
Recent document support via Windows taskbar
Set your own theme for the JSON viewer
Where do I download it?
Go jump on over to GitHub and visit the releases page where you can download the 1.1.0 installer.exe which will get you all setup and ready to start inspecting V8 NuCache files if you are experimenting with V8 or have been attending the V8 hackathons.
Thanks
A couple of thanks. One to Stephan for creating NuCache and lending me some of his code from a command line tool which powers this application in a more UI friendly way. So kudos Stephan!
For the next blog post, I plan to try and talk about how this little utility app works and how maybe you can start making your own tools too, so watch this space shortly…
For the curious hackers and impatient people, I am sure you can jump over to the GitHub repository and look through the source code to see how it was built.
So in this blog post I will perform a switcheroo trick and swap the logging framework used in Umbraco V8 from Log4Net to use Serilog, however I will be one of those awful magicians from that crumby late 90’s show that revealed magician’s secrets to tricks.
That 90’s show where the magician would show how tricks were done
But first up let me try and tell you why I even decided to try and do this in the first place…
Why bother doing a switcheroo with logging frameworks?
I will try my best to explain why I wanted to switch out the current default Logging Framework used for Umbraco which is Log4Net for a Logging Framework called Serilog.
Serilog is a Logging framework that enables structured logging, which is a way to provide more additional meta information to your log with properties versus Log4Net’s approach which simply logs out the given string to a text file or other endpoint.
The main benefit that I see with structured logging, it allows you to query and find log items a lot easier than trawling through an arbitrary text log file, looking for clues and how log items may or may not relate to one another.
For example you could find all Log messages from a given class/type very quickly, find a group of related log items for member id 1234 and perhaps even add the environment in which the log came from such as Development, Staging or Live. Having this extra metadata of properties to search & filter on gives you some great tools & insights into looking through logs in a more organised fashion.
If you use Serilog’s Sinks, a term which is a datastore for logs, then you are able to output the logs to several places at once such as traditional text files, databases or perhaps more useful tools like ElasticSearch or even Serilog’s author companion tool Seq which allows you to visually, perform complex searches & queries to get an insight into your logs.
A screenshot from Seq, a tool to visually filter & query logs
I think I may have done a terrible job of trying to explain this in a short summary, but least I tried ยฏ\_(ใ)_/ยฏ
So in Umbraco V8 you can create a new class that inherits from the class Umbraco.Web.UmbracoApplication, in doing so you are then able to override the method called GetLogger to return an implementation of Umbraco’s ILogger interface, where we can proxy calls to the Umbraco logger to use an underlying Serilog ILogger. With this then done to get Umbraco to use this we simply need to update the Global.asax file on disk to inherit from our new class that is overriding the UmbracoApplication GetLogger method.
using System;
using Serilog;
using Serilog.Core;
using Umbraco.Web;
using ILogger = Umbraco.Core.Logging.ILogger;
namespace MyProject
{
public class SwapLogging : UmbracoApplication
{
protected override ILogger GetLogger()
{
var customLogger = new SeriLogger();
return customLogger;
}
}
/// <summary>
/// Not the nicest but we need to implement Umbraco's own ILogger
/// To call/wrap the underlying Serilog calls
/// </summary>
public class SeriLogger : ILogger
{
private Logger _seriLogger;
public SeriLogger()
{
var basedir = AppDomain.CurrentDomain.BaseDirectory;
var appDomainId = AppDomain.CurrentDomain.Id;
//Configure & setup SeriLogger with Sinks & Enrichers
//Sinks are where we want to push log data to
//Enrichers add extra properties/information to enhance the log item
//TODO: Move to a config file - https://github.com/serilog/serilog/wiki/AppSettings
_seriLogger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.WithProcessId()
.Enrich.WithProcessName()
.Enrich.WithThreadId()
.Enrich.WithProperty("DomainId", appDomainId) //We can add our own properties to logs
.Enrich.WithProperty("BaseDirectory", basedir)
.WriteTo.RollingFile(basedir + "\\logs\\New-UmbracoLogFile-{Date}.txt",
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [P{ProcessId}/D{DomainId}/T{ThreadId}] {Level:u} {SourceContext} - {Message}{NewLine}{Exception}") //We can define what format we want the text logfile to be output as
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
}
public void Error(Type reporting, string message, Exception exception = null)
{
_seriLogger
.ForContext(reporting)
.Error(exception, message);
}
public void Warn(Type reporting, string message)
{
_seriLogger
.ForContext(reporting)
.Warning(message);
}
public void Warn(Type reporting, Func messageBuilder)
{
_seriLogger
.ForContext(reporting)
.Warning(messageBuilder());
}
public void Warn(Type reporting, Exception exception, string message)
{
_seriLogger
.ForContext(reporting)
.Warning(exception, message);
}
public void Warn(Type reporting, Exception exception, Func messageBuilder)
{
_seriLogger
.ForContext(reporting)
.Warning(exception, messageBuilder());
}
public void Info(Type reporting, string message)
{
_seriLogger
.ForContext(reporting)
.Information(message);
}
public void Info(Type reporting, Func messageBuilder)
{
_seriLogger
.ForContext(reporting)
.Information(messageBuilder());
}
public void Debug(Type reporting, string message)
{
_seriLogger
.ForContext(reporting)
.Debug(message);
}
public void Debug(Type reporting, Func messageBuilder)
{
_seriLogger
.ForContext(reporting)
.Debug(messageBuilder());
}
}
}
I’m not convinced, show me it works!
With all magic tricks there is some skepticism, so to be fully transparent and to ensure you its working here is a view of logs coming from Umbraco V8 in my local copy of Seq.
A quick screenshot of my local copy of Seq with Umbraco V8 logs and additional properties pushed in
Tada!
OK so now you know how the magic is done, I would like to hear back via twitter or comments on this post, if this is something useful to have learnt or was this is just a pointless experiment, either way I would love to hear back from you.