Using Custom Protocols with the SmartInspect Libraries

Closing Words


Beginning with SmartInspect 2.0, the SmartInspect libraries provide the functionality to register and use your own custom protocols. In the SmartInspect concept protocols are responsible for transporting the logging data. Some protocols like the file or TCP protocols are already built-in and this article explains how to add your own. It introduces the basic concepts and provides a working implementation of a custom protocol which is capable of sending the logging data via email.


Implementing and registering custom protocols consists of four simple steps. At first, we need to declare a class which derives from the Protocol class (TSiProtocol in Delphi), then implement the abstract methods, proceed with handling the protocol options and finally register the new protocol class.

The following sections explain the individual steps in detail. The examples are written in C# and use the SmartInspect .NET library. The concept is the same with the Delphi and Java libraries but the implementations use a different syntax, of course.

Declaring a custom protocol

Declaring a custom protocol is as simple as choosing a suitable name for our class and deriving it from the Protocol class. Let's pretend we are building a custom protocol for sending logging data via email. A good name for this protocol would be MailProtocol. The first step of implementing our own protocol would thus look like:

using Gurock.SmartInspect;

public class MailProtocol: Protocol

Implementing the abstract methods

Each custom protocol at least needs to implement the abstract methods to write a log packet and to connect to and disconnect from the protocol specific destination. Additionally, each protocol has a name which needs to be exposed with a property (getter method in Delphi and Java). Put together, a minimal implementation thus looks like:

protected override string Name
    get { return "mail"; }

protected override void InternalConnect()

protected override void InternalWritePacket(Packet packet)

protected override void InternalDisconnect()

Let's leave the methods empty here. A concrete implementation which is capable of sending real email can be downloaded at the end of this article.

Handling protocol options

Protocol options influence the runtime behavior of protocols. They can be specified as a comma separated list of key/value pairs in the connections string. Protocol options have a name, type and usually also a default value. As an example, when configuring the SmartInspect .NET library to log to a file and using a custom log file name, one could set the connections string like this:

SiAuto.Si.Connections = "file(filename=mylog.sil)";

To process our own protocol options, we need to do two things. At first we need to publish the names of the options we are willing to accept and process. This can be done by overriding the IsValidOption method in our protocol class and returning true for each option we support. When overriding the IsValidOption method, it is important to call the IsValidOption method of the base protocol class in order to recognize the options common to all protocols (like the backlog functionality, for example).

Let's pretend we provide options for specifying the SMTP server and port as well as for the receiver and sender email addresses:

protected override bool IsValidOption(string name)
        name.Equals("host") ||    /* SMTP server host */
        name.Equals("port") ||    /* Port of SMTP server */
        name.Equals("to") ||      /* Receiver address */
        name.Equals("from") ||    /* Sender address */
        base.IsValidOption(name); /* Handle common options */

The second part of the option handling process is the actual option loading. The intended way to do this is to override the virtual LoadOptions method and call the provided option query methods like GetStringOption, GetIntegerOption or GetBooleanOption. Similar to the IsValidOption method, we need to call the base method to load the common protocol options:

protected override void LoadOptions()
    base.LoadOptions(); /* Load common options */
    this.fHost = GetStringOption("host", null);
    this.fPort = GetIntegerOption("port", 25);
    this.fTo = GetStringOption("to", null);
    this.fFrom = GetStringOption("from", null);

Registering the new protocol

After implementing the new protocol class, all that's left to do is to register the new protocol. This is done with a single line of code. We just need to pass the name and type of the new protocol to the static RegisterProtocol method of the ProtocolFactory class:

ProtocolFactory.RegisterProtocol("mail", typeof(MailProtocol));

And once the new protocol has been registered it can be specified in the connections string like any other built-in protocol:

/* Build connections string */
ConnectionsBuilder builder = new ConnectionsBuilder();
builder.AddOption("host", /* SMTP server goes here */);
builder.AddOption("to", /* Receiver address .. */);
builder.AddOption("from", /* Sender address .. */);

/* Assign connections and enable logging */
SiAuto.Si.Connections = builder.Connections;
SiAuto.Si.Enabled = true;

Closing Words

Implementing and registering custom protocols isn't that hard and can be very helpful to extend the built-in functionalities of SmartInspect. Besides the mail protocol of this article, custom protocols for publishing logging data via SMS/RSS feeds or uploading logs to a FTP or HTTP server come to my mind. As usual, if you have any questions about this topic, feel free to contact me at [email protected].

MailProtocol.cs (9 KB)

Try SmartInspect

Get started in minutes and try SmartInspect free for 30 days.

Try SmartInspect