Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works

Random project

MiniLogger

Logger for Object Pascal

View on GitLab

Anyone may press Interesting, signed in or not. It helps others find this project.

Member rating

No ratings yet.

Sign in to rate this project.

README

Table of contents

[[TOC]]


Introduction

This is just another logger for Object Pascal of which I consider there are many. It is simple and has a few features:

  • using only Free Pascal RTL and FCL
  • using concept of streams
  • streaming to standard output, file and stream assigned by user
  • different kind of messages and options
  • callbacks (can be used to output to visual components or other classes that do not use streaming)
  • conditional compiling to switch between real and dummy implementations
  • zlib License

How to use

  1. Install Free Pascal Compiler and RTL.
  2. Add file uminilogger.pas to your project
  3. Add MINILOG_ENABLE define to your compiler options to enable real implementation instead of dummy. It looks like -dMINILOG_ENABLE as compiler flag.
  4. Create object of class KMiniLogger and use it!

Structure

Here you can find description of everything what exists in uminilogger.pas.

Also you can try ExampleGUI in examples, but you need Lazarus IDE to build it.

Directives

Name Description How to use
MINILOG_ENABLE Enables real implementation instead of dummy. Dummy is just interface, methods do nothing useful. Add flag -dMINILOG_ENABLE to your compiler options. If you use Lazarus: Project Options->Compiler Options->Custom Options->Defines.

Types

Name Type Description
KString string Alias to build in type string, which is alias (at least on my pc) to AnsiString, which is not Unicode. Idea is to add Unicode support in future.
KStringList TStringList Alias to RTL class TStringList, which uses string type. If KString implementation will be changed, then KStringList should be changed as well.
KLogMessageKind enum Enumaration of existing messages
KLogMessages set of enum Set of KLogMessageKind. It used for variable that stores what kind of messages to log.
KLogOption enum Enumaration of existing options
KLogOptions set of enum Set of KLogOption. It used for variable that stores what kind of options are enabled.
KLogNotifyEvent callback Callback for notification events.
KLogRegisterEvent callback Callback for register events. Register event is an event when message is logged (registered). Every kind of message has callback function (see below)
KMiniLoggger class Logger itself

Messages

KLogMessageKind is an enumeration of all existing messages.

KLogMessages = set of KLogMessageKind; is set which used for variable that stores what kind of messages to log.

Name Default behaviour Description
lmkInternal always enabled Internal Logger's message. It can not be used outside of Logger itself. All internals are sended to all assigned streams + standard Error
lmkInfo enabled, optional Information message
lmkWarning enabled, optional Warning message
lmkError enabled, optional Error message
lmkDebug enabled, optional Debug message
lmkFatal enabled, optional Fatal message
lmkUser enabled, optional User defined message

[!note] Difference between message kind Right now there is no difference between various message kinds.

Options

KLogOption is an enumeration of all existing options for Logger.

KLogOptions = set of KLogOption; is set which used for variable that stores what kind of options are enabled.

Name Default Description
kloStdOutput off Enables streaming to standard Output
kloCanStop off Enables possibility to stop Logger at any time. If disabled then logging stops with destructor.
kloFile on Enables streaming to file. If disabled then no file created.
kloFileUniqueName on When enabled, then every log file has a unique name, which contains date and time stamp as file name suffix.
kloFileStreaming on Enables file streaming, so every new message will be written to file immediately. If disabled then all messages will be saved to memory at first and saved to file when object's destructor is called.

[!note] kloCanStop Because Logger is not implemented as singleton, it can be useful to prevent Logger from stop if you made it as global variable

[!caution] Disabling kloFileStreaming Logger saves all messages in memory, but also it has a limit (see SizeMax). If you disable kloFileStreaming and message count >= SizeMax, then all messages in memory will be cleared to continue logging.

Events

KLogNotifyEvent = procedure(Sender : TObject) of object; - callback for notification events. Right now, there are only two type of such events:

  • onStart invoked when Logger's procedure Start is executed;
  • onStop invoked when Logger's procedure Stop is executed. Note: kloCanStop is disabled then onStop NEVER executes.

KLogRegisterEvent = procedure(Sender : TObject; const aKind : KLogMessageKind; const aMsg : KString) of object; - callback for register events. Register event is an event when message is logged (registered). Every kind of message has callback function. Note: you can not assign callback function for internal message.

Event parameters:

  • Sender is a reference to object that invoked an event;
  • aKind is a message kind;
  • aMsg is a message with all applied formatation (maybe it would be better if that was a raw message).

Class KMiniLoggger

That is logger itself.

Public

Description of class KMiniLogger interface: all public routines, properties, variables, constants etc.

Procedures and functions

Constructor & Destructor
constuctor Create;
Creates Logger's object, but do NOT start it. Use Start procedure to start logging. Creates stream to standard Error for internal messages. If stream to standard Error can not be created then exception is raised see TIOStream documentation for more. Also creates journal of type KStringList to save messages in memory.
destructor Destroy; override;
Destroys Logger's object, closes and frees all streams. If stream assigned by user was set as owned by Logger then it will be freed as well. Destructor invokes procedure Stop inside, but OnStop event won't be executed anyway.

Logging routines
procedure SendInfo(const aMsg : KString); overload;
procedure SendInfo(const aFmt : KString; const aArgs : array of const); overload;
Logs(Registers) Information kind of messages.
procedure SendWarning(const aMsg : KString); overload;
procedure SendWarning(const aFmt : KString; const aArgs : array of const); overload;
Logs Warning kind of messages.
procedure SendError(const aMsg : KString); overload;
procedure SendError(const aFmt : KString; const aArgs : array of const); overload;
Logs Error kind of messages.
procedure SendDebug(const aMsg : KString); overload;
procedure SendDebug(const aFmt : KString; const aArgs : array of const); overload;
Logs Debug kind of messages.
procedure SendFatal(const aMsg : KString); overload;
procedure SendFatal(const aFmt : KString; const aArgs : array of const); overload;
Logs Fatal kind of messages.
procedure SendUserMsg(const aMsg : KString); overload;
procedure SendUserMsg(const aFmt : KString; const aArgs : array of const); overload;
Logs User defined kind of messages.

All logging routines have two forms:

  • simple: uses aMsg parameter to store message as string;
  • formatted: uses parameter aFmt - string with placeholders, and parameter aArgs - list of arguments that will replace placeholders. See Free Pascal's procedure Format documentation and wiki for more.

Formatted message looks like: [cMsgTimeStampFmt cMsgTitle[aKind]: <Formatted message>]<LineEnding>, where:

  • cMsgTimeStampFmt is a constant that defines date and time format
  • cMsgTitle[aKind] is an element of array of constants that defines message title depending on its kind
  • <Formatted message> is a message produced by Format(aFmt, aArgs)
  • <LineEnding> depends on platform

[!tip] Example Execution mylogger.SendInfo('%s', ['Information message']); on Linux, gives you next result:

['yyyy mmm dd hh:nn:ss' INFO: Information message]\n, where:

  • yyyy - year (with century)
  • mmm - month (abbreviation)
  • dd - day of month (leading zero)
  • hh - hour (leading zero)
  • nn - minute (leading zero)
  • ss - second (leading zero)

Misc routines
procedure Start;
Starts logging, creates streams to standard Output and file, if corresponding options are enabled.
procedure Stop;
Stops logging, if kloCanStop is enabled. Also destroys all opened streams except std Error. User assigned stream is freed if Logger owns it, otherwise it set to nil.
procedure Assign(aStream : TStream; const aOwner : Boolean = False);
Assigns a user defined stream for logging. aOwner describes who is an owner of assigned stream. Owner is responsible for stream to be freed. aOwner equals True => Logger is aStream's owner

[!caution] Before started! When logging is started you can NOT change any options or assign another user defined stream. That is why you need to set all options before you start logging!

[!note] Start and Stop with File stream If kloCanStop and kloFileUniqueName options are enabled, then every stop closes existing file, and every start creates new one

Properties

Name Type Modes Description
SizeMax Integer read, write Max number of messages that will be stored in memory. When count of messages is equals or bigger than that number all messages in memory will be cleared.
Messages KLogMessages read, write Set of messages to be logged.
Options KLogOptions read, write Set of Logger's options that are enabled.
Started Boolean read Flag that shows if logging is started.
FileSlug KString read, write File's name without extension and suffix. Suffix is used only when kloFileUniqueName is on. If empty then cDefFileSlug constant is used.
FilePath KString read, write File's path, can be relative or absolute. If empty then cDefFilePath constant is used.
FileExt KString read, write File's extension. If empty then cDefFileExt constant is used.
FileName KString read File's name that consists of slug + (suffix, if needed) + extension
FullFileName KString read File's full name: path + name
OnStart KLogNotifyEvent read, write Callback that is invoked when procedure Start is executed
OnStop KLogNotifyEvent read, write Callback that is invoked when procedure Stop is executed
OnLog[Kind] KLogRegisterEvent[KLogMessageKind] read, write Array of callbacks. Message kind is used as an array's index. Every element is invoked when corresponding message is logged e.g. you can assign callback only for Debug messages.
NOTE: you can NOT assign callback for Internal messages.

Private

Description of class KMiniLogger implementation: all private routines, properties, variables, constants etc.

[!note] Private Everything listed in this section are strict private or private

Constants

Name Type Value Description
cDefJournalSizeMax Integer 255 Default max number of messages that can be stored in memory.
cMsgTitle array of KString ('INTERNAL', 'INFO', 'WARNING', 'ERROR', 'DEBUG', 'FATAL', 'USER-DEFINED') Title for every message kind.
cMsgTimeStampFmt KString 'yyyy mmm dd hh:nn:ss' Defines date and time format for logged messages
cDefFilePath KString './Logs/' Default file path
cDefFileSlug KString 'logger' Default file slug
cDefFileExt KString 'log' Default file extension
cFileTimeStampFmt KString 'yyyy-mm-dd-hh-nn-ss' File suffix that used when kloFileUniqueName is on. It defines date and time format for created file.

[!warning] Constants I do not remember exactly what kind of problems are related to such declaration of constants inside of class in Free Pascal. All what I remember that is not right. However I still use this declaration, because I consider it more easy and comfy. That is why, please do not change them outside where they live.

Variables

Name Type Description
mJournal KStringList List of logged messages.
mSizeMax Integer Maximum size of list.
mStdError TIOStream Stream to the standard Error.
mStdOutput TIOStream Stream to the standard Output.
mMessages KLogMessages Set of messages that can be logged.
mOptions KLogOptions Set of enabled options.
mStarted Boolean Flag that shows if logging is started.

Variables associated with file stream

Name Type Description
mStreamFile TFileStream Stream to file
mFileSlug KString File's slug
mFilePath KString File's path
mFileExt KString File's extension

Variables associated with assigned stream

Name Type Description
mStreamUser TStream Stream assigned by user using Assign procedure
mOwnsUserStream Boolean Flag that shows if Logger is the Owner of mStreamUser

Variables associated with events

Name Type Description
mOnStart KLogNotifyEvent Callback that is executed in procedure Start
mOnStop KLogNotifyEvent Callback that is executed in procedure Stop
mOnLog array of KLogRegisterEvent Array of callbacks. Each of them is executed when corresponding message is logged

Procedures and functions

Getters
function GetLogMsgEvent(const aKind : KLogMessageKind) : KLogRegisterEvent;
Returns element of array mOnLog with index aKind. Associated with a property OnLog.
function GetFileName : KString;
Returns file's name that consists of slug + (suffix, if needed) + extension. Associated with a property FileName.
function GetFullFileName : KString;
Returns file's full name: path + name. Associated with a property FullFileName.

Setters
rocedure SetSizeMax(const aValue : Integer);
Sets new maximum size for mJournal. Associated with a property SizeMax.
procedure SetLogMsgEvent(const aKind : KLogMessageKind; aValue : KLogRegisterEvent);
Sets new value to element of array mOnLog with index aKind. Associated with a property OnLog.
procedure SetMessages(const aValue : KLogMessages);
Sets new value for mMessages. Associated with a property Messages. Also always adds lmkInternal.
procedure SetOptions(const aValue : KLogOptions);
Sets new value for mOptions. Associated with a property Options.
procedure SetFileSlug(const aValue : KString);
Sets new value for mFileSlug. Associated with a property FileSlug.
procedure SetFilePath(const aValue : KString);
Sets new value for mFilePath. Associated with a property FilePath. Checks and adds if needed a DirectorySeparator in the end of path.
procedure SetFileExt(const aValue : KString);
Sets new value for mFileExt. Associated with a property FileExt.

Misc routines
procedure DoLog(const aKind : KLogMessageKind; const aFmt : KString; const aArgs : array of const);
Main logging procedure that saves messages in memory and writes them to assigned streams. Also formats messages using Free Pascal's Format and FormatDateTime functions.
procedure SendInternal(const aMsg : string);
Logs Internal kind of message. It used only inside of Logger.
procedure FreeUserStream;
Frees user assigned stream. If mOwnsUserStream is True, then stream is freed, else mStreamUser is set to nil.

F.A.Q.

Q: Why not to use singleton implementation?

A: I just send you to this article Singleton Pattern - Free Pascal Wiki


ToDo Ideas

  • [ ] Add help functionality and information to different kind of messages e.g. pointer address, routine/type name, code line etc.
  • [ ] Add Exceptions, tracing, levels, dumps
  • [ ] Add Unicode (UTF-8) support
  • [ ] Add multithreading support