2016-06-22 17:49:16 +02:00
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Delphi MVC Framework
|
|
|
|
//
|
2024-01-02 17:04:27 +01:00
|
|
|
// Copyright (c) 2010-2024 Daniele Teti and the DMVCFramework Team
|
2016-06-22 17:49:16 +02:00
|
|
|
//
|
|
|
|
// 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;
|
|
|
|
|
2017-03-23 18:51:25 +01:00
|
|
|
{$I dmvcframework.inc}
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2017-03-23 18:51:25 +01:00
|
|
|
System.Classes,
|
|
|
|
System.SysUtils,
|
|
|
|
MVCFramework.Commons,
|
2022-10-20 17:29:04 +02:00
|
|
|
System.Diagnostics,
|
2016-09-06 10:30:52 +02:00
|
|
|
LoggerPro,
|
2017-03-23 18:51:25 +01:00
|
|
|
LoggerPro.FileAppender;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
const
|
|
|
|
LOGGERPRO_TAG = 'dmvcframework';
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
type
|
2017-09-23 15:03:07 +02:00
|
|
|
TLogLevel = (levDebug = 0, levNormal = 1, levWarning = 2, levError = 3, levException = 4);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
{$IF Defined(SYDNEYORBETTER)}
|
|
|
|
|
|
|
|
Profiler = record
|
|
|
|
private
|
|
|
|
fMessage: string;
|
|
|
|
fStopWatch: TStopWatch;
|
|
|
|
fIndent: string;
|
|
|
|
public
|
|
|
|
class operator Finalize(var Dest: Profiler);
|
|
|
|
constructor Start(const Message: string); overload;
|
|
|
|
constructor Start(const Message: string; const Params: array of TVarRec); overload;
|
|
|
|
constructor Start(const Message: string; const Params: array of TVarRec; const TAG: String); overload;
|
|
|
|
class var ProfileLogger: ILogWriter;
|
|
|
|
class var LoggerTag: String;
|
2023-04-06 14:47:01 +02:00
|
|
|
class var WarningThreshold: UInt32;
|
|
|
|
class var LogsOnlyIfOverThreshold: Boolean;
|
2022-10-20 17:29:04 +02:00
|
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
|
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;
|
2019-03-05 20:55:37 +01:00
|
|
|
procedure Log(AObject: TObject); overload;
|
|
|
|
|
2016-11-27 23:17:20 +01:00
|
|
|
procedure LogD(AMessage: string); overload;
|
2019-03-05 20:55:37 +01:00
|
|
|
procedure LogD(AMessage: TObject); overload;
|
|
|
|
|
|
|
|
procedure LogI(AMessage: string); overload;
|
|
|
|
procedure LogI(AObject: TObject); overload;
|
|
|
|
|
|
|
|
procedure LogW(AMessage: string); overload;
|
|
|
|
procedure LogW(AObject: TObject); overload;
|
|
|
|
|
2016-11-27 23:17:20 +01:00
|
|
|
procedure LogE(AMessage: string);
|
2024-01-24 00:14:26 +01:00
|
|
|
|
|
|
|
procedure LogF(AMessage: string);
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
procedure Log(LogLevel: TLogLevel; const AMessage: string); overload;
|
2021-12-27 10:13:23 +01:00
|
|
|
|
|
|
|
procedure LogException(const E: Exception; const AMessage: String);
|
|
|
|
|
2016-09-27 14:22:17 +02:00
|
|
|
procedure LogEnterMethod(const AMethodName: string);
|
|
|
|
procedure LogExitMethod(const AMethodName: string);
|
2016-09-06 10:30:52 +02:00
|
|
|
|
|
|
|
// direct access to loggerpro logger
|
|
|
|
function Log: ILogWriter; overload;
|
|
|
|
|
|
|
|
procedure SetDefaultLogger(const aLogWriter: ILogWriter);
|
|
|
|
procedure InitializeDefaultLogger;
|
2016-09-27 14:33:51 +02:00
|
|
|
{ @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
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
procedure InitThreadVars;
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
var
|
|
|
|
LogLevelLimit: TLogLevel = TLogLevel.levNormal;
|
2024-01-24 00:14:26 +01:00
|
|
|
UseConsoleLogger: Boolean = True;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2019-03-05 20:55:37 +01:00
|
|
|
uses
|
2024-01-24 00:14:26 +01:00
|
|
|
{$IF Defined(MSWINDOWS)}
|
|
|
|
LoggerPro.ConsoleAppender,
|
|
|
|
{$ELSE}
|
2024-02-14 18:02:25 +01:00
|
|
|
{$IF Not Defined(MOBILE)}
|
|
|
|
LoggerPro.SimpleConsoleAppender, //only for linux
|
|
|
|
{$ENDIF}
|
2024-01-23 17:19:48 +01:00
|
|
|
{$ENDIF}
|
2024-01-23 17:25:32 +01:00
|
|
|
LoggerPro.Renderers,
|
2019-05-02 17:38:57 +02:00
|
|
|
System.IOUtils,
|
|
|
|
MVCFramework.Serializer.JsonDataObjects,
|
|
|
|
MVCFramework.DuckTyping;
|
2019-03-05 20:55:37 +01:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
{$IF Defined(SYDNEYORBETTER)}
|
2022-12-06 16:10:55 +01:00
|
|
|
threadvar
|
2022-10-20 17:29:04 +02:00
|
|
|
gIndent: NativeUInt;
|
|
|
|
gReqNr: NativeUInt;
|
2022-12-06 16:10:55 +01:00
|
|
|
|
|
|
|
const
|
|
|
|
PROFILER_LOG_TYPE: array [false..true] of TLogType = (TLogType.Info, TLogType.Warning);
|
2022-10-20 17:29:04 +02:00
|
|
|
{$ENDIF}
|
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
var
|
2022-12-06 16:10:55 +01:00
|
|
|
gLock: TObject;
|
|
|
|
gDefaultLogger: ILogWriter;
|
|
|
|
gLevelsMap: array [TLogLevel.levDebug .. TLogLevel.levException] of LoggerPro.TLogType = (
|
2016-09-06 10:30:52 +02:00
|
|
|
(
|
|
|
|
TLogType.Debug
|
|
|
|
),
|
|
|
|
(
|
|
|
|
TLogType.Info
|
|
|
|
),
|
|
|
|
(
|
|
|
|
TLogType.Warning
|
|
|
|
),
|
2016-11-27 23:17:20 +01:00
|
|
|
(
|
|
|
|
TLogType.Error
|
|
|
|
),
|
2016-09-06 10:30:52 +02:00
|
|
|
(
|
|
|
|
TLogType.Error
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
function Log: ILogWriter;
|
|
|
|
begin
|
2022-12-06 16:10:55 +01:00
|
|
|
if gDefaultLogger = nil then
|
2022-10-20 17:29:04 +02:00
|
|
|
begin
|
|
|
|
SetDefaultLogger(nil);
|
|
|
|
end;
|
2016-11-27 23:17:20 +01:00
|
|
|
|
2022-12-06 16:10:55 +01:00
|
|
|
Result := gDefaultLogger;
|
2016-09-06 10:30:52 +02:00
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
function LogLevelAsString(ALogLevel: TLogLevel): string;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
case ALogLevel of
|
|
|
|
levNormal:
|
|
|
|
Result := ''; // normal is '' because is more readable
|
|
|
|
levWarning:
|
|
|
|
Result := 'WARNING';
|
|
|
|
levError:
|
|
|
|
Result := 'ERROR';
|
|
|
|
levException:
|
|
|
|
Result := 'EXCEPTION';
|
|
|
|
else
|
|
|
|
Result := 'UNKNOWN';
|
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
|
|
|
|
2019-03-05 20:55:37 +01:00
|
|
|
function ObjectToJSON(const AObject: TObject): String;
|
|
|
|
var
|
|
|
|
lSer: TMVCJsonDataObjectsSerializer;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
lSer := TMVCJsonDataObjectsSerializer.Create;
|
|
|
|
try
|
|
|
|
if TDuckTypedList.CanBeWrappedAsList(AObject) then
|
|
|
|
begin
|
|
|
|
Result := '[' + AObject.QualifiedClassName + '] ' + lSer.SerializeCollection(AObject);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Result := '[' + AObject.QualifiedClassName + '] ' + lSer.SerializeObject(AObject);
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lSer.Free;
|
2019-03-05 20:55:37 +01:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
procedure LogW(AMessage: string);
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
Log.Warn(AMessage, LOGGERPRO_TAG);
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure LogE(AMessage: string);
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
Log.Error(AMessage, LOGGERPRO_TAG);
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
|
|
|
|
2024-01-24 00:14:26 +01:00
|
|
|
procedure LogF(AMessage: string);
|
|
|
|
begin
|
|
|
|
Log.Fatal(AMessage, LOGGERPRO_TAG);
|
|
|
|
end;
|
|
|
|
|
2021-12-27 10:13:23 +01:00
|
|
|
procedure LogException(const E: Exception; const AMessage: String);
|
|
|
|
begin
|
2023-10-18 16:57:02 +02:00
|
|
|
LogE(E.ClassName + ': ' + E.Message + ' - (Custom Message: ' + AMessage + ')');
|
2021-12-27 10:13:23 +01:00
|
|
|
end;
|
|
|
|
|
2016-09-27 14:22:17 +02:00
|
|
|
procedure LogEnterMethod(const AMethodName: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
LogI('>> ' + AMethodName);
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
|
|
|
|
2016-09-27 14:22:17 +02:00
|
|
|
procedure LogExitMethod(const AMethodName: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
LogI('<< ' + AMethodName);
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure Log(LogLevel: TLogLevel; const AMessage: string);
|
|
|
|
begin
|
2022-12-06 16:10:55 +01:00
|
|
|
case gLevelsMap[LogLevel] of
|
2022-10-20 17:29:04 +02:00
|
|
|
TLogType.Debug:
|
|
|
|
Log.Debug(AMessage, LOGGERPRO_TAG);
|
|
|
|
TLogType.Info:
|
|
|
|
Log.Info(AMessage, LOGGERPRO_TAG);
|
|
|
|
TLogType.Warning:
|
|
|
|
Log.Warn(AMessage, LOGGERPRO_TAG);
|
|
|
|
TLogType.Error:
|
|
|
|
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
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
procedure Log(AMessage: string); overload;
|
2016-11-27 23:17:20 +01:00
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
LogI(AMessage);
|
2016-11-27 23:17:20 +01:00
|
|
|
end;
|
|
|
|
|
2019-03-05 20:55:37 +01:00
|
|
|
procedure Log(AObject: TObject); overload;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
Log(ObjectToJSON(AObject));
|
2019-03-05 20:55:37 +01:00
|
|
|
end;
|
|
|
|
|
2016-11-27 23:17:20 +01:00
|
|
|
procedure LogI(AMessage: string); overload;
|
2016-09-06 10:30:52 +02:00
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
Log.Info(AMessage, LOGGERPRO_TAG);
|
2016-09-06 10:30:52 +02:00
|
|
|
end;
|
|
|
|
|
2016-11-27 23:17:20 +01:00
|
|
|
procedure LogD(AMessage: string); overload;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
Log.Debug(AMessage, LOGGERPRO_TAG);
|
2016-11-27 23:17:20 +01:00
|
|
|
end;
|
|
|
|
|
2019-03-05 20:55:37 +01:00
|
|
|
procedure LogD(AMessage: TObject); overload;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
LogD(ObjectToJSON(AMessage));
|
2019-03-05 20:55:37 +01:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure LogI(AObject: TObject); overload;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
LogI(ObjectToJSON(AObject));
|
2019-03-05 20:55:37 +01:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure LogW(AObject: TObject); overload;
|
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
LogW(ObjectToJSON(AObject));
|
2019-03-05 20:55:37 +01:00
|
|
|
end;
|
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
procedure SetDefaultLogger(const aLogWriter: ILogWriter);
|
|
|
|
begin
|
2023-08-09 15:57:28 +02:00
|
|
|
if gDefaultLogger = nil then
|
|
|
|
begin
|
|
|
|
TMonitor.Enter(gLock); // double check here
|
|
|
|
try
|
|
|
|
if gDefaultLogger = nil then
|
|
|
|
begin
|
|
|
|
if aLogWriter <> nil then
|
|
|
|
begin
|
|
|
|
gDefaultLogger := aLogWriter;
|
|
|
|
Log.Info('Custom Logger initialized', LOGGERPRO_TAG);
|
|
|
|
end
|
|
|
|
else
|
2016-11-27 23:17:20 +01:00
|
|
|
begin
|
2023-08-09 15:57:28 +02:00
|
|
|
InitializeDefaultLogger;
|
2016-11-27 23:17:20 +01:00
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
2023-08-09 15:57:28 +02:00
|
|
|
finally
|
|
|
|
TMonitor.Exit(gLock);
|
2016-09-06 10:30:52 +02:00
|
|
|
end;
|
2023-08-09 15:57:28 +02:00
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
|
|
|
|
2024-01-23 17:19:48 +01:00
|
|
|
|
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
procedure InitializeDefaultLogger;
|
2019-05-02 17:38:57 +02:00
|
|
|
var
|
|
|
|
lLogsFolder: String;
|
2024-01-24 00:14:26 +01:00
|
|
|
lFileAppender, lConsoleAppender: ILogAppender;
|
|
|
|
lAppenders: TArray<ILogAppender>;
|
2013-10-30 00:48:23 +01:00
|
|
|
begin
|
2022-10-20 17:29:04 +02:00
|
|
|
{ This procedure must be called in a synchronized context
|
|
|
|
(Normally only SetDefaultLogger should be the caller) }
|
2022-12-06 16:10:55 +01:00
|
|
|
if not Assigned(gDefaultLogger) then
|
2022-10-20 17:29:04 +02:00
|
|
|
begin
|
2019-05-02 17:38:57 +02:00
|
|
|
{$IF NOT DEFINED(MOBILE)}
|
2022-10-20 17:29:04 +02:00
|
|
|
lLogsFolder := AppPath + 'logs';
|
2019-05-02 17:38:57 +02:00
|
|
|
{$ELSE}
|
2022-10-20 17:29:04 +02:00
|
|
|
lLogsFolder := TPath.Combine(TPath.GetDocumentsPath, 'logs');
|
2019-05-02 17:38:57 +02:00
|
|
|
{$ENDIF}
|
2024-04-09 17:15:11 +02:00
|
|
|
lFileAppender := TLoggerProFileAppender.Create(5, 10000, lLogsFolder);
|
2024-01-24 00:14:26 +01:00
|
|
|
if IsConsole and UseConsoleLogger then
|
|
|
|
begin
|
|
|
|
{$IF Defined(MSWINDOWS)}
|
|
|
|
lConsoleAppender := TLoggerProConsoleAppender.Create(TLogItemRendererNoTag.Create);
|
|
|
|
{$ELSE}
|
2024-02-14 18:02:25 +01:00
|
|
|
{$IF Not Defined(MOBILE)}
|
2024-01-24 00:14:26 +01:00
|
|
|
lConsoleAppender := TLoggerProSimpleConsoleAppender.Create(TLogItemRendererNoTag.Create);
|
|
|
|
{$ENDIF}
|
2024-02-14 18:02:25 +01:00
|
|
|
{$ENDIF}
|
2024-01-24 00:14:26 +01:00
|
|
|
lAppenders := [lFileAppender, lConsoleAppender];
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
lAppenders := [lFileAppender];
|
|
|
|
end;
|
|
|
|
gDefaultLogger := BuildLogWriter(lAppenders);
|
2022-10-20 17:29:04 +02:00
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
end;
|
2024-01-24 00:14:26 +01:00
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
2016-09-27 14:33:51 +02:00
|
|
|
procedure ReleaseGlobalLogger;
|
|
|
|
begin
|
2022-12-06 16:10:55 +01:00
|
|
|
if gDefaultLogger <> nil then
|
2022-10-20 17:29:04 +02:00
|
|
|
begin
|
2022-12-06 16:10:55 +01:00
|
|
|
TMonitor.Enter(gLock);
|
2022-10-20 17:29:04 +02:00
|
|
|
try
|
2022-12-06 16:10:55 +01:00
|
|
|
if gDefaultLogger <> nil then // double check
|
2022-10-20 17:29:04 +02:00
|
|
|
begin
|
2022-12-06 16:10:55 +01:00
|
|
|
gDefaultLogger := nil;
|
2022-10-20 17:29:04 +02:00
|
|
|
end;
|
|
|
|
finally
|
2022-12-06 16:10:55 +01:00
|
|
|
TMonitor.Exit(gLock);
|
2016-09-27 14:33:51 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-12-06 16:10:55 +01:00
|
|
|
{ ****************************************** }
|
2022-10-20 17:29:04 +02:00
|
|
|
{ *************** PROFILER ***************** }
|
2022-12-06 16:10:55 +01:00
|
|
|
{ ****************************************** }
|
2022-10-20 17:29:04 +02:00
|
|
|
{$IF Defined(SYDNEYORBETTER)}
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
constructor Profiler.Start(const Message: string; const Params: array of TVarRec);
|
|
|
|
begin
|
|
|
|
Start(Message, Params, LoggerTag);
|
|
|
|
end;
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
constructor Profiler.Start(const Message: string; const Params: array of TVarRec; const TAG: String);
|
|
|
|
begin
|
|
|
|
if Profiler.ProfileLogger = nil then
|
|
|
|
Exit;
|
|
|
|
fMessage := Format(Message, Params);
|
|
|
|
fStopWatch := TStopWatch.StartNew;
|
2023-04-06 14:47:01 +02:00
|
|
|
if not LogsOnlyIfOverThreshold then
|
|
|
|
begin
|
|
|
|
Inc(gReqNr);
|
|
|
|
fIndent := StringOfChar(' ', gIndent);
|
|
|
|
ProfileLogger.Info('[%s>>][%6d][%s]', [
|
|
|
|
fIndent,
|
|
|
|
gReqNr,
|
|
|
|
fMessage], TAG);
|
|
|
|
Inc(gIndent);
|
|
|
|
end;
|
2022-10-20 17:29:04 +02:00
|
|
|
end;
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
class operator Profiler.Finalize(var Dest: Profiler);
|
|
|
|
begin
|
|
|
|
if Profiler.ProfileLogger = nil then
|
|
|
|
Exit;
|
2022-12-06 16:10:55 +01:00
|
|
|
Dest.fStopWatch.Stop;
|
2023-04-06 14:47:01 +02:00
|
|
|
if not LogsOnlyIfOverThreshold then
|
|
|
|
begin
|
|
|
|
ProfileLogger.Log(
|
|
|
|
PROFILER_LOG_TYPE[Dest.fStopWatch.ElapsedMilliseconds >= WarningThreshold],
|
|
|
|
'[%s<<][%6d][%s][ELAPSED: %s]',
|
|
|
|
[
|
|
|
|
Dest.fIndent,
|
|
|
|
gReqNr,
|
|
|
|
Dest.fMessage,
|
|
|
|
Dest.fStopWatch.Elapsed.ToString
|
|
|
|
], LoggerTag);
|
|
|
|
Dec(gIndent);
|
|
|
|
Dec(gReqNr);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
if Dest.fStopWatch.ElapsedMilliseconds >= WarningThreshold then
|
|
|
|
begin
|
|
|
|
ProfileLogger.Log(
|
|
|
|
PROFILER_LOG_TYPE[True],
|
|
|
|
'[%s][ELAPSED: %s][THRESHOLD %d ms]',
|
|
|
|
[
|
|
|
|
Dest.fMessage,
|
|
|
|
Dest.fStopWatch.Elapsed.ToString,
|
|
|
|
WarningThreshold
|
|
|
|
], LoggerTag);
|
|
|
|
end;
|
|
|
|
end;
|
2022-10-20 17:29:04 +02:00
|
|
|
end;
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
constructor Profiler.Start(const Message: string);
|
|
|
|
begin
|
|
|
|
Start(Message, []);
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
procedure InitThreadVars;
|
|
|
|
begin
|
|
|
|
{$IF Defined(SYDNEYORBETTER)}
|
|
|
|
gIndent := 0;
|
|
|
|
gReqNr := 0;
|
|
|
|
{$ENDIF}
|
|
|
|
end;
|
|
|
|
|
|
|
|
initialization
|
|
|
|
|
2022-12-06 16:10:55 +01:00
|
|
|
gLock := TObject.Create;
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
{$IF Defined(SYDNEYORBETTER)}
|
|
|
|
Profiler.LoggerTag := 'profiler';
|
2022-12-06 16:10:55 +01:00
|
|
|
Profiler.WarningThreshold := 1000; //one sec
|
2022-10-20 17:29:04 +02:00
|
|
|
{$ENDIF}
|
|
|
|
{ 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)]);
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
// Creates log in the AppData/Roaming with PID in the filename
|
|
|
|
// _Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
|
|
|
|
// [TFileAppenderOption.IncludePID])]);
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2022-10-20 17:29:04 +02:00
|
|
|
// Creates log in the same folder with PID in the filename
|
|
|
|
// _Log := BuildLogWriter([TLoggerProFileAppender.Create(10, 5,
|
|
|
|
// [TFileAppenderOption.IncludePID])]);
|
2016-09-06 10:30:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
finalization
|
|
|
|
|
2022-12-06 16:10:55 +01:00
|
|
|
gLock.Free;
|
2022-10-20 17:29:04 +02:00
|
|
|
|
2016-09-06 10:30:52 +02:00
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
end.
|