0

I have a (Node)JS class:

class PayloadContainingError extends Error {
  constructor(msg, payload) {
    super(msg);
    this.payload = payload;
  }
}

payload field may contain long strings, even in MB range.

If I console.log this class at some point, I get the full payload in the log. Instead, I want it to log a truncated portion (like the Linux head command).

E.g. if I console.error("Bad payload", instance_of_PayloadContainingError), instead of getting

Bad payload { Error: BAD
    at foo.bar
  payload:
    'a possibly million-character long line that pollutes my log'
}

I want console to log

Bad payload { Error: BAD
    at foo.bar
  payload:
    'first 100 chars...'
}

Is this possible via some magic on the class/field level - without having to refactor any (existing and future) console.log calls?

[Edit] For those voting to close this question in favor of "JavaScript toString() override": per my understanding, toString() is not the question here - console seems to do beyond what toString() usually does, when logging an error object (e.g. adding the stacktrace - which I don't want to reimplement anyway). (As mentioned in one of my comments, overriding toString() does not change the output anyway.)

Janaka Bandara
  • 1,024
  • 1
  • 12
  • 27
  • 1
    Does this answer your question? [Is it possible to override JavaScript's toString() function to provide meaningful output for debugging?](https://stackoverflow.com/questions/6307514/is-it-possible-to-override-javascripts-tostring-function-to-provide-meaningfu) – Andy Ray May 27 '21 at 02:46
  • Sadly not - tried adding a `toString() { return payload.substring(0,100); }` method to the class, as well as a separate `PayloadContainingError.prototype.toString = function() { return payload.substring(0,100); }` (returning only the truncated payload was just for demonstration), but neither makes any change in the `console.error` output - looks like `console` uses a different strategy when stringifying an error – Janaka Bandara May 27 '21 at 08:28

1 Answers1

0

It seems like node's console.* methods take into account only enumerable properties. Therefore you could make this property non-enumerable:

class PayloadContainingError extends Error {
    constructor(msg, payload) {
      super(msg);
      Object.defineProperty(this, "payload", {
            enumerable: false,
            value: payload,
        });
    }
}

const e = new PayloadContainingError("test error", "a possibly million-character long line that pollutes my log");
console.error(e);
$ node ./test.js 
PayloadContainingError: test error
    at Object.<anonymous> (/home/slava-b/arc/fei-24447/frontend/projects/infratest/packages/tokenator-universal/test.js:43:11)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11
Slava Baginov
  • 949
  • 1
  • 8
  • 10