mirror of
https://github.com/labring/FastGPT.git
synced 2025-12-25 20:02:47 +00:00
Some checks are pending
Document deploy / sync-images (push) Waiting to run
Document deploy / generate-timestamp (push) Blocked by required conditions
Document deploy / build-images (map[domain:https://fastgpt.cn suffix:cn]) (push) Blocked by required conditions
Document deploy / build-images (map[domain:https://fastgpt.io suffix:io]) (push) Blocked by required conditions
Document deploy / update-images (map[deployment:fastgpt-docs domain:https://fastgpt.cn kube_config:KUBE_CONFIG_CN suffix:cn]) (push) Blocked by required conditions
Document deploy / update-images (map[deployment:fastgpt-docs domain:https://fastgpt.io kube_config:KUBE_CONFIG_IO suffix:io]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / get-vars (push) Waiting to run
Build FastGPT images in Personal warehouse / build-fastgpt-images (map[arch:amd64 runs-on:ubuntu-24.04]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / build-fastgpt-images (map[arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / release-fastgpt-images (push) Blocked by required conditions
* perf: html2md * perf: index * Add model log * update next version * log index
172 lines
4.8 KiB
TypeScript
172 lines
4.8 KiB
TypeScript
import dayjs from 'dayjs';
|
|
import chalk from 'chalk';
|
|
import { LogLevelEnum } from './log/constant';
|
|
import { connectionMongo } from '../mongo/index';
|
|
import { getMongoLog } from './log/schema';
|
|
import { getLogger } from '../otel/log';
|
|
|
|
export enum EventTypeEnum {
|
|
outLinkBot = '[Outlink bot]',
|
|
feishuBot = '[Feishu bot]',
|
|
wxOffiaccount = '[Offiaccount bot]'
|
|
}
|
|
|
|
const logger = getLogger();
|
|
|
|
const logMap = {
|
|
[LogLevelEnum.debug]: {
|
|
levelLog: chalk.green('[Debug]')
|
|
},
|
|
[LogLevelEnum.info]: {
|
|
levelLog: chalk.blue('[Info]')
|
|
},
|
|
[LogLevelEnum.warn]: {
|
|
levelLog: chalk.yellow('[Warn]')
|
|
},
|
|
[LogLevelEnum.error]: {
|
|
levelLog: chalk.red('[Error]')
|
|
}
|
|
};
|
|
const envLogLevelMap: Record<string, number> = {
|
|
debug: LogLevelEnum.debug,
|
|
info: LogLevelEnum.info,
|
|
warn: LogLevelEnum.warn,
|
|
error: LogLevelEnum.error
|
|
};
|
|
|
|
const { LOG_LEVEL, STORE_LOG_LEVEL, SIGNOZ_STORE_LEVEL } = (() => {
|
|
const LOG_LEVEL = (process.env.LOG_LEVEL || 'info').toLocaleLowerCase();
|
|
const STORE_LOG_LEVEL = (process.env.STORE_LOG_LEVEL || '').toLocaleLowerCase();
|
|
const SIGNOZ_STORE_LEVEL = (process.env.SIGNOZ_STORE_LEVEL || 'warn').toLocaleLowerCase();
|
|
|
|
return {
|
|
LOG_LEVEL: envLogLevelMap[LOG_LEVEL] ?? LogLevelEnum.info,
|
|
STORE_LOG_LEVEL: envLogLevelMap[STORE_LOG_LEVEL] ?? 99,
|
|
SIGNOZ_STORE_LEVEL: envLogLevelMap[SIGNOZ_STORE_LEVEL] ?? LogLevelEnum.warn
|
|
};
|
|
})();
|
|
|
|
/**
|
|
* Sanitize object to prevent circular references for BSON serialization
|
|
* Remove properties that may contain circular references
|
|
*/
|
|
const sanitizeObjectForBSON = (obj: Record<string, any>): Record<string, any> => {
|
|
try {
|
|
// Use JSON stringify with replacer to handle circular references
|
|
const seen = new WeakSet();
|
|
const sanitized = JSON.parse(
|
|
JSON.stringify(obj, (key, value) => {
|
|
// Handle circular references
|
|
if (typeof value === 'object' && value !== null) {
|
|
if (seen.has(value)) {
|
|
return '[Circular Reference]';
|
|
}
|
|
seen.add(value);
|
|
}
|
|
|
|
// Remove known problematic properties from axios config
|
|
if (key === 'config' && value && typeof value === 'object') {
|
|
return {
|
|
method: value.method,
|
|
url: value.url,
|
|
baseURL: value.baseURL,
|
|
headers: value.headers,
|
|
timeout: value.timeout,
|
|
responseType: value.responseType
|
|
};
|
|
}
|
|
|
|
// Remove functions and other non-serializable values
|
|
if (typeof value === 'function' || typeof value === 'symbol') {
|
|
return undefined;
|
|
}
|
|
|
|
return value;
|
|
})
|
|
);
|
|
return sanitized;
|
|
} catch (error) {
|
|
// If sanitization fails, return a safe fallback
|
|
return {
|
|
error: 'Failed to sanitize object',
|
|
originalKeys: Object.keys(obj)
|
|
};
|
|
}
|
|
};
|
|
|
|
/* add logger */
|
|
export const addLog = {
|
|
log(level: LogLevelEnum, msg: string, obj: Record<string, any> = {}) {
|
|
if (level < LOG_LEVEL) return;
|
|
|
|
const stringifyObj = JSON.stringify(obj);
|
|
const isEmpty = Object.keys(obj).length === 0;
|
|
|
|
console.log(
|
|
`${logMap[level].levelLog} ${dayjs().format('YYYY-MM-DD HH:mm:ss')} ${msg} ${
|
|
level !== LogLevelEnum.error && !isEmpty ? stringifyObj : ''
|
|
}`
|
|
);
|
|
|
|
level === LogLevelEnum.error && console.error(obj);
|
|
|
|
if (logger && level >= SIGNOZ_STORE_LEVEL) {
|
|
logger.emit({
|
|
severityNumber: level.valueOf(),
|
|
severityText: ['debug', 'info', 'warn', 'error'][level],
|
|
body: {
|
|
msg,
|
|
obj
|
|
}
|
|
});
|
|
}
|
|
|
|
// store log
|
|
if (level >= STORE_LOG_LEVEL && connectionMongo.connection.readyState === 1) {
|
|
(async () => {
|
|
try {
|
|
// Sanitize metadata to prevent circular reference errors
|
|
const safeMetadata = sanitizeObjectForBSON(obj);
|
|
|
|
await getMongoLog().create({
|
|
text: msg,
|
|
level,
|
|
metadata: safeMetadata
|
|
});
|
|
} catch (error) {
|
|
console.error('store log error', error);
|
|
}
|
|
})();
|
|
}
|
|
},
|
|
debug(msg: string, obj?: Record<string, any>) {
|
|
this.log(LogLevelEnum.debug, msg, obj);
|
|
},
|
|
info(msg: string, obj?: Record<string, any>) {
|
|
this.log(LogLevelEnum.info, msg, obj);
|
|
},
|
|
warn(msg: string, obj?: Record<string, any>) {
|
|
this.log(LogLevelEnum.warn, msg, obj);
|
|
},
|
|
error(msg: string, error?: any) {
|
|
this.log(LogLevelEnum.error, msg, {
|
|
...(error?.data && { data: error?.data }),
|
|
message: error?.message || error,
|
|
stack: error?.stack,
|
|
...(error?.config && {
|
|
config: {
|
|
headers: error.config.headers,
|
|
url: error.config.url,
|
|
data: error.config.data
|
|
}
|
|
}),
|
|
...(error?.response && {
|
|
response: {
|
|
status: error.response.status,
|
|
statusText: error.response.statusText
|
|
}
|
|
})
|
|
});
|
|
}
|
|
};
|