Easy in-proc debugging for Seq Apps

TL;DR: the new Seq.Apps.Testing package makes it easy to interactively debug Seq Apps in C#, by hosting them in a console app and sending events directly from Serilog.

Seq Apps are server-side plug-ins that send and receive events and notifications. A huge number have been published to NuGet, and while they can be written in any language, nearly all of them are built in C# using the Seq.Apps library.

At runtime, Seq loads up C# app assemblies in a hosting process and feeds events through STDIN, STDOUT, and STDERR. This is all well-and-good, but it's a painful feedback loop to work with while you're developing a new app: change your app, build a NuGet package, install it into Seq, find and attach to the running host process, debug, find an issue, ... repeat.

The new Seq.Apps.Testing package cuts this feedback loop right down: change your app, press F5, and interactively debug - just like any other application!

Screenshot of a debugger stepping through source code from the Seq.App.Mail.SmtpMailApp class.
Debugging Seq.App.Mail.Smtp in JetBrains Rider.

Here's how to set it up.

Create a console test harness

First, alongside your Seq App project, create a new console application:

mkdir TestHarness
cd TestHarness
dotnet new console

Then, add a reference to your Seq app project, and install the Seq.Apps.Testing package:

dotnet add reference ../MyApp/MyApp.csproj
dotnet add package Seq.Apps.Testing --prerelease
dotnet add package Serilog.Sinks.Console

I've also added Serilog.Sinks.Console, since it makes it a bit easier to check that the events being generated look the way you expect.

Configure Serilog to send events directly to your app

This example is from https://github.com/datalust/seq-app-mail, where new apps for SMTP and Microsoft 365 email are being developed.

The SMTP app is implemented by the class SmtpMailApp. In Program.cs, under TestHarness, use AuditTo.SeqApp() to send Serilog events directly to the app:

using Seq.App.Mail.Smtp;
using Serilog;

using var logger = new LoggerConfiguration()
    .WriteTo.Console()
    .AuditTo.SeqApp<SmtpMailApp>(new Dictionary<string, string>
    {
        [nameof(SmtpMailApp.From)] = "from@localhost",
        [nameof(SmtpMailApp.To)] = "to@localhost",
        [nameof(SmtpMailApp.Host)] = "localhost",
        [nameof(SmtpMailApp.ProtocolSecurity)] = "None"
    })
    .CreateLogger();

AuditTo.SeqApp<SmtpMailApp>() is where all of the interesting things take place.

Why AuditTo? The AuditTo configuration object adds sinks to the Serilog pipeline just like WriteTo, but allows exceptions from the sinks to propagate back out. This is what we need here, since we don't want exceptions to be swallowed while we're debugging.

The dictionary passed to AuditTo.SeqApp needs to contain values for all of the app's required settings. For example, the From address that we pass through with:

        [nameof(SmtpMailApp.From)] = "from@localhost",

Supplies a value to the From property on SmtpMailApp:

    [SeqAppSetting(
        DisplayName = "From address",
        HelpText = "The address from which the email is being sent.")]
    public string? From { get; set; }

Generate events using the Serilog logger

The logger object can now be used to send events directly (and synchronously) to the app instance:

logger.Information("Hello, {Name}!", Environment.UserName);

You can get creative here, using C# the full Serilog API to add properties, serialize structured data, repeat events in a loop, and so on.

F5!

The screenshot in the introduction shows what the debugger looks like after stopping on a breakpoint and stepping through SmtpMailApp.

The app can do just about anything locally that it can do when hosted in Seq. I'm using the wonderful Papercut SMTP to collect email on my development machine - and I've got mail!

Papercut SMTP app inbox showing an email with the "Hello, {Name}!" event from the earlier source code example.

Getting help

Seq.Apps.Testing is brand new, so this blog post is currently the definitive source for information about it; I'm sure I've left out some details - please let me know in the comments if you have any trouble getting up and running.

Enjoy! 😎

Nicholas Blumhardt

Read more posts by this author.