Output Handlers
The logger provides the capability of logging to various other output handlers. An output handler is a class that provides a log output method with a parameter that contains output information. The output information contains the timestamp, the value, the log level and a set of pre-formatted strings (such as the name, type and value, based on the TMSLogger.Outputs property) and then saves the information to a file, or sends it to a browser, TCP/IP client. The output handlers support various formats such as plain text and HTML.
Each output handler except for the default TTMSLoggerConsoleOutputHandler class is available in separate units. Each unit name starts with TMSLogging and then specifies which output handler is implemented. To use an output handler, it needs to be registered first. The logger has a set of RegisterOutputHandler* methods that can be used to register or create an instance of an output handler.
An output handler has an Active property, which is true by default and has a set of constructor overloads. The RegisterOutputHandlerClass method will accept a list of parameters that should match the number of parameters in the constructor of the output handler class you wish to create. When you are not sure on the type of parameters, you can take a look at the create signature, or simply create a separate instance of the output handler. When creating a separate instance, it can be registered using the RegisterOutputHandler or RegisterManagedOutputHandler call instead. Using the latter will tell the logger to destroy the output handler instance when the logger instance itself is destroyed. The former will not destroy the output handler.
Each output handler has a procedure LogOutput(const AOutputInformation: TTMSLoggerOutputInformation); that contains the log information.
Some output handlers will automatically strip HTML/XML tags from the message. Mostly the ones which those tags are not relevant, like console output, file output, etc. If you want to prevent an output handler from stripping such tags, set the StripHtml
property to false:
TextOutputHandler.StripHtml := False;
Following are the output handlers that are currently available.
Console Output
Class: TTMSLoggerConsoleOutputHandler at TMSLoggingCore
unit.
The TTMSLoggerConsoleOutputHandler outputs the log information to the console window of the IDE or the log monitor/console of the device (iOS, Android, Mac OSX). Note that this does not output to the regular Windows console. To do that, you should use the Windows Console Output handler.
Windows Console Output
Class name: TTMSLoggerWindowsConsoleOutputHandler at TMSLoggingWindowsConsoleOutputHandler
unit.
The TTMSLoggerWindowsConsoleOutputHandler outputs log messages to the Microsoft Windows console window. It also changes the output color according to the log level.
Text File Output
Class name: TTMSLoggerTextOutputHandler at TMSLoggingTextOutputHandler
unit.
The TTMSLoggerTextOutputHandler outputs the information as plain text to a file.
Sample output:
Event Log Output
Class name: TTMSLoggerEventLogOutputHandler at TMSLoggingEventLogOutputHandler
unit.
The TTMSLoggerEventLogOutputHandler will log the output information to the Windows event log. Creating an instance can be done with the following code:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerEventLogOutputHandler);
Important
The TTMSLoggerEventOutputHandler requires administrator privileges on Windows in order to successfully write an event to the Windows event log. Starting the application without administrator privileges will also log to the event log but will display a message indicating it cannot find the event id linked to the specific event log.
Sample output:
CSV File Output
Class name: TTMSLoggerCSVOutputHandler at TMSLoggingCSVOutputHandler
unit.
The TTMSLoggerCSVOutputHandler outputs the information as plain text to a CSV file, separated by a delimiter, which can be configured with a separate property.
Sample output:
TCP Output
Class name: TTMSLoggerTCPOutputHandler at TMSLoggingTCPOutputHandler
unit.
The TTMSLoggerTCPOutputHandler is a server that sends the output information to each connected TCP/IP client. The client application can implement its own TCP/IP client read buffer instructions but an instance of TTMSLoggerTCPClient, which already implements this, can also be chosen. The TTMSLoggerTCPClient has an OnReceivedOutputInformation event is triggered whenever output information is received.
Registering a TTMSLoggerTCPOutputHandler is similar to the TTMSLoggerBrowserOutputHandler, but does not have an option to change the HTML formatting viewer.
The sample output screenshot is a TCP Client that implements this technique and serves as a viewer. The executable is available in the installation directory and is supported for Windows and Mac OSX.
Sample output:
Memo Output
Class name: TTMSLoggerMemoOutputHandler at Vcl.TMSLoggingMemoOutputHandler
unit.
The TTMSLoggerMemoOutputHandler outputs log messages to a TMemo VCL control, in a thread-safe way. It's useful to allow the end-user to quickly visualize log information in the VCL application.
The Create constructor requires you to pass the instance of TMemo that will receive the messages.
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerMemoOutputHandler, [Memo1]);
Browser Output
Class name: TTMSLoggerBrowserOutputHandler at TMSLoggingBrowserOutputHandler
unit.
The TTMSLoggerBrowserOutputHandler is a server that sends the output information to each connected client browser. To register a TTMSLoggerBrowserOutputHandler, the following code can be used:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerBrowserOutputHandler, [Self]);
After registering it, navigating to the IP-address of the server, or the localhost with the default port of 8888 will display an empty HTML table. As soon as the logger logs a value, the table will be updated. To change the port number, the parameter list can be modified as demonstrated in the code below.
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerBrowserOutputHandler, [Self, 1234]);
Optionally, the HTML table view can be changed to an HTML plain view by specifying an additional parameter:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerBrowserOutputHandler, [Self, 1234, TValue.From(ohmPlain)]);
Available constructors:
constructor Create(const AOwner: TComponent); reintroduce; overload; virtual;
constructor Create(const AOwner: TComponent; const APort: Integer); reintroduce; overload; virtual;
constructor Create(const AOwner: TComponent; const APort: Integer; const AMode: TTMSLoggerHTMLOutputHandlerMode); reintroduce; overload; virtual;
constructor Create(const AOwner: TComponent; const APort: Integer; const AMode: TTMSLoggerHTMLOutputHandlerMode; const ATitle: string); reintroduce; overload; virtual;
AOwner: A component to serve as the owner for internal components. Usually Self.
APort: The TCP port used to create the TCP/IP listener
AMode: The format data will be output.
ATitle: The HTML page title.
Example:
var
Handler: TTMSLoggerBrowserOutputHandler;
begin
Handler := TTMSLoggerBrowserOutputHandler.Create(Self);
TMSLogger.RegisterManagedOutputHandler(Handler);
Handler.Title := 'Browser Logging (Custom Title)';
Sample output:
HTML Output
Class name: TTMSLoggerHTMLOutputHandler at TMSLoggingHTMLOutputHandler
unit.
The TTMSLoggerHTMLOutputHandler is based on the same output as the TTMSLoggerBrowserOutputHandler but saves the output information to a file instead. The constructor overloads for this class are different than the ones for the TTMSLoggerBrowserOutputHandler. To know exactly which parameters to pass to the TMSLogger.RegisterOutputHandlerClass, you can simply type "TTMSLoggerHTMLOutputHandler.Create(" which will show a list of constructor overloads.
Available constructors:
constructor Create(const AFileName: string); overload; override;
constructor Create(const AFileName: string; ADataName: string); reintroduce; overload; virtual;
constructor Create(const AFileName: string; ADataName: string; AMode: TTMSLoggerHTMLOutputHandlerMode); reintroduce; overload; virtual;
constructor Create(const AFileName: string; ADataName: string; AMode: TTMSLoggerHTMLOutputHandlerMode; const ATitle: string); reintroduce; overload; virtual;
AFileName: The name of .html file to be generated.
ADataName: The name of .js file to be generated.
AMode: The format data will be output.
ATitle: The HTML page title.
Examples:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerHTMLOutputHandler, ['.\demo_table.html', 'demo_table.js', TValue.From(ohmTable), 'Table logging']);
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerHTMLOutputHandler, ['.\demo_plain.html', 'demo_plain.js', TValue.From(ohmPlain), 'Plain logging']);
Datasource Output
Class name: TTMSLoggerDataSourceOutputHandler at TMSLoggingDataSourceOutputHandler
unit.
The TTMSLoggerDataSourceOutputHandler is capable of connecting to a datasource via the register method demonstrated in the code below.
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerDataSourceOutputHandler, [DataSource1]);
The result of the registration returns an instance of TTMSLoggerDataSourceOutputHandler which contains a Fields property to setup the field names to connect to via the datasource parameter. By default these fields are already prefilled with property name as a field name.
Aurelius Output
Class name: TTMSLoggerAureliusOutputHandler at TMSLoggingAureliusOutputHandler
unit.
The TTMSLoggerAureliusOutputHandler connects via an Aurelius IDBConnectionPool interface to send logging outputs to a dataset connected via TMS Aurelius. The process of setting up a connection is simple as demonstrated in the code below.
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerAureliusOutputHandler, [TValue.From<IDBConnectionPool>(pool)]);
Slack Output
Class name: TTMSLoggerSlackWebhookOutputHandler at TMSLoggingSlackOutputHandler
unit.
The TTMSLoggerSlackWebhookOutputHandler outputs log messages to a Slack channel through an incoming webhook. The incoming webhook is a Slack feature which provides you a unique URL that is used to post messages to a specific channel in your workplace.
The Create constructor requires you to pass the incoming webhook URL:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerSlackWebhookOutputHandler, ['https://hooks.slack.com/services/ABCDEFG/ABCDEFG/hajsdfhkadsfjbXBAHASQW']);
Discord Output
Class name: TTMSLoggerDiscordWebhookOutputHandler at TMSLoggingDiscordOutputHandler
unit.
The TTMSLoggerDiscordWebhookOutputHandler outputs log messages to a Discord channel through an incoming webhook. The incoming webhook is a Discord feature which provides you a unique URL that is used to post messages to a specific channel in your workplace.
The Create constructor requires you to pass the incoming webhook URL:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerDiscordWebhookOutputHandler, ['https://discord.com/api/webhooks/0000000000/abcdefgh']);
Exceptionless Output
Class name: TTMSLoggerExceptionlessOutputHandler at VCL.TMSLoggingExceptionlessOutputHandler
(for VCL) or FMX.TMSLoggingExceptionlessOutputHandler
(for FMX) or FNC.TMSLoggingExceptionlessOutputHandler
(for FNC) unit.
The TTMSLoggerExceptionlessOutputHandler connects via the TAdvExceptionless (VCL) or TTMSFMXCloudExceptionless (FMX) or TTMSFNCCloudExceptionless (FNC) non-visual component. When registering this output handler, the log statements are send to the Exceptionless server which can be monitored through the dashboard service at https://exceptionless.com. This output handler is not pre-installed, and requires the TMS Cloud Pack for VCL and/or the TMS Cloud Pack for FMX and/or the TMS Cloud Pack for FNC installed. To start working with TTMSLoggerExceptionlessOutputHandler add the unit for the framework you are using in your application and add the following to initialize:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerExceptionlessOutputHandler, [AdvExceptionLess1, 'AProjectID']);
or
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerExceptionlessOutputHandler, [TMSFMXCloudExceptionLess1, 'AProjectID']);
AProjectID is a string that needs to be replaced after the Exeptionless cloud component has retrieved its projects. The output handler requires an already authenticated Exceptionless cloud component in order to function properly.
myCloudData Output
Class name: TTMSLoggerMyCloudDataOutputHandler at VCL.TMSLoggingMyCloudDataOutputHandler
or FMX.TMSLoggingMyCloudDataOutputHandler
unit.
The TTMSLoggerMyCloudDataOutputHandler connects via the TAdvMyCloudData (VCL) or TTMSFMXCloudMyCloudData (FMX) non-visual component. When registering this outputhandler, the log statements are send to the MyCloudData server. This outputhandler is not pre-installed, and requires the TMS Cloud Pack for VCL and/or the TMS Cloud Pack for FMX installed. To start working with TTMSLoggerMyCloudDataOutputHandler add the unit for the framework you are using in your application and add the following to initialize:
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerMyCloudDataOutputHandler, [AdvMyCloudData1, 'ATableName']);
or
TMSLogger.RegisterOutputHandlerClass(TTMSLoggerMyCloudDataOutputHandler, [TMSFMXCloudMyCloudData1, 'ATableName']);
The ATableName string parameter is optional. By default the output handler will try to create a table called 'MyCloudDataLogging' and add Meta data through the MetaData property. This property can be accessed after registering the TTMSLoggerMyCloudDataOutputHandler which returns an instance. The MetaData properties are initialized with a default value that can be overridden. Below is a sample screenshot after following the above steps. The default values for the table and Meta data names are used in tis sample.
Custom Output
If the default output handlers are
not sufficient, the logger supports implementing a custom output
handler. The TTMSLoggerBaseOutputHandler
and TTMSLoggerCustomFileOutputHandler
class provides a set of procedures to easily implement a custom output
handler.
The TTMSLoggerCustomFileOutputHandler class
inherits from TTMSLoggerBaseOutputHandler
and adds support for logging to a file. The functionality to concatenate
the output information and strip the HTML is located in the
TMSLoggingUtils
unit, and can be access
with TTMSLoggerUtils class functions and
procedures. Below is a sample that outputs the log information inside a
TMemo based on the TTMSLoggerBaseOutputHandler:
Note
The code below is just for learning purposes. It's simple and not thread-safe to make it easier to understand. If you want log to a TMemo control, use the built-in Memo Output handler.
type
TMyOutputHandler = class(TTMSLoggerBaseOutputHandler)
private
FMemo: TMemo;
protected
procedure Clear; override;
procedure LogOutput(const AOutputInformation: TTMSLoggerOutputInformation); override;
public
constructor Create(const AMemo: TMemo); reintroduce; virtual;
property Memo: TMemo read FMemo write FMemo;
end;
implementation
{ TMyOutputHandler }
procedure TMyOutputHandler.Clear;
begin
inherited;
if Assigned(Memo) then
Memo.Lines.Clear;
end;
constructor TMyOutputHandler.Create(const AMemo: TMemo);
begin
inherited Create;
FMemo := AMemo;
end;
procedure TMyOutputHandler.LogOutput(const AOutputInformation: TTMSLoggerOutputInformation);
begin
inherited;
if Assigned(Memo) then
Memo.Lines.Add(TTMSLoggerUtils.StripHTML(
TTMSLoggerUtils.GetConcatenatedLogMessage(AOutputInformation, True)));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TMSLogger.RegisterOutputHandlerClass(TMyOutputHandler, [Memo1]);
end;