delphimvcframework/sources/MVCFramework.Logger.pas

278 lines
7.3 KiB
ObjectPascal
Raw Normal View History

// ***************************************************************************
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2016 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
// ***************************************************************************
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// *************************************************************************** }
2015-12-22 12:38:17 +01:00
2013-10-30 00:48:23 +01:00
unit MVCFramework.Logger;
interface
uses
LoggerPro,
2013-10-30 00:48:23 +01:00
System.SysUtils;
const
LOGGERPRO_TAG = 'dmvcframework';
2013-10-30 00:48:23 +01:00
type
2016-11-27 23:17:20 +01:00
TLogLevel = (levDebug = 0, levNormal = 1, levWar = 2, levError = 3, levException = 4);
2013-10-30 00:48:23 +01:00
function LogLevelAsString(ALogLevel: TLogLevel): string;
2016-11-27 23:17:20 +01:00
procedure Log(AMessage: string); overload;
procedure LogD(AMessage: string); overload;
procedure LogI(AMessage: string);
procedure LogW(AMessage: string);
procedure LogE(AMessage: string);
2013-10-30 00:48:23 +01:00
procedure Log(LogLevel: TLogLevel; const AMessage: string); overload;
procedure LogEnterMethod(const AMethodName: string);
procedure LogExitMethod(const AMethodName: string);
procedure LogException(const AException: Exception; const AMessage: string = '');
2016-11-27 23:17:20 +01:00
procedure LogEx(AException: Exception; AMessage: string = ''); deprecated 'Use LogException or Log.Error';
// direct access to loggerpro logger
function Log: ILogWriter; overload;
procedure SetDefaultLogger(const aLogWriter: ILogWriter);
procedure InitializeDefaultLogger;
{ @abstract(Use only inside DLL because dll unloading is not a safe place to shutdown threads, so call this before unload DLL)
Use this also in ISAPI dll. Check the @code(loggerproisapisample.dll) sample
}
procedure ReleaseGlobalLogger;
2013-10-30 00:48:23 +01:00
var
LogLevelLimit: TLogLevel = TLogLevel.levNormal;
implementation
uses
System.Classes, LoggerPro.FileAppender;
var
_lock: TObject;
_DefaultLogger: ILogWriter;
2016-11-27 23:17:20 +01:00
_LevelsMap: array [TLogLevel.levDebug .. TLogLevel.levException] of LoggerPro.TLogType =
(
(
TLogType.Debug
),
(
TLogType.Info
),
(
TLogType.Warning
),
2016-11-27 23:17:20 +01:00
(
TLogType.Error
),
(
TLogType.Error
)
);
function Log: ILogWriter;
begin
2016-11-27 23:17:20 +01:00
if _DefaultLogger = nil then
begin
SetDefaultLogger(nil);
end;
Result := _DefaultLogger;
end;
2013-10-30 00:48:23 +01:00
function LogLevelAsString(ALogLevel: TLogLevel): string;
begin
case ALogLevel of
levNormal:
Result := ''; // normal is '' because is more readable
levWar:
Result := 'WARNING';
levError:
Result := 'ERROR';
levException:
Result := 'EXCEPTION';
else
Result := 'UNKNOWN';
2013-10-30 00:48:23 +01:00
end;
end;
procedure LogEx(AException: Exception; AMessage: string = '');
begin
2016-11-27 23:17:20 +01:00
LogEx(AException, AMessage);
2013-10-30 00:48:23 +01:00
end;
procedure LogW(AMessage: string);
begin
2016-11-27 23:17:20 +01:00
Log.Warn(AMessage, LOGGERPRO_TAG);
2013-10-30 00:48:23 +01:00
end;
procedure LogE(AMessage: string);
begin
2016-11-27 23:17:20 +01:00
Log.Error(AMessage, LOGGERPRO_TAG);
2013-10-30 00:48:23 +01:00
end;
procedure LogException(
const AException: Exception;
const AMessage: string);
2013-10-30 00:48:23 +01:00
begin
2016-11-27 23:17:20 +01:00
Log.Error(Format('[%s] %s (Custom message: "%s")', [AException.ClassName,
AException.Message, AMessage]), LOGGERPRO_TAG);
2013-10-30 00:48:23 +01:00
end;
procedure LogEnterMethod(const AMethodName: string);
2013-10-30 00:48:23 +01:00
begin
2016-11-27 23:17:20 +01:00
LogI('>> ' + AMethodName);
2013-10-30 00:48:23 +01:00
end;
procedure LogExitMethod(const AMethodName: string);
2013-10-30 00:48:23 +01:00
begin
2016-11-27 23:17:20 +01:00
LogI('<< ' + AMethodName);
2013-10-30 00:48:23 +01:00
end;
procedure Log(LogLevel: TLogLevel; const AMessage: string);
begin
case _LevelsMap[LogLevel] of
TLogType.Debug:
2016-11-27 23:17:20 +01:00
Log.Debug(AMessage, LOGGERPRO_TAG);
TLogType.Info:
2016-11-27 23:17:20 +01:00
Log.Info(AMessage, LOGGERPRO_TAG);
TLogType.Warning:
2016-11-27 23:17:20 +01:00
Log.Warn(AMessage, LOGGERPRO_TAG);
TLogType.Error:
2016-11-27 23:17:20 +01:00
Log.Error(AMessage, LOGGERPRO_TAG);
else
raise Exception.Create('Invalid LOG LEVEL! Original message was: ' + AMessage);
end;
2013-10-30 00:48:23 +01:00
end;
2013-10-30 00:48:23 +01:00
procedure Log(AMessage: string); overload;
2016-11-27 23:17:20 +01:00
begin
LogI(AMessage);
end;
procedure LogI(AMessage: string); overload;
begin
Log.Info(AMessage, LOGGERPRO_TAG);
end;
2016-11-27 23:17:20 +01:00
procedure LogD(AMessage: string); overload;
begin
Log.Debug(AMessage, LOGGERPRO_TAG);
end;
procedure SetDefaultLogger(const aLogWriter: ILogWriter);
begin
2016-11-27 23:17:20 +01:00
if _DefaultLogger = nil then
begin
TMonitor.Enter(_lock); // double check here
try
if _DefaultLogger = nil then
2013-10-30 00:48:23 +01:00
begin
2016-11-27 23:17:20 +01:00
if aLogWriter <> nil then
begin
_DefaultLogger := aLogWriter;
Log.Info('Custom Logger initialized', LOGGERPRO_TAG);
end
else
begin
InitializeDefaultLogger;
Log.Info('Default Logger initialized', LOGGERPRO_TAG);
end;
2013-10-30 00:48:23 +01:00
end;
2016-11-27 23:17:20 +01:00
finally
TMonitor.Exit(_lock);
end;
2013-10-30 00:48:23 +01:00
end;
end;
procedure InitializeDefaultLogger;
2013-10-30 00:48:23 +01:00
begin
2016-11-27 23:17:20 +01:00
{ This procedure must be called in a synchronized context
(Normally only SetDefaultLogger should be the caller) }
if not Assigned(_DefaultLogger) then
begin
_DefaultLogger := BuildLogWriter([TLoggerProFileAppender.Create(5, 2000, 'logs')]);
end;
2013-10-30 00:48:23 +01:00
end;
procedure ReleaseGlobalLogger;
begin
if _DefaultLogger <> nil then
begin
TMonitor.Enter(_lock);
try
if _DefaultLogger <> nil then // double check
begin
_DefaultLogger := nil;
end;
finally
TMonitor.Exit(_lock);
end;
end;
end;
initialization
_lock := TObject.Create;
{ The TLoggerProFileAppender has its defaults defined as follows:
DEFAULT_LOG_FORMAT = '%0:s [TID %1:-8d][%2:-10s] %3:s [%4:s]';
DEFAULT_MAX_BACKUP_FILE_COUNT = 5;
DEFAULT_MAX_FILE_SIZE_KB = 1000;
You can override these dafaults passing parameters to the constructor.
Here's some configuration examples:
@longcode(#
// Creates log in the same exe folder without PID in the filename
_Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
[TFileAppenderOption.LogsInTheSameFolder])]);
// Creates log in the AppData/Roaming with PID in the filename
_Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
[TFileAppenderOption.IncludePID])]);
// Creates log in the same folder with PID in the filename
_Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
[TFileAppenderOption.IncludePID])]);
#)
}
// Creates log in the ..\..\ folder without PID in the filename
// DefaultDMVCFrameworkLogger := BuildLogWriter([TLoggerProFileAppender.Create(10, 5)]);
// Create logs in the exe' same folder
// _Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5)]);
// Creates log in the AppData/Roaming with PID in the filename
// _Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
// [TFileAppenderOption.IncludePID])]);
// Creates log in the same folder with PID in the filename
// _Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
// [TFileAppenderOption.IncludePID])]);
finalization
_lock.Free;
2013-10-30 00:48:23 +01:00
end.