Skip to content

Instantly share code, notes, and snippets.

@dmorosinotto
Last active August 30, 2023 15:48
Show Gist options
  • Save dmorosinotto/b1d0a2dd5df7bdfcfab25dc83b41ca3d to your computer and use it in GitHub Desktop.
Save dmorosinotto/b1d0a2dd5df7bdfcfab25dc83b41ca3d to your computer and use it in GitHub Desktop.
Logger client side that override console to send all Errors to backend ( POST base64(JSON) --> /Log/Error )
//CONSOLE LOG OVEERIDE DEFINITION BY LELE 2023-08-30
// declare global {
type NLogLevel = 'log' | 'info' | 'warn' | 'error' | 'none';
interface NLogOptions {
NDebug?: boolean;
NLogLevel?: NLogLevel;
NShowLevel?: NLogLevel;
NAgent?: string;
NApp?: string;
NID?: number;
NLogUrl?: string;
NTimeout?: number;
NMaxCache?: number;
}
interface Console extends NLogOptions {
init?(options?: NLogOptions): void;
_?: {
start(): void;
stop(): void;
cache: ReadonlyArray<{
UTC: string; //DATE ISO FORMAT
NID: number;
APP: string;
USR?: string;
TYPE: Uppercase<Exclude<NLogLevel, 'none'>>;
ARGS: string[];
}>;
};
}
// }
//CONSOLE LOG OVVERRIDE BY LELE 2023-08-30
if (!console._) {
console._ = Object.freeze({
unique: Math.random(),
noop: function () {},
cache: [],
curr: { timer: 0, timeout: 0, sent: 0 },
log: console.log.bind(console),
info: console.info.bind(console),
warn: console.warn.bind(console),
error: console.error.bind(console),
setInterval: window.setInterval.bind(window),
clearInterval: window.clearInterval.bind(window),
level(logType) {
switch (logType) {
case 'log': return 0;
case 'info': return 1;
case 'warn': return 2;
case 'error': return 3;
default: return 666; //none
}
},
do(method, args) {
const _ = console._;
if (_.level(method) >= _.level(console.NLogLevel)) {
const UTC = new Date().toISOString();
const NID = console.NID || _.unique;
const APP = console.NApp || window.location.origin;
const USR = console.NAgent || '';
const ARGS = args.map((err, i) => {
let json = err instanceof Error ? (console.NDebug ? err.stack : err.message) : err;
try {
json = JSON.stringify(json);
} catch {
json = `CANT SERIALIZE args[${i}]`;
}
return json;
});
_.cache.push({ UTC, NID, APP, USR, TYPE: String(method).toUpperCase(), ARGS });
if (console.NMaxCache) {
while (_.curr.sent && _.cache.length > console.NMaxCache) {
_.cache.shift();
_.curr.sent--;
}
} else if (_.curr.sent) {
_.cache.splice(0, _.curr.sent);
_.curr.sent = 0;
}
}
if (_.level(method) >= _.level(console.NShowLevel)) {
_[method](...args);
}
if (method === 'error') {
_.send();
}
},
send() {
const _ = console._;
try {
const from = _.curr.sent;
const to = _.cache.length;
if (to > from) {
_.curr.sent = to;
fetch(window.location.origin + (console.NLogUrl || '/Log/Error'), {
method: 'POST',
// mode: "cors",
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: `"${btoa(JSON.stringify(_.cache.slice(from, to)))}"`,
})
.then(_.noop)
.catch(_.noop)
}
} catch {}
},
stop() {
const _ = console._;
try {
_.curr.timer && _.clearTimeout(_.curr.timer);
} catch {}
},
start() {
const _ = console._;
if (_.curr.timeout > 0) {
_.stop();
_.curr.timer = _.setInterval(_.send, _.curr.timeout);
} else _.curr.timer = 0;
}
});
Object.defineProperty(console, 'NTimeout', {
get: function () {
return console._.curr.timeout;
},
set(value) {
console._.curr.timeout = value;
console._.start();
}
});
console.init = function (options = {}) {
Object.assign(console, {
NID: console._.unique,
NLogUrl: '/Log/Error',
NTimeout: 5 * 60 * 1000, //5min
NMaxCache: 100,
NLogLevel: 'warn',
NShowLevel: 'log',
NDebug: false,
NApp: window.location.origin,
NAgent: '',
...options,
});
};
['log', 'info', 'warn', 'error'].map((method) => {
console[type] = function () {
console._.do(method, Array.from(arguments));
};
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment