fullstack-build / tslog

📝 tslog - Universal Logger for TypeScript and JavaScript
https://tslog.js.org
MIT License
1.34k stars 63 forks source link

Requesting advice for removing `undefined` from ILogObj before outputting #189

Open quinnturner opened 1 year ago

quinnturner commented 1 year ago

I am excited to get v4 working!

I have an ILogObj:

export interface LogObj {
  requestId?: string | (() => string | undefined);
  jobId?: string | (() => string | undefined);
  jobName?: string | (() => string | undefined);
  userId?: string | (() => string | undefined);
}

These properties are optionally defined using AsyncLocalStorage. Due to being optional, when I output, I have the following in logs:

requestId: {UUID}
jobId: undefined
jobName: undefined
userId: {UUID}

How would you recommend I remove the undefined values altogether from the logs?

My first thought is to use overwrite.toLogObj. However, I don't want to lose all of the "magic" that this library does internally for handling errors, masking, etc., in toLogObj. Ideally, I'd prefer to extend the toLogObj, kind of like an beforeToLogObj. I don't want to override any of the existing behaviour of the logger, I'd prefer to let tslog just do its thing and me hook in.

quinnturner commented 1 year ago

Because I need to get this out the door ASAP, here is what I did as a workaround:

diff --git a/dist/cjs/BaseLogger.js b/dist/cjs/BaseLogger.js
index 81bd08d7bc53f65aeac95d5d1f9610b447368e79..79f6b7380f12df28343b6bc4c1ed1d092d0fb3ac 100644
--- a/dist/cjs/BaseLogger.js
+++ b/dist/cjs/BaseLogger.js
@@ -75,6 +75,7 @@ class BaseLogger {
             attachedTransports: [...(settings?.attachedTransports ?? [])],
             overwrite: {
                 mask: settings?.overwrite?.mask,
+                beforeToLogObj: settings?.overwrite?.beforeToLogObj,
                 toLogObj: settings?.overwrite?.toLogObj,
                 addMeta: settings?.overwrite?.addMeta,
                 formatMeta: settings?.overwrite?.formatMeta,
@@ -95,7 +96,10 @@ class BaseLogger {
             : this.settings.maskValuesOfKeys != null && this.settings.maskValuesOfKeys.length > 0
                 ? this._mask(logArgs)
                 : logArgs;
-        const thisLogObj = this.logObj != null ? this._recursiveCloneAndExecuteFunctions(this.logObj) : undefined;
+        let thisLogObj = this.logObj != null ? this._recursiveCloneAndExecuteFunctions(this.logObj) : undefined;
+        if (this.settings.overwrite?.beforeToLogObj != null) {
+            thisLogObj = this.settings.overwrite?.beforeToLogObj(thisLogObj)
+        }
         const logObj = this.settings.overwrite?.toLogObj != null ? this.settings.overwrite?.toLogObj(maskedArgs, thisLogObj) : this._toLogObj(maskedArgs, thisLogObj);
         const logObjWithMeta = this.settings.overwrite?.addMeta != null
             ? this.settings.overwrite?.addMeta(logObj, logLevelId, logLevelName)
diff --git a/dist/esm/BaseLogger.js b/dist/esm/BaseLogger.js
index a7b58d3d123d0a6f748172eb05e3d102aead3cbe..712cd38101d227da97d425ba65d9d0cf990d1eb9 100644
--- a/dist/esm/BaseLogger.js
+++ b/dist/esm/BaseLogger.js
@@ -58,6 +58,7 @@ export class BaseLogger {
             attachedTransports: [...(settings?.attachedTransports ?? [])],
             overwrite: {
                 mask: settings?.overwrite?.mask,
+                beforeToLogObj: settings?.overwrite?.beforeToLogObj,
                 toLogObj: settings?.overwrite?.toLogObj,
                 addMeta: settings?.overwrite?.addMeta,
                 formatMeta: settings?.overwrite?.formatMeta,
@@ -78,7 +79,10 @@ export class BaseLogger {
             : this.settings.maskValuesOfKeys != null && this.settings.maskValuesOfKeys.length > 0
                 ? this._mask(logArgs)
                 : logArgs;
-        const thisLogObj = this.logObj != null ? this._recursiveCloneAndExecuteFunctions(this.logObj) : undefined;
+        let thisLogObj = this.logObj != null ? this._recursiveCloneAndExecuteFunctions(this.logObj) : undefined;
+        if (this.settings.overwrite?.beforeToLogObj != null) {
+            thisLogObj = this.settings.overwrite?.beforeToLogObj(thisLogObj)
+        }
         const logObj = this.settings.overwrite?.toLogObj != null ? this.settings.overwrite?.toLogObj(maskedArgs, thisLogObj) : this._toLogObj(maskedArgs, thisLogObj);
         const logObjWithMeta = this.settings.overwrite?.addMeta != null
             ? this.settings.overwrite?.addMeta(logObj, logLevelId, logLevelName)
diff --git a/dist/types/interfaces.d.ts b/dist/types/interfaces.d.ts
index fa363bd0250f4dc8713b0a59f7f525deaa3bb726..3246a9cb13e2e3400dd8053ec222710fd05d07ac 100644
--- a/dist/types/interfaces.d.ts
+++ b/dist/types/interfaces.d.ts
@@ -48,6 +48,7 @@ export interface ISettingsParam<LogObj> {
     attachedTransports?: ((transportLogger: LogObj & ILogObjMeta) => void)[];
     overwrite?: {
         mask?: (args: unknown[]) => unknown[];
+        beforeToLogObj?: (clonesLogObj?: LogObj) => LogObj | undefined;
         toLogObj?: (args: unknown[], clonesLogObj?: LogObj) => LogObj;
         addMeta?: (logObj: LogObj, logLevelId: number, logLevelName: string) => LogObj & ILogObjMeta;
         formatMeta?: (meta?: IMeta) => string;
   overwrite: {
        beforeToLogObj: (clonesLogObj?: LogObj) => {
          if (!clonesLogObj) {
            return undefined;
          }
          for (const logObjKey of logObjKeys.filter(
            (key) => key in clonesLogObj && clonesLogObj[key] == undefined,
          )) {
            delete clonesLogObj[logObjKey];
          }
          if (Object.keys(clonesLogObj).length === 0) {
            return undefined;
          }
          return clonesLogObj;
        },
      },