Catalog · How the catalog works
MiniLogger
Logger for Object Pascal
Anyone may press Interesting, signed in or not. It helps others find 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
- Install Free Pascal Compiler and RTL.
- Add file
uminilogger.pasto your project - Add
MINILOG_ENABLEdefine to your compiler options to enable real implementation instead of dummy. It looks like-dMINILOG_ENABLEas compiler flag. - 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
kloFileStreamingLogger saves all messages in memory, but also it has a limit (see SizeMax). If you disablekloFileStreamingand 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:
onStartinvoked when Logger's procedure Start is executed;onStopinvoked when Logger's procedure Stop is executed. Note:kloCanStopis disabled thenonStopNEVER 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:
Senderis a reference to object that invoked an event;aKindis a message kind;aMsgis 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
aMsgparameter to store message as string; - formatted: uses parameter
aFmt- string with placeholders, and parameteraArgs- 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:
cMsgTimeStampFmtis a constant that defines date and time formatcMsgTitle[aKind]is an element of array of constants that defines message title depending on its kind<Formatted message>is a message produced byFormat(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
kloCanStopandkloFileUniqueNameoptions 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 privateorprivate
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
