Blog

All Blog Posts  |  Next Post  |  Previous Post

Clever JavaScript techniques exploited for clever server logging in web apps

Tuesday, September 3, 2024

TMS Software Delphi  Components

Everywhere in the world, enthousiast Delphi developers create all sorts of projects with TMS WEB Core combined with all kinds of backend technology like TMS XData, RAD Server, .NET Core, WebBroker, PHP, ... and we enjoy being in touch with our customers, see what each of you is doing, assist in the process of creating Delphi web apps and also regularly learning from our users as well.

This is particularly the case with the code submitted by our TMS WEB Core user Walter Weyers. Walter came up with a very smart and very well written class and component to replace browser console logging by server logging (to a PHP server in this case). The nice thing is that via this blog article, you can not only learn from the genius technique presented here, but Walter offers the created component with full source code for free for your own use! 

A very smart idea taken to a class

But first things first! The genius idea! Well, if you have been a bit into TMS WEB Core development, you have without a doubt resorted to console logging to follow what is happening in your web application in the browser console (open it by pressing F12). Just like sometimes we use this technique in VCL application development to follow what is happening in our apps by using OutputDebugString(), the browser is offering the console object and this has methods console.log(), console.warn(), console.error(), ...  The convenience of the console functions is that we can throw in whatever type of parameter and whatever number of parameter. The browser console tries to present it as good as possible in the browser console. 

And now the trick!

Suppose that we want to override a function like console.log() and replace it with our own method? Yes, it is possible to do this in the browser!  We need a little bit of JavaScript for this though but the essential part comes down to:
// save the reference to the default console.log function
const originalConsoleLog = console.log;

// assign our new function to it
console.log = function() {
       // Output to the "real" console calling the original function we had saved a reference to
       originalLog.apply(console, arguments);
       // do whatever we want ourselves with this call
       OurFunction(arguments);
       }
Note that arguments is an array of all the possible multiple arguments passed to the console.log() function.
This is at the core of the TServerLog class that Walter created. In its constructor, it will override the console.log, console.info,  console.warn and console.error browser methods. In the override, it will take the arguments, convert these to a JSON string and post these to a server URL where the server can store all the log information.


The class & component interface

Walter introduces the TServerLog Class, the class that manages the logging operations, configuration, and communication with the web worker. The web worker is an internal background task that processes log messages, sends them to the server and handles retries on failures. In this class, the console's log, info, warn, and error methods are overridden to capture messages and send them to the web worker. In case the developer still wants to send messages only to the local browser console and not to the server, the class provides methods ConsoleLog, ConsoleInfo, ConsoleWarn, ConsoleError that directly calls the original browser console functions, bypassing to send the information to the server. The web worker posts error messages back to the main thread if the log submission fails after a defined number of retries. In addition, sending to the server will be stopped (Enabled=False), while the output to the console continues.
TServerLog is a class but a component wrapper for this class TServerLogger was created that allows to use this functionality directly from a component dropped on the form. 


Usage

1. Create an instance of TServerLog, specifying the log file name, server URL, send interval, and buffer size.
2. Use the provided methods (ConsoleLog, ConsoleInfo, ConsoleWarn, ConsoleError) to log messages directly to the console without sending them to the server.
3. The logs captured by the overridden console methods are automatically batched and sent to the server at the specified interval or when the buffer size is exceeded.
4. The web worker handles the actual sending of log messages and retries in case of failures, notifying the main thread of any errors.

Example:
  
var Logger: TServerLog;

begin
  Logger := TServerLog.Create('MyLogfile', 'LogIt.php', 3, 1000);
  
  Logger.ConsoleLog('This is a console-only log message');
  Logger.ConsoleError('This is a console-only error message');
  
  console.log('This log is written to both the console and the server');
  console.error('This error is written to both the console and the server');
  
  // ...
  Logger.Free;
end;

Server

For this example, Walter offered a PHP script that handles the incoming HTTP POST requests. As this is a simple HTTP POST handler, this server script could have been written in several other technologies, like TMS XData, .NET core, Next.js etc...
We leave it as an excercise to the user to come up with the equivalent server code in other languages / frameworks. 


Get started

Download this free class & component as well as demo application offered by Walter Weyers here and take advantage of this innovative & creative technique to do server logging in TMS WEB Core apps. Apart from TMS WEB Core, Delphi and a server that can handle HTTP POST requests via PHP scripts, there are no other prerequisites. 

And of course, a big thank you and shout out to Walter Weyers for this wonderful & smart component!









Bruno Fierens




This blog post has not received any comments yet.



Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post