mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
🐛 fix: Prevent Unnecessary Cloning of Symbols in Log Object (#1455)
fix(api/config/parsers): prevent cloning of unnecessary symbols within log object by using `klona` instead of `klona/full`, handle symbols edge case, log parsing errors, and use spaces instead of tab for cleaner logs
This commit is contained in:
parent
20971aa005
commit
c3d5a08b26
1 changed files with 71 additions and 49 deletions
|
|
@ -1,11 +1,16 @@
|
||||||
|
const { klona } = require('klona');
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
const traverse = require('traverse');
|
const traverse = require('traverse');
|
||||||
const { klona } = require('klona/full');
|
|
||||||
|
|
||||||
const SPLAT_SYMBOL = Symbol.for('splat');
|
const SPLAT_SYMBOL = Symbol.for('splat');
|
||||||
const MESSAGE_SYMBOL = Symbol.for('message');
|
const MESSAGE_SYMBOL = Symbol.for('message');
|
||||||
|
|
||||||
const sensitiveKeys = [/^(sk-)[^\s]+/, /(Bearer )[^\s]+/, /(api-key:? )[^\s]+/, /(key=)[^\s]+/];
|
const sensitiveKeys = [
|
||||||
|
/^(sk-)[^\s]+/, // OpenAI API key pattern
|
||||||
|
/(Bearer )[^\s]+/, // Header: Bearer token pattern
|
||||||
|
/(api-key:? )[^\s]+/, // Header: API key pattern
|
||||||
|
/(key=)[^\s]+/, // URL query param: sensitive key pattern (Google)
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if a given value string is sensitive and returns matching regex patterns.
|
* Determines if a given value string is sensitive and returns matching regex patterns.
|
||||||
|
|
@ -102,55 +107,72 @@ const condenseArray = (item) => {
|
||||||
*/
|
*/
|
||||||
const debugTraverse = winston.format.printf(({ level, message, timestamp, ...metadata }) => {
|
const debugTraverse = winston.format.printf(({ level, message, timestamp, ...metadata }) => {
|
||||||
let msg = `${timestamp} ${level}: ${truncateLongStrings(message?.trim(), 150)}`;
|
let msg = `${timestamp} ${level}: ${truncateLongStrings(message?.trim(), 150)}`;
|
||||||
|
try {
|
||||||
if (level !== 'debug') {
|
if (level !== 'debug') {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
|
||||||
|
|
||||||
if (!metadata) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
const debugValue = metadata[SPLAT_SYMBOL]?.[0];
|
|
||||||
|
|
||||||
if (!debugValue) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugValue && Array.isArray(debugValue)) {
|
|
||||||
msg += `\n${JSON.stringify(debugValue.map(condenseArray))}`;
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof debugValue !== 'object') {
|
|
||||||
return (msg += ` ${debugValue}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg += '\n{';
|
|
||||||
|
|
||||||
const copy = klona(metadata);
|
|
||||||
traverse(copy).forEach(function (value) {
|
|
||||||
const parent = this.parent;
|
|
||||||
const parentKey = `${parent && parent.notRoot ? parent.key + '.' : ''}`;
|
|
||||||
const tabs = `${parent && parent.notRoot ? '\t\t' : '\t'}`;
|
|
||||||
if (this.isLeaf && typeof value === 'string') {
|
|
||||||
const truncatedText = truncateLongStrings(value);
|
|
||||||
msg += `\n${tabs}${parentKey}${this.key}: ${JSON.stringify(truncatedText)},`;
|
|
||||||
} else if (this.notLeaf && Array.isArray(value) && value.length > 0) {
|
|
||||||
const currentMessage = `\n${tabs}// ${value.length} ${this.key.replace(/s$/, '')}(s)`;
|
|
||||||
this.update(currentMessage, true);
|
|
||||||
msg += currentMessage;
|
|
||||||
const stringifiedArray = value.map(condenseArray);
|
|
||||||
msg += `\n${tabs}${parentKey}${this.key}: [${stringifiedArray}],`;
|
|
||||||
} else if (this.isLeaf && typeof value === 'function') {
|
|
||||||
msg += `\n${tabs}${parentKey}${this.key}: function,`;
|
|
||||||
} else if (this.isLeaf) {
|
|
||||||
msg += `\n${tabs}${parentKey}${this.key}: ${value},`;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
msg += '\n}';
|
if (!metadata) {
|
||||||
return msg;
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
const debugValue = metadata[SPLAT_SYMBOL]?.[0];
|
||||||
|
|
||||||
|
if (!debugValue) {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debugValue && Array.isArray(debugValue)) {
|
||||||
|
msg += `\n${JSON.stringify(debugValue.map(condenseArray))}`;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof debugValue !== 'object') {
|
||||||
|
return (msg += ` ${debugValue}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += '\n{';
|
||||||
|
|
||||||
|
const copy = klona(metadata);
|
||||||
|
traverse(copy).forEach(function (value) {
|
||||||
|
if (typeof this?.key === 'symbol') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let _parentKey = '';
|
||||||
|
const parent = this.parent;
|
||||||
|
|
||||||
|
if (typeof parent?.key !== 'symbol' && parent?.key) {
|
||||||
|
_parentKey = parent.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parentKey = `${parent && parent.notRoot ? _parentKey + '.' : ''}`;
|
||||||
|
|
||||||
|
const tabs = `${parent && parent.notRoot ? ' ' : ' '}`;
|
||||||
|
|
||||||
|
const currentKey = this?.key ?? 'unknown';
|
||||||
|
|
||||||
|
if (this.isLeaf && typeof value === 'string') {
|
||||||
|
const truncatedText = truncateLongStrings(value);
|
||||||
|
msg += `\n${tabs}${parentKey}${currentKey}: ${JSON.stringify(truncatedText)},`;
|
||||||
|
} else if (this.notLeaf && Array.isArray(value) && value.length > 0) {
|
||||||
|
const currentMessage = `\n${tabs}// ${value.length} ${currentKey.replace(/s$/, '')}(s)`;
|
||||||
|
this.update(currentMessage, true);
|
||||||
|
msg += currentMessage;
|
||||||
|
const stringifiedArray = value.map(condenseArray);
|
||||||
|
msg += `\n${tabs}${parentKey}${currentKey}: [${stringifiedArray}],`;
|
||||||
|
} else if (this.isLeaf && typeof value === 'function') {
|
||||||
|
msg += `\n${tabs}${parentKey}${currentKey}: function,`;
|
||||||
|
} else if (this.isLeaf) {
|
||||||
|
msg += `\n${tabs}${parentKey}${currentKey}: ${value},`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
msg += '\n}';
|
||||||
|
return msg;
|
||||||
|
} catch (e) {
|
||||||
|
return (msg += `\n[LOGGER PARSING ERROR] ${e.message}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue