2
0

Quick.Debug.Utils.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. { ***************************************************************************
  2. Copyright (c) 2016-2020 Kike Pérez
  3. Unit : Quick.Debug.Utils
  4. Description : Debug Utils
  5. Author : Kike Pérez
  6. Version : 1.9
  7. Created : 05/06/2020
  8. Modified : 07/07/2020
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Debug.Utils;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. System.SysUtils,
  26. Quick.Logger.Intf,
  27. Quick.Serializer.Intf,
  28. Quick.Commons,
  29. {$IFNDEF NEXTGEN}
  30. Quick.Console,
  31. {$ELSE}
  32. {$IFNDEF DELPHILINUX}
  33. FMX.Types,
  34. {$ENDIF}
  35. {$ENDIF}
  36. Quick.Chrono;
  37. type
  38. TDebugConsoleLogger = class(TInterfacedObject,ILogger)
  39. private
  40. fShowTime : Boolean;
  41. fFormatSettings : TFormatSettings;
  42. function FormatMsg(const aMsg : string) : string;
  43. public
  44. constructor Create;
  45. property ShowTime : Boolean read fShowTime write fShowTime;
  46. property FormatSettings : TFormatSettings read fFormatSettings write fFormatSettings;
  47. procedure Info(const aMsg : string); overload;
  48. procedure Info(const aMsg : string; aParams : array of const); overload;
  49. procedure Succ(const aMsg : string); overload;
  50. procedure Succ(const aMsg : string; aParams : array of const); overload;
  51. procedure Done(const aMsg : string); overload;
  52. procedure Done(const aMsg : string; aParams : array of const); overload;
  53. procedure Warn(const aMsg : string); overload;
  54. procedure Warn(const aMsg : string; aParams : array of const); overload;
  55. procedure Error(const aMsg : string); overload;
  56. procedure Error(const aMsg : string; aParams : array of const); overload;
  57. procedure Critical(const aMsg : string); overload;
  58. procedure Critical(const aMsg : string; aParams : array of const); overload;
  59. procedure Trace(const aMsg : string); overload;
  60. procedure Trace(const aMsg : string; aParams : array of const); overload;
  61. procedure Debug(const aMsg : string); overload;
  62. procedure Debug(const aMsg : string; aParams : array of const); overload;
  63. procedure &Except(const aMsg : string; aValues : array of const); overload;
  64. procedure &Except(const aMsg, aException, aStackTrace : string); overload;
  65. procedure &Except(const aMsg : string; aValues: array of const; const aException, aStackTrace: string); overload;
  66. end;
  67. IDebugMethodEnter = interface
  68. ['{3BE4E8C2-CBCF-43BC-B3BE-0A0235C49BF1}']
  69. procedure TimeIt;
  70. end;
  71. TDebugMethodEnter = class(TInterfacedObject,IDebugMethodEnter)
  72. private
  73. fLogger : ILogger;
  74. fCallerMethod : string;
  75. fTimeIt : Boolean;
  76. fChrono : IChronometer;
  77. public
  78. constructor Create(aLogger : ILogger; const aCallerMethod : string);
  79. destructor Destroy; override;
  80. procedure TimeIt;
  81. end;
  82. IDebugMehtodChrono = interface
  83. ['{3DDD5389-D55A-4DEA-81FA-980CF41ACE38}']
  84. procedure BreakPoint(const aMessage : string);
  85. procedure Stop;
  86. end;
  87. TDebugMethodChrono = class(TInterfacedObject,IDebugMehtodChrono)
  88. private
  89. fLogger : ILogger;
  90. fCallerMethod : string;
  91. fMsg : string;
  92. fChrono : IChronometer;
  93. public
  94. constructor Create(aLogger: ILogger; const aCallerMethod, aMsg : string);
  95. destructor Destroy; override;
  96. procedure BreakPoint(const aMsg : string);
  97. procedure Stop;
  98. end;
  99. TDebugger = class
  100. private class var
  101. fLogger : ILogger;
  102. fSerializer : ISerializer;
  103. fShowTime : Boolean;
  104. public
  105. class constructor Create;
  106. class destructor Destroy;
  107. class procedure SetLogger(aLogger : ILogger);
  108. class property ShowTime : Boolean read fShowTime write fShowTime;
  109. class function NewChrono(aStarted : Boolean) : IChronometer;
  110. class function TimeIt(aOwner : TObject; const aFunctionName, aDescription : string) : IDebugMehtodChrono;
  111. class function Log : ILogger;
  112. class procedure Trace(aOwner : TObject; const aMsg : string); overload;
  113. class procedure Trace(aOwner : TObject; const aMsg : string; aParams : array of const); overload;
  114. class procedure Trace(const aMsg : string); overload;
  115. class procedure Trace(const aMsg : string; aParams : array of const); overload;
  116. class procedure Trace(const aMsg : string; const aObject : TObject); overload;
  117. class function Enter(aOwner : TObject; const aFunctionName: string) : IDebugMethodEnter;
  118. end;
  119. {$IFDEF NEXTGEN}
  120. procedure cout(const cMsg : string; params : array of const; cEventType : TLogEventType); overload;
  121. procedure cout(const cMsg : string; cEventType : TLogEventType); overload;
  122. {$ENDIF}
  123. implementation
  124. uses
  125. Quick.Json.Serializer;
  126. {$IFDEF NEXTGEN}
  127. procedure cout(const cMsg : string; params : array of const; cEventType : TLogEventType);
  128. begin
  129. FMX.Types.Log.d(Format(cMsg,params));
  130. end;
  131. procedure cout(const cMsg : string; cEventType : TLogEventType); overload;
  132. begin
  133. FMX.Types.Log.d(cMsg);
  134. end;
  135. {$ENDIF}
  136. { TDebugger }
  137. class constructor TDebugger.Create;
  138. begin
  139. fSerializer := TJsonSerializer.Create(TSerializeLevel.slPublicProperty);
  140. fLogger := TDebugConsoleLogger.Create;
  141. fShowTime := True;
  142. end;
  143. class destructor TDebugger.Destroy;
  144. begin
  145. fSerializer := nil;
  146. fLogger := nil;
  147. end;
  148. class function TDebugger.TimeIt(aOwner : TObject; const aFunctionName, aDescription: string): IDebugMehtodChrono;
  149. begin
  150. if aOwner <> nil then Result := TDebugMethodChrono.Create(fLogger,Format('%s.%s',[aOwner.ClassName,aFunctionName]),aDescription)
  151. else Result := TDebugMethodChrono.Create(fLogger,Format('%s',[aFunctionName]),aDescription);
  152. end;
  153. class function TDebugger.Enter(aOwner : TObject; const aFunctionName: string) : IDebugMethodEnter;
  154. begin
  155. if aOwner <> nil then
  156. begin
  157. fLogger.Debug(Format('[ENTER] >> %s.%s',[aOwner.ClassName,aFunctionName]));
  158. Result := TDebugMethodEnter.Create(fLogger,Format('%s.%s',[aOwner.ClassName,aFunctionName]));
  159. end
  160. else
  161. begin
  162. fLogger.Debug(Format('[ENTER] >> %s',[aFunctionName]));
  163. Result := TDebugMethodEnter.Create(fLogger,aFunctionName);
  164. end;
  165. end;
  166. class function TDebugger.NewChrono(aStarted : Boolean) : IChronometer;
  167. begin
  168. Result := TChronometer.Create(aStarted);
  169. end;
  170. class function TDebugger.Log: ILogger;
  171. begin
  172. Result := fLogger;
  173. end;
  174. class procedure TDebugger.SetLogger(aLogger: ILogger);
  175. begin
  176. if aLogger = nil then raise Exception.Create('Debugger logger cannot be nil!');
  177. fLogger := aLogger;
  178. fShowTime := False;
  179. end;
  180. class procedure TDebugger.Trace(aOwner: TObject; const aMsg: string);
  181. begin
  182. if aOwner <> nil then fLogger.Trace(Format('[TRACE] %s -> %s',[aOwner.ClassName,aMsg]))
  183. else fLogger.Trace(Format('[TRACE] -> %s',[aMsg]))
  184. end;
  185. class procedure TDebugger.Trace(aOwner: TObject; const aMsg: string; aParams: array of const);
  186. begin
  187. Self.Trace(aOwner,Format(aMsg,aParams));
  188. end;
  189. class procedure TDebugger.Trace(const aMsg: string);
  190. begin
  191. fLogger.Trace(Format('[TRACE] %s',[aMsg]));
  192. end;
  193. class procedure TDebugger.Trace(const aMsg: string; aParams: array of const);
  194. begin
  195. Self.Trace(Format(aMsg,aParams));
  196. end;
  197. class procedure TDebugger.Trace(const aMsg: string; const aObject: TObject);
  198. begin
  199. Self.Trace(aMsg + ' ' + fSerializer.ObjectToJson(aObject));
  200. end;
  201. { TDebugConsoleLogger }
  202. constructor TDebugConsoleLogger.Create;
  203. begin
  204. fFormatSettings.DateSeparator := '/';
  205. fFormatSettings.TimeSeparator := ':';
  206. fFormatSettings.ShortDateFormat := 'DD-MM-YYY HH:NN:SS.ZZZ';
  207. fFormatSettings.ShortTimeFormat := 'HH:NN:SS';
  208. {$IFNDEF NEXTGEN}
  209. Console.LogVerbose := LOG_ALL;
  210. {$ENDIF}
  211. fShowTime := True;
  212. end;
  213. procedure TDebugConsoleLogger.Critical(const aMsg: string; aParams: array of const);
  214. begin
  215. cout(FormatMsg(aMsg),aParams,TLogEventType.etCritical);
  216. end;
  217. procedure TDebugConsoleLogger.Critical(const aMsg: string);
  218. begin
  219. cout(FormatMsg(aMsg),TLogEventType.etCritical);
  220. end;
  221. procedure TDebugConsoleLogger.Debug(const aMsg: string; aParams: array of const);
  222. begin
  223. cout(FormatMsg(aMsg),aParams,TLogEventType.etDebug);
  224. end;
  225. procedure TDebugConsoleLogger.Debug(const aMsg: string);
  226. begin
  227. cout(FormatMsg(aMsg),TLogEventType.etDebug);
  228. end;
  229. procedure TDebugConsoleLogger.Done(const aMsg: string; aParams: array of const);
  230. begin
  231. cout(FormatMsg(aMsg),aParams,TLogEventType.etDone);
  232. end;
  233. procedure TDebugConsoleLogger.Done(const aMsg: string);
  234. begin
  235. cout(FormatMsg(aMsg),TLogEventType.etDone);
  236. end;
  237. procedure TDebugConsoleLogger.Error(const aMsg: string);
  238. begin
  239. cout(FormatMsg(aMsg),TLogEventType.etError);
  240. end;
  241. procedure TDebugConsoleLogger.Error(const aMsg: string; aParams: array of const);
  242. begin
  243. cout(FormatMsg(aMsg),aParams,TLogEventType.etError);
  244. end;
  245. procedure TDebugConsoleLogger.&Except(const aMsg: string; aValues: array of const);
  246. begin
  247. cout(FormatMsg(aMsg),aValues,TLogEventType.etException);
  248. end;
  249. procedure TDebugConsoleLogger.&Except(const aMsg, aException, aStackTrace: string);
  250. begin
  251. cout(FormatMsg(aMsg),TLogEventType.etException);
  252. end;
  253. procedure TDebugConsoleLogger.&Except(const aMsg: string; aValues: array of const; const aException, aStackTrace: string);
  254. begin
  255. cout(FormatMsg(aMsg),aValues,TLogEventType.etException);
  256. end;
  257. function TDebugConsoleLogger.FormatMsg(const aMsg: string): string;
  258. begin
  259. if fShowTime then Result := DateTimeToStr(Now(),fFormatSettings) + ' ' + aMsg
  260. else Result := aMsg
  261. end;
  262. procedure TDebugConsoleLogger.Info(const aMsg: string; aParams: array of const);
  263. begin
  264. cout(FormatMsg(aMsg),aParams,TLogEventType.etInfo);
  265. end;
  266. procedure TDebugConsoleLogger.Info(const aMsg: string);
  267. begin
  268. cout(FormatMsg(aMsg),TLogEventType.etInfo);
  269. end;
  270. procedure TDebugConsoleLogger.Succ(const aMsg: string; aParams: array of const);
  271. begin
  272. cout(FormatMsg(aMsg),aParams,TLogEventType.etSuccess);
  273. end;
  274. procedure TDebugConsoleLogger.Succ(const aMsg: string);
  275. begin
  276. cout(FormatMsg(aMsg),TLogEventType.etSuccess);
  277. end;
  278. procedure TDebugConsoleLogger.Trace(const aMsg: string; aParams: array of const);
  279. begin
  280. cout(FormatMsg(aMsg),aParams,TLogEventType.etTrace);
  281. end;
  282. procedure TDebugConsoleLogger.Trace(const aMsg: string);
  283. begin
  284. cout(FormatMsg(aMsg),TLogEventType.etTrace);
  285. end;
  286. procedure TDebugConsoleLogger.Warn(const aMsg: string; aParams: array of const);
  287. begin
  288. cout(FormatMsg(aMsg),aParams,TLogEventType.etWarning);
  289. end;
  290. procedure TDebugConsoleLogger.Warn(const aMsg: string);
  291. begin
  292. cout(FormatMsg(aMsg),TLogEventType.etWarning);
  293. end;
  294. { TDebugFunctionEnter }
  295. constructor TDebugMethodEnter.Create(aLogger: ILogger; const aCallerMethod: string);
  296. begin
  297. fLogger := aLogger;
  298. fCallerMethod := aCallerMethod;
  299. end;
  300. destructor TDebugMethodEnter.Destroy;
  301. begin
  302. if fTimeIt then
  303. begin
  304. fChrono.Stop;
  305. fLogger.Debug(Format('[EXIT] >> %s in %s',[fCallerMethod,fChrono.ElapsedTime]));
  306. end
  307. else fLogger.Debug(Format('[EXIT] >> %s',[fCallerMethod]));
  308. inherited;
  309. end;
  310. procedure TDebugMethodEnter.TimeIt;
  311. begin
  312. fTimeIt := True;
  313. fChrono := TChronometer.Create(True);
  314. end;
  315. { TDebugMethodChrono }
  316. constructor TDebugMethodChrono.Create(aLogger: ILogger; const aCallerMethod, aMsg : string);
  317. begin
  318. fLogger := aLogger;
  319. fCallerMethod := aCallerMethod;
  320. fMsg := aMsg;
  321. fChrono := TChronometer.Create(True);
  322. end;
  323. destructor TDebugMethodChrono.Destroy;
  324. begin
  325. if fChrono.IsRunning then
  326. begin
  327. fChrono.Stop;
  328. fLogger.Trace(Format('[CHRONO] %s -> %s = %s',[fCallerMethod,fMsg,fChrono.ElapsedTime]));
  329. end;
  330. inherited;
  331. end;
  332. procedure TDebugMethodChrono.BreakPoint(const aMsg: string);
  333. begin
  334. fChrono.BreakPoint;
  335. fLogger.Trace(Format('[CHRONO] %s -> %s = %s',[fCallerMethod,aMsg,fChrono.ElapsedTime_BreakPoint]));
  336. end;
  337. procedure TDebugMethodChrono.Stop;
  338. begin
  339. fChrono.Stop;
  340. fLogger.Trace(Format('[CHRONO] %s -> %s = %s',[fCallerMethod,fMsg,fChrono.ElapsedTime]));
  341. end;
  342. end.