尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FastGPT 统一日志体系实战指南:从 `@fastgpt/service/common/logger` 到 OTEL 可观测性

FastGPT 统一日志体系实战指南:从 `@fastgpt/service/common/logger` 到 OTEL 可观测性 FastGPT 统一日志体系实战指南从fastgpt/service/common/logger到 OTEL 可观测性【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT导读FastGPT 作为基于 LLM 的知识库问答与可视化 AI 工作流平台后端由知识库解析、向量训练、工作流调度、对话续跑、对象存储等多个高并发模块组成日志质量直接决定线上问题的定位效率。本文以仓库内.agents/design/common/logger/index.mdFastGPT Logger 使用规范为骨架结合packages/service/common/logger与sdk/otel的真实实现系统讲解 FastGPT 后端统一日志的统一入口、分类体系、等级规范、结构化写法、请求链路上下文、错误记录、敏感信息治理与 OTEL 导出配置帮助你在开发插件、调试知识库队列或排查工作流故障时写出可检索、可聚合、可追踪的规范日志。1. 为什么需要统一日志入口FastGPT 后端基于 Next.js API Routes 承载成百上千个接口与后台任务如果每个模块各自console.*输出日志会存在三个问题没有统一级别过滤、无法携带请求上下文、无法接入 OpenTelemetry 采集。因此项目在 packages/service/common/logger/index.ts 建立了唯一出口它再向fastgpt-sdk/otel/logger转发export { configureLogger, disposeLogger, getLogger } from ./client; export { withContext, withCategoryPrefix } from fastgpt-sdk/otel/logger; export { LogCategories } from ./categories; export type { LogCategory } from ./categories;实际初始化与获取逻辑位于 client.tsexport async function configureLogger() { const { serviceEnv } await import(../../env); await configureLoggerFromEnv({ env: serviceEnv, defaultCategory: [system], defaultServiceName: fastgpt-client, sensitiveProperties: [fastgpt] }); }从源码可见三个关键约定defaultCategory为[system]即getLogger()不传 category 时默认归属系统级defaultServiceName为fastgpt-client对应LOG_OTEL_SERVICE_NAME默认值sensitiveProperties: [fastgpt]会把带fastgpt属性标记的日志从 OTEL 链路中过滤掉详见第 7 节。在仓库中这一入口已被基础设施层广泛使用例如 mongo/index.ts 的getLogger(LogCategories.INFRA.MONGO)、s3/buckets/base.ts 的LogCategories.INFRA.S3、dingtalk/accessToken.ts 的LogCategories.MODULE.OUTLINK.DINGTALK以及 rateLimit/core.ts 的LogCategories.INFRA.REDIS验证了「模块持有一个带分类的 logger 实例」这一统一模式。初始化时机与单例约束configureLogger()只需要在服务启动/入口处调用一次内部通过configureLoggerFromEnv完成 Sink输出管道组装。重复调用不会导致重复输出但建议放在应用初始化流程的最前面保证后续所有模块拿到的 logger 都已具备完整配置。2. Category 分类规范内置LogCategories规范明确要求必须使用项目内置的LogCategories禁止自定义字符串数组。完整定义见 categories.ts其层级结构与选型建议对应如下顶层分类含义常用子类节选LogCategories.SYSTEM系统级初始化、全局状态SYSTEM.UPGRADE.V4163升级迁移、NETWORKLogCategories.INFRA.*数据库、缓存、对象存储、队列等基础设施MONGO、POSTGRES、REDIS、VECTOR、QUEUE、S3、OTEL、FILE、WORKERLogCategories.HTTP.*HTTP 请求、响应、错误REQUEST、RESPONSE、ERRORLogCategories.MODULE.*业务模块参考pages/api路径省略core/support前缀见下方展开LogCategories.ERROR跨模块错误汇总[error]LogCategories.EVENT.*事件/埋点类日志EVENT.TRACKLogCategories.MODULE的业务模块子分类是重头戏源码中覆盖了WORKFLOW含AI、DATASET、DISPATCH、INTERACTIVE、OPTIMIZE_CODE、STATUS、TOOLS、CODE_SANDBOX、APP含EVALUATION、MCP_TOOLS、TEMPLATE等、DATASET含QUEUES、TRAINING、FILE_PARSE、EMBEDDING、QA、IMAGE_PARSE、IMAGE_INDEX、INDEX_EXTEND、LLM_PARGRAPH、WEB_SYNC、API_DATASET、AI含AGENT、TOOL_CALL、LLM、LLM_COMPRESS、RERANK、SANDBOX、EMBEDDING等、AGENT_SKILLS、USER、WALLET、TEAM、OUTLINK钉钉/飞书/企微/微信、CHAT含RESUME、QUOTE、RECORD、INPUT_GUIDE等、PERMISSION、PLUGIN、MCPAPP/CLIENT/SERVER、OPENAPI、MARKETING。这里有一个重要的命名原则业务模块分类参考pages/api的路径结构并省略core/support前缀。比如知识库向量队列任务属于pages/api/core/dataset/...对应分类即为LogCategories.MODULE.DATASET.QUEUEScore/ai/...相关逻辑则归类到LogCategories.MODULE.AI.*。这样保证了「看到分类就能定位代码目录」的检索一致性。当现有类别不足时在 categories.ts 中补充新分类保持层级语义清晰如INFRA → 具体组件、MODULE → 业务域 → 子功能避免层级过深或过宽注意LogCategory联合类型会自动把LogCategories.MODULE的每个叶子节点收窄为可推导类型补充分类后无需手动维护类型。3. 日志等级使用建议日志底层基于logtape/logtape等级枚举定义在 env.const.tsexport const LogLevelSchema z.enum([trace, debug, info, warning, error, fatal]);等级使用建议等级适用场景trace极高频、细粒度流程追踪默认仅开发环境开启生产建议关闭debug调试信息、队列长度、循环状态、重试过程info关键流程节点、成功状态、启动与完成warn可恢复异常、可忽略的异常条件error失败、异常退出、需要定位的问题fatal不可恢复错误通常伴随进程退出结合源码等级过滤由 sinks.ts 的levelFilter通过mapLevelToSeverityNumber(record.level) mapLevelToSeverityNumber(level)实现即只输出不低于设定等级的日志。控制台默认最低等级是debugOTEL 默认是info因此开发期能看到的trace日志在生产 OTEL 链路里默认不会出现需要在LOG_OTEL_LEVEL显式调低。4. 结构化日志稳定消息 结构化字段规范核心日志由「稳定消息 结构化字段」组成不要在消息字符串里拼大段 JSON。推荐写法logger.info(Schedule trigger scan completed, { dueCount, durationMs });不推荐logger.info(Scan completed: ${JSON.stringify({ dueCount, durationMs })});这样做的好处是稳定消息可被文本检索精确命中结构化字段可被日志平台聚合、过滤与告警如按teamId分组、按durationMs排序。自动补齐{*}的底层实现「消息 字段」之所以能变成msg: {*}是因为 sdk/otel/src/logger/client.ts 中getLogger返回了一个 Proxy 包装的 loggerif (typeof firstArg string) { if ( typeof secondArg object secondArg verbose in secondArg typeof secondArg.verbose boolean !secondArg.verbose ) { const { verbose: _verbose, ...properties } secondArg; return fn.call(target, firstArg, properties); } return fn.call(target, ${firstArg}: {*}, secondArg); }即只要以「字符串消息 对象字段」两参形式调用且字段中没有verbose: false就会自动格式化为消息: {*}。如果不希望追加{*}例如请求日志本身已含全部信息显式传verbose: falselogger.info(Request received, { verbose: false, requestId, method, url });verbose是保留字会被解构剥离不会作为日志字段输出。5. 请求链路与上下文withContext注入requestId服务端推荐通过withContext注入requestId等上下文使同一请求链路上的多条日志自动关联import { withContext } from fastgpt/service/common/logger; return withContext({ requestId }, async () { logger.info(Request received, { requestId, method, url }); });withContext与withCategoryPrefix均由 sdk/otel/src/logger/index.ts 从logtape/logtape转发导出属于 logtape 的异步上下文能力在上下文作用域内产生的日志会自动携带requestId属性无需在每个调用点手动透传。API 入口的统一处理Next.js API 入口侧原文档所指packages/service/common/middle/entry.ts对应实现为 http/entry.ts通过createApiEntry管线统一处理日志、追踪、错误与默认 JSON 响应其中使用randomUUID()生成requestId并调用withContext注入路由归一化函数normalizeRouteSegmenthttp/entry.ts会将形如24 位 ObjectId、UUID、纯数字段等 ID 类路径段替换为:id避免teamId/datasetId等高频变化的路径碎片污染日志检索维度统一抛出ZodError/ApiRequestInputParseError等结构化错误配合setSpanError、withActiveSpan完成 trace 关联。因此业务代码不需要重复打印请求进/出日志只需在业务逻辑内部打印关键节点。6. 错误日志规范统一约定使用error字段记录错误对象并补充业务上下文。try { await doSomething(); } catch (error) { logger.error(Do something failed, { error, appId, userId }); throw error; }要避免的反模式用err、e等不一致的字段名——破坏日志平台聚合跨模块无法统一检索只记录error.message——丢失堆栈stack无法定位调用链捕获后既不记录也不抛出——吞掉异常会导致问题静默。正确姿势是「记录完整错误对象 业务上下文 重新抛出或由上层统一处理」。error字段对象由日志平台/格式化器展开同时保留appId、userId等可检索维度。7. 敏感信息与 OTEL 导出治理禁止记录token、密钥、密码、完整聊天内容、隐私数据等。FastGPT 作为承载真实用户对话与知识库内容的平台日志一旦外泄后果严重因此敏感治理是硬性要求。如确需记录用于调试两条处理路径脱敏或截断只保留必要片段添加fastgpt: true属性标记避免 OTEL 导出。logger.warn(Payload truncated for debug, { fastgpt: true, payloadPreview: payload.slice(0, 200) });其底层机制在 sinks.tsOTEL Sink 的过滤器会检查日志记录属性只要属性中存在sensitiveProperties列表中的键此处为fastgpt该条日志就不会进入 OTEL 导出器sinks.otel withFilter(getOpenTelemetrySink({...}), (record) { const properties record.properties ?? {}; return ( levelFilter(record, otelOptions.level) !sensitiveProperties.some((property) property in properties) ); });注意fastgpt: true只拦截 OTEL 导出控制台输出仍然可见适合「本地/开发排查但不污染生产可观测链路」的场景。生产环境请务必保证敏感信息在写入日志前已完成脱敏。8. 配置项环境变量日志系统由configureLogger()读取环境变量schema 定义于 env.ts环境变量类型默认值说明LOG_ENABLE_CONSOLEbooleantrue是否开启控制台输出LOG_CONSOLE_LEVELenumdebug控制台最低等级trace/debug/info/warning/error/fatalLOG_ENABLE_OTELbooleanfalse是否开启 OTEL 日志导出LOG_OTEL_LEVELenuminfoOTEL 最低等级LOG_OTEL_SERVICE_NAMEstringfastgpt-clientOTEL 服务名LOG_OTEL_URLurl可选OTEL 收集器地址补充两个源码确认的细节OTEL 默认关闭LOG_ENABLE_OTELfalse开启后若未配置LOG_OTEL_URLsdk 侧 env.ts 会回落到http://localhost:4318/v1/logsOTLP/HTTP v1 logs 端点适用于本地部署 OpenTelemetry Collector 的场景非法等级值会被 parseLogLevel 静默回退到默认值不会导致进程启动失败但LOG_ENABLE_OTELtrue时若缺少 serviceNameSink 组装阶段会显式抛错见 sinks.ts服务名是 OTEL 标识的必填项。Sink 缓冲与性能控制台与 OTEL Sink 共用了 sinks.ts 定义的高性能参数bufferSize: 8192、flushInterval: 5000毫秒、nonBlocking: true、lazy: true。这意味着日志写入不会阻塞业务线程而是批量异步刷出——因此不要依赖日志顺序来推断业务时序排查并发问题时优先使用requestId/上下文关联。控制台格式化器关闭了图标与着色输出为纯文本便于在容器日志系统中稳定解析。9. 完整示例基础设施监控与业务模块组合综合以上规范给出一个覆盖「初始化 分类 结构化 错误处理 上下文」的完整示例import { configureLogger, getLogger, LogCategories, withContext } from fastgpt/service/common/logger; // 服务启动时只初始化一次 await configureLogger(); // 基础设施层监控 Mongo change stream const mongoLogger getLogger(LogCategories.INFRA.MONGO); mongoLogger.info(Mongo change stream watch started); try { await watchMongo(); } catch (error) { mongoLogger.error(Mongo watch failed, { error, collection: system_config }); throw error; } // 业务模块层带请求上下文的知识库向量队列任务 return withContext({ requestId, teamId }, async () { const queueLogger getLogger(LogCategories.MODULE.DATASET.QUEUES); queueLogger.info(Vector queue task started, { datasetId, queueSize }); queueLogger.debug(Queue processing, { batchIndex, retryCount }); // ...业务逻辑 });对应生产环境可参考的.env片段# 控制台输出开发默认开启 LOG_ENABLE_CONSOLEtrue LOG_CONSOLE_LEVELdebug # OTEL 日志导出对接 Collector / 可观测平台 LOG_ENABLE_OTELtrue LOG_OTEL_LEVELinfo LOG_OTEL_SERVICE_NAMEfastgpt-prod LOG_OTEL_URLhttp://otel-collector:4318/v1/logs10. 常见误区速查误区正确做法依据用console.log/info/error直接输出从fastgpt/service/common/logger取 logger统一入口约定见 index.tsgetLogger([custom, tag])自定义数组使用内置LogCategories不足时在 categories.ts 扩展分类规范第 2 节把 JSON 拼进消息字符串使用「稳定消息 结构化字段」两参形式Proxy 自动补{*}见 client.ts用err/e记录错误统一{ error, ...上下文 }保留堆栈并重新抛出错误日志规范第 6 节把 token、聊天内容写进日志脱敏/截断调试用fastgpt: true标记隔离 OTEL 导出敏感治理第 7 节见 sinks.ts在每个 API 里打印请求进出日志交给 http/entry.ts 的createApiEntry统一处理请求链路第 5 节遵循这套规范后FastGPT 的日志将具备三个可量化能力分类可导航Category ↔ 代码目录一一对应、链路可追踪requestId OTEL、问题可聚合结构化字段 统一等级过滤无论是本地docker logs排查还是对接 OpenTelemetry Collector 构建集中可观测平台都能做到开箱即用。【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表