analogger 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
 
2
- [![Test workflow](https://github.com/thimpat/analogger/actions/workflows/test.yml/badge.svg)](https://github.com/thimpat/analogger/actions/workflows/test.yml)
3
2
  [![nycrc Coverage](https://img.shields.io/nycrc/thimpat/analogger?preferredThreshold=lines)](https://github.com/thimpat/analogger/blob/main/README.md)
4
- [![Version workflow](https://github.com/thimpat/analogger/actions/workflows/versioning.yml/badge.svg)](https://github.com/thimpat/analogger/actions/workflows/versioning.yml)
5
3
  [![npm version](https://badge.fury.io/js/analogger.svg)](https://www.npmjs.com/package/analogger)
6
4
  <img alt="semantic-release" src="https://img.shields.io/badge/semantic--release-19.0.2-e10079?logo=semantic-release">
7
5
 
@@ -287,23 +285,29 @@ Display the browser native message box if run from it; otherwise, it displays th
287
285
  ### setOptions()
288
286
 
289
287
 
290
- | **Options** | **default** | **Expect** | **Description** |
291
- |---------------------|-------------|-----------------------------------|------------------------------------------------------------------------------------|
292
- | silent | false | boolean | _Hide logs from console (not errors)_ |
293
- | hideLog | false | boolean | _Same as above (silent has precedence over hideLog)_ |
294
- | hideError | false | boolean | _Hide errors from console_ |
295
- | hideHookMessage | false | boolean | _Hide the automatic message shown when some native console methods are overridden_ |
296
- | hidePassingTests | false | boolean | _Hide Live test results_ |
297
- | logToDom | false | string (DOM Selector) | _display log in a DOM container_ |
298
- | logToFile | false | string (File path) | _write log to a file if running from Node_ |
299
- | logToRemote | undefined | string (URL) | _Send log to a remote (more info in the next version)_ |
300
- | logMaxSize | 0 | number | _Set maximum size for the log file_ |
301
- | compressArchives | false | boolean | _Whether to archive and compress the logs after deleting an archive_ |
302
- | compressionLevel | 1 | number | _Archive compression level (0 to 9 with 0 = no compression)_ |
303
- | addArchiveTimestamp | true | boolean | _Whether to add a timestamp to the generated rotated logs_ |
304
- | logMaxArchives | 3 | number | _Maximum number of log files to use_ |
305
- | requiredLogLevel | "LOG" | "LOG" / "INFO" / "WARN" / "ERROR" | _Define the log level from which the system can show a log entry_ |
306
- | enableDate | false | boolean | _Show date + time (instead of time only)_ |
288
+ | **Options** | **default** | **Expect** | **Description** |
289
+ |-----------------------|-------------|-----------------------------------|------------------------------------------------------------------------------------|
290
+ | silent | false | boolean | _Hide logs from console (not errors)_ |
291
+ | hideLog | false | boolean | _Same as above (silent has precedence over hideLog)_ |
292
+ | hideError | false | boolean | _Hide errors from console_ |
293
+ | hideHookMessage | false | boolean | _Hide the automatic message shown when some native console methods are overridden_ |
294
+ | hidePassingTests | false | boolean | _Hide Live test results_ |
295
+ | logToDom | false | string (DOM Selector) | _display log in a DOM container_ |
296
+ | logToFile | false | string (File path) | _write log to a file if running from Node_ |
297
+ | logToRemote | undefined | string (URL) | _Send log to a remote (more info in the next version)_ |
298
+ | logMaxSize | 0 | number | _Set maximum size for the log file_ |
299
+ | compressArchives | false | boolean | _Whether to archive and compress the logs after deleting an archive_ |
300
+ | compressionLevel | 1 | number | _Archive compression level (0 to 9 with 0 = no compression)_ |
301
+ | addArchiveTimestamp | true | boolean | _Whether to add a timestamp to the generated rotated logs_ |
302
+ | logMaxArchives | 3 | number | _Maximum number of log files to use_ |
303
+ | requiredLogLevel | "LOG" | "LOG" / "INFO" / "WARN" / "ERROR" | _Define the log level from which the system can show a log entry_ |
304
+ | enableDate | false | boolean | _Show date + time (instead of time only)_ |
305
+ | logToLocalStorage | false | boolean | _Persist logs in browser localStorage_ |
306
+ | logToLocalStorageMax | 50 | number | _Max entries to keep in localStorage_ |
307
+ | compressArchives | false | boolean | _If true, rotates log files into a .tar.gz archive_ |
308
+ | compressionLevel | 1 | number | _Gzip compression level (0-9)_ |
309
+ | addArchiveTimestamp | true | boolean | _Appends a consistent timestamp to rotated files_ |
310
+ | forceLidOn | false | boolean | _Automatically generates a short hash LID if one isn't provided_ |
307
311
 
308
312
  <br/>
309
313
 
@@ -1185,6 +1189,69 @@ anaLogger.addPlugin("doSomething", doSomething);
1185
1189
 
1186
1190
 
1187
1191
 
1192
+ ```
1193
+
1194
+ ---
1195
+
1196
+ [![Test workflow](https://github.com/thimpat/analogger/actions/workflows/test.yml/badge.svg)](https://github.com/thimpat/analogger/actions/workflows/test.yml)
1197
+ [![nycrc Coverage](https://img.shields.io/nycrc/thimpat/analogger?preferredThreshold=lines)](https://github.com/thimpat/analogger/blob/main/README.md)
1198
+ [![npm version](https://badge.fury.io/js/analogger.svg)](https://www.npmjs.com/package/analogger)
1199
+
1200
+ Analogger is a highly customizable logger for Node and Browser environments. It logs to terminals, browser DOM, files, and remote servers.
1201
+
1202
+ ---
1203
+
1204
+ ## 🚀 New Features (v1.24+)
1205
+
1206
+ ### 💾 Local Storage Persistence (Browser)
1207
+ You can now persist logs in the browser's Local Storage. This is useful for debugging issues that occur across page refreshes.
1208
+
1209
+ ```javascript
1210
+ // Enable local storage logging
1211
+ anaLogger.setOptions({
1212
+ logToLocalStorage: true,
1213
+ logToLocalStorageMax: 100 // Keep last 100 logs
1214
+ });
1215
+
1216
+ // Restore logs from previous session after page reload
1217
+ anaLogger.restoreLogs();
1218
+ ```
1219
+
1220
+ 🗄️ Advanced Log Rotation & Archiving (Node)
1221
+ Manage large log files with automatic rotation and .tar.gz compression.
1222
+
1223
+ ```javascript
1224
+ anaLogger.setOptions({
1225
+ logToFile: "./app.log",
1226
+ logMaxSize: 5 * 1024 * 1024, // 5MB
1227
+ logMaxArchives: 5,
1228
+ compressArchives: true, // Archive rotated logs into .tar.gz
1229
+ compressionLevel: 6, // Gzip level (1-9)
1230
+ addArchiveTimestamp: true // Add ISO timestamps to filenames
1231
+ });
1232
+ ```
1233
+
1234
+ ### New Helper Methods
1235
+
1236
+ > restoreLogs()
1237
+
1238
+ (Browser only) Reads the history from localStorage and re-prints the logs to the current console. Perfect for diagnosing crashes that trigger a page reload.
1239
+
1240
+ > getLids()
1241
+
1242
+ Returns a deep clone of all loaded Lids, including statistics like callCount, callTimes, and human-readable dates.
1243
+
1244
+ > forceResolveLineCall(bool)
1245
+
1246
+ When enabled, AnaLogger captures the exact file and line number where the log was called and attaches it to the context.
1247
+
1248
+ ### Manual LID strings
1249
+
1250
+ If you don't want to pass objects, you can use a shorthand string format:
1251
+
1252
+ ```javascript
1253
+ // AnaLogger will parse this string as a context object
1254
+ anaLogger.log("lid: USR_LOGIN, color: purple", "User logged in");
1188
1255
  ```
1189
1256
 
1190
1257
  ---
package/ana-logger.d.cts CHANGED
@@ -114,8 +114,10 @@ declare class ____AnaLogger {
114
114
  */
115
115
  isBrowser(): boolean;
116
116
  resetLogger(): void;
117
+ remoteBuffer: any[];
118
+ remoteTimer: NodeJS.Timeout;
117
119
  resetOptions(): void;
118
- setOptions({ contextLenMax, idLenMax, lidLenMax, symbolLenMax, enableTrace, messageLenMax, hideLog, hideError, hideHookMessage, hidePassingTests, logToDom, logToFile, logMaxSize, logMaxArchives, logIndexArchive, addArchiveTimestamp, addArchiveIndex, compressArchives, compressionLevel, logToRemote, logToRemoteUrl, logToRemoteBinaryUrl, loopback, requiredLogLevel, oneConsolePerContext, silent, enableDate, logToLocalStorage, logToLocalStorageMax, protocol, host, port, pathname, binarypathname, loadHtmlToImage }?: any): void;
120
+ setOptions({ contextLenMax, idLenMax, lidLenMax, symbolLenMax, enableTrace, messageLenMax, hideLog, hideError, hideHookMessage, hidePassingTests, logToDom, logToFile, logMaxSize, logMaxArchives, logIndexArchive, addArchiveTimestamp, addArchiveIndex, compressArchives, compressionLevel, logToRemote, logToRemoteUrl, logToRemoteBinaryUrl, loopback, requiredLogLevel, oneConsolePerContext, silent, enableDate, logToLocalStorage, logToLocalStorageMax, logToLocalStorageSize, logToRemoteMaxEntries, logToRemoteDebounce, protocol, host, port, pathname, binarypathname, loadHtmlToImage }?: any): void;
119
121
  EOL: string;
120
122
  updateOptions(options: any): void;
121
123
  getOptions(): {
@@ -268,7 +270,9 @@ declare class ____AnaLogger {
268
270
  args?: any;
269
271
  }): void;
270
272
  writeLogToFile(text: any): void;
271
- writeLogToRemote(...data: any[]): any;
273
+ writeLogToRemote(...data: any[]): void;
274
+ flushRemoteLogs(): void;
275
+ performRemotePost(data: any): any;
272
276
  writeLogToLocalStorage(context: any, ...args: any[]): void;
273
277
  restoreLogs(): void;
274
278
  /**
@@ -930,6 +930,11 @@ class ____AnaLogger
930
930
  this.options.enableDate = undefined;
931
931
  this.options.logToLocalStorage = undefined;
932
932
  this.options.logToLocalStorageMax = 50;
933
+ this.options.logToLocalStorageSize = 10000;
934
+ this.options.logToRemoteMaxEntries = undefined;
935
+ this.options.logToRemoteDebounce = undefined;
936
+ this.remoteBuffer = [];
937
+ this.remoteTimer = null;
933
938
  }
934
939
 
935
940
  resetOptions()
@@ -967,6 +972,9 @@ class ____AnaLogger
967
972
  enableDate = undefined,
968
973
  logToLocalStorage = undefined,
969
974
  logToLocalStorageMax = 50,
975
+ logToLocalStorageSize = 10000,
976
+ logToRemoteMaxEntries = undefined,
977
+ logToRemoteDebounce = undefined,
970
978
  /** Remote - all optional **/
971
979
  protocol = undefined,
972
980
  host = undefined,
@@ -994,6 +1002,9 @@ class ____AnaLogger
994
1002
  this.options.enableTrace = enableTrace;
995
1003
 
996
1004
  this.options.logToLocalStorageMax = logToLocalStorageMax;
1005
+ this.options.logToLocalStorageSize = logToLocalStorageSize;
1006
+ this.options.logToRemoteMaxEntries = logToRemoteMaxEntries;
1007
+ this.options.logToRemoteDebounce = logToRemoteDebounce;
997
1008
 
998
1009
  if (loadHtmlToImage) {
999
1010
  const code = getHtmlToImage();
@@ -1986,6 +1997,58 @@ class ____AnaLogger
1986
1997
  }
1987
1998
 
1988
1999
  writeLogToRemote(...data)
2000
+ {
2001
+ try
2002
+ {
2003
+ if (this.options.logToRemoteMaxEntries === undefined && this.options.logToRemoteDebounce === undefined)
2004
+ {
2005
+ this.performRemotePost([...data]);
2006
+ return;
2007
+ }
2008
+
2009
+ this.remoteBuffer.push([...data]);
2010
+
2011
+ if (this.options.logToRemoteMaxEntries !== undefined && this.remoteBuffer.length >= this.options.logToRemoteMaxEntries)
2012
+ {
2013
+ this.flushRemoteLogs();
2014
+ return;
2015
+ }
2016
+
2017
+ if (this.options.logToRemoteDebounce !== undefined && !this.remoteTimer)
2018
+ {
2019
+ this.remoteTimer = setTimeout(() =>
2020
+ {
2021
+ this.flushRemoteLogs();
2022
+ }, this.options.logToRemoteDebounce);
2023
+ }
2024
+ }
2025
+ catch (e)
2026
+ {
2027
+ /* istanbul ignore next */
2028
+ ____AnaLogger.Console.error("LOG_TO_REMOTE_FAILURE: ", e.message);
2029
+ }
2030
+ }
2031
+
2032
+ flushRemoteLogs()
2033
+ {
2034
+ if (this.remoteTimer)
2035
+ {
2036
+ clearTimeout(this.remoteTimer);
2037
+ this.remoteTimer = null;
2038
+ }
2039
+
2040
+ if (this.remoteBuffer.length === 0)
2041
+ {
2042
+ return;
2043
+ }
2044
+
2045
+ const dataToFlush = [...this.remoteBuffer];
2046
+ this.remoteBuffer = [];
2047
+
2048
+ this.performRemotePost(dataToFlush);
2049
+ }
2050
+
2051
+ performRemotePost(data)
1989
2052
  {
1990
2053
  try
1991
2054
  {
@@ -1995,8 +2058,7 @@ class ____AnaLogger
1995
2058
  return null;
1996
2059
  }
1997
2060
 
1998
- const entry = [...data];
1999
- const stringified = JSON.stringify(entry);
2061
+ const stringified = JSON.stringify(data);
2000
2062
  fetch(urlDest, {
2001
2063
  method : "post",
2002
2064
  body : stringified,
@@ -2008,7 +2070,7 @@ class ____AnaLogger
2008
2070
  catch (e)
2009
2071
  {
2010
2072
  /* istanbul ignore next */
2011
- ____AnaLogger.Console.error("LOG_TO_REMOTE_FAILURE: ", e.message);
2073
+ ____AnaLogger.Console.error("REMOTE_POST_FAILURE: ", e.message);
2012
2074
  }
2013
2075
  }
2014
2076
 
@@ -2044,7 +2106,16 @@ class ____AnaLogger
2044
2106
  history = history.slice(history.length - max);
2045
2107
  }
2046
2108
 
2047
- localStorage.setItem(key, JSON.stringify(history));
2109
+ const maxSize = this.options.logToLocalStorageSize || 10000;
2110
+ let serialized = JSON.stringify(history);
2111
+
2112
+ while (serialized.length > maxSize && history.length > 1)
2113
+ {
2114
+ history.shift();
2115
+ serialized = JSON.stringify(history);
2116
+ }
2117
+
2118
+ localStorage.setItem(key, serialized);
2048
2119
  }
2049
2120
  catch (e)
2050
2121
  {