Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Cannot log URLs #247

Closed
abirtley opened this issue Jul 24, 2023 · 2 comments · May be fixed by lkeff/airhornbot#5
Closed

Bug: Cannot log URLs #247

abirtley opened this issue Jul 24, 2023 · 2 comments · May be fixed by lkeff/airhornbot#5
Labels
bug Something isn't working

Comments

@abirtley
Copy link

Describe the bug
If you attempt to log a URL, you get a variety of errors, depending on whether the URL is a top level logged item, or a field inside a logged object. Either way, it fails.

To Reproduce
Steps to reproduce the behavior:

import { Logger } from 'tslog';
process.version; //? 18.16.0
const logger = new Logger({});
logger.info(new URL('https://www.abc.def')); //? Cannot convert undefined or null to object
logger.info({ u: new URL('https://www.abc.def') }); //? TypeError: Cannot convert undefined or null to object at getPrototypeOf (<anonymous>) at URL.[nodejs.util.inspect.custom...

Expected behavior
The URLs are logged without error.

Screenshots

image image

Additional context

Seems to be a reversion of #93, but perhaps a different cause.

I have managed to hack around it with the following additions in BaseLogger.js (node_modules/tslog/dist/esm/BaseLogger.js). With this amended code, URL objects can be logged without issue.

    _recursiveCloneAndMaskValuesOfKeys(source, keys, seen = []) {
        if (seen.includes(source)) {
            return { ...source };
        }
        if (typeof source === "object" && source != null) {
            seen.push(source);
        }

// NEW FUNCTION isURL - JUST A PROOF OF CONCEPT REALLY
        function isUrl(candidate) {
            if (!candidate || typeof candidate !== 'object') {
                return false;
            }
            if (candidate.href !== undefined && candidate.hash !== undefined && candidate.pathname !== undefined) {
                return true;
            }
            return false;
        }


        return isBuffer(source)
            ? source
            : source instanceof Map
                ? new Map(source)
                : source instanceof Set
                    ? new Set(source)
                    : Array.isArray(source)
                        ? source.map((item) => this._recursiveCloneAndMaskValuesOfKeys(item, keys, seen))
                        : source instanceof Date
                            ? new Date(source.getTime())
                            : isError(source)
                                ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
                                    o[prop] = keys.includes(this.settings?.maskValuesOfKeysCaseInsensitive !== true ? prop : prop.toLowerCase())
                                        ? this.settings.maskPlaceholder
                                        : this._recursiveCloneAndMaskValuesOfKeys(source[prop], keys, seen);
                                    return o;
                                }, this._cloneError(source))
                                // NEW CODE: IF THIS IS A URL, JUST RETURN IT AS A STRING. DO NOT RECURSE.
                                : isUrl(source)
                                ? source.toString()
                                : source != null && typeof source === "object"
                                    ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
                                        o[prop] = keys.includes(this.settings?.maskValuesOfKeysCaseInsensitive !== true ? prop : prop.toLowerCase())
                                            ? this.settings.maskPlaceholder
                                            : this._recursiveCloneAndMaskValuesOfKeys(source[prop], keys, seen);
                                        return o;
                                    }, Object.create(Object.getPrototypeOf(source)))
                                    : ((source) => {
                                        this.settings?.maskValuesRegEx?.forEach((regEx) => {
                                            source = source?.toString()?.replace(regEx, this.settings.maskPlaceholder);
                                        });
                                        return source;
                                    })(source);

Node.js Version
e.g. 18.16.0

OS incl. Version
macOS 13.4.1 (c)

@abirtley abirtley added the bug Something isn't working label Jul 24, 2023
@alexanderguy
Copy link

I came here to report the same issue with tslog v4.8.2, on both OS X and Linux with two different versions of node. Running the above test case, here are the stack traces I'm seeing:

node:internal/url:668
        ObjectGetPrototypeOf(this[context]) !== URLContext.prototype) {
        ^

TypeError: Cannot convert undefined or null to object
    at getPrototypeOf (<anonymous>)
    at [nodejs.util.inspect.custom] (node:internal/url:668:9)
    at formatValue (node:internal/util/inspect:806:19)
    at inspect (node:internal/util/inspect:365:10)
    at formatWithOptionsInternal (node:internal/util/inspect:2273:40)
    at formatWithOptions (node:internal/util/inspect:2135:10)
    at transportFormatted (file://redacted/node_modules/tslog/dist/esm/runtime/nodejs/index.js:89:33)
    at Logger.log (file://redacted/node_modules/tslog/dist/esm/BaseLogger.js:104:19)
    at Logger.info (file://redacted/node_modules/tslog/dist/esm/index.js:20:22)
    at file://redacted/repro.mjs:4:8

Node.js v18.13.0


node:internal/url:815
    return this.#context.href;
                ^

TypeError: Cannot read private member #context from an object whose class did not declare it
    at get href [as href] (node:internal/url:815:17)
    at [nodejs.util.inspect.custom] (node:internal/url:756:21)
    at formatValue (node:internal/util/inspect:804:19)
    at inspect (node:internal/util/inspect:363:10)
    at formatWithOptionsInternal (node:internal/util/inspect:2297:40)
    at formatWithOptions (node:internal/util/inspect:2159:10)
    at transportFormatted (file://redacted/node_modules/.pnpm/[email protected]/node_modules/tslog/dist/esm/runtime/nodejs/index.js:89:33)
    at Logger.log (file://redacted/node_modules/.pnpm/[email protected]/node_modules/tslog/dist/esm/BaseLogger.js:104:19)
    at Logger.info (file://redacted/node_modules/.pnpm/[email protected]/node_modules/tslog/dist/esm/index.js:20:22)
    at file://redacted/repro.mjs:4:8

Node.js v20.2.0

terehov added a commit that referenced this issue Aug 7, 2023
@terehov
Copy link
Contributor

terehov commented Aug 7, 2023

It's solved in V4.9.0.
Thanks for pointing it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants