Egg.js 日志系统
1. Egg 企业级日志系统解决什么问题Egg 内置日志能力主要由egg-logger提供目标不是简单地console.log而是解决 Web 服务中的如下问题1.日志分级egg 日志级别级别含义适合场景DEBUG调试日志最详细给开发者看的细节本地开发、排查问题INFO普通信息日志记录正常业务流程比如“订单创建成功”WARN警告日志出现异常苗头但不一定导致请求失败ERROR错误日志程序异常、请求失败、服务调用失败NONE不输出日志关闭日志输出日志级别的控制可通过如下进行配置exports.logger{level:INFO,// 默认INFO只打印INFO、WARN、ERROR如果配置WARN则只打印WARN、ERROR其他类推};2.请求上下文日志在请求处理中使用ctx.logger日志里会自动带上请求相关信息例如在代码里写的是ctx.logger.info([AgentChat] chatStream 用户请求入参: %j,{sessionId,message});但是在日志文件里会生成如下2026-07-26 11:22:06,879 INFO 10837 [-/::1/723f86b7-0038-48a9-987f-6e4158c55ab4/342.335ms POST /api/agent/chat/stream] [OpenClaw chatStream] 请求参数 {endpoint:http://dev1-ge.back.jd.com/oxygen/api/oxygen/chat/stream,sessionId:session_xxxx-ec35-4210-937c-xxxx,clientRequestId:req_516de26c-89a1-461b-8f8c-80e9bb5fd3e3}字段含义如下字段示例含义时间2026-07-26 09:54:26,351日志打印时间精确到毫秒日志级别INFO日志等级表示普通信息不是错误进程 ID77817当前 Node/Egg 进程的 PID日志分类[egg:lib:core:logger]打印日志的模块或命名空间日志内容init all loggers with options...具体事件说明3.错误日志集中收敛任意 logger 调用.error()打印的错误日志都会额外进入统一错误日志文件common-error.log。这方便排查线上异常。4.应用日志、框架日志、Agent 日志分离应用业务日志和框架内部日志不会混在一起。5.自动切割默认按天切割。也支持按小时、按文件大小切割。6.高性能默认不是每条日志都立刻写磁盘而是先写入内存 buffer再定时刷盘。2. Egg 日志分类Egg 里最核心的日志可以分成这几类分类Logger 对象常见使用入口默认日志文件主要用途备注应用业务日志appLogger / loggerctx.logger/app.logger${appInfo.name}-web.log例如server-web.log业务代码最常用的日志ctx.logger用于请求内app.logger用于应用级逻辑框架/插件日志coreLoggerctx.coreLogger/app.coreLoggeregg-web.logEgg 框架内部、插件日志普通业务代码一般不用写插件或框架扩展时更常用统一错误日志errorLogger一般不直接调用由所有 logger 的.error()自动汇总common-error.log汇总所有ERROR级别日志方便排查异常例如ctx.logger.error(err)会同时写入业务日志和common-error.logAgent 进程日志agentLoggeragent.logger/agent.coreLoggeregg-agent.logAgent 进程中的日志用于 Egg 多进程模型里的 Agent 进程自定义日志自定义 Logger例如payLogger/auditLoggerapp.getLogger(xxx)/ctx.getLogger(xxx)自定义文件例如pay.log独立业务日志如支付、审计、安全日志通过config.customLogger配置调用.error()也会汇总到common-error.log插件专用日志插件自定义 Logger例如scheduleLogger插件提供的 logger例如 schedule 插件 logger插件自定义例如egg-schedule.log某些插件自己的运行日志不是 Egg 基础必有日志是否存在取决于是否启用对应插件简版记忆ctx.logger / app.logger → 业务日志 → ${appInfo.name}-web.log ctx.coreLogger / app.coreLogger → 框架、插件日志 → egg-web.log 所有 logger.error(...) → 额外复制到 common-error.log agent.logger → Agent 进程日志 → egg-agent.log 自定义 logger → 自定义业务日志 → 自定义文件 scheduleLogger → schedule 插件日志 → egg-schedule.logEgg 默认把日志放在${appInfo.root}/logs/${appInfo.name}本地和单测环境的root是项目目录生产等其他环境的root是 HOME 目录name来自package.json。可以这样自定义日志目录// config/config.default.js exports.logger { dir: /path/to/your/custom/log/dir, };也可以自定义日志文件名// config/config.default.js module.exports appInfo { return { logger: { appLogName: ${appInfo.name}-web.log, coreLogName: egg-web.log, agentLogName: egg-agent.log, errorLogName: common-error.log, }, }; };3. 日志怎么打印3.1 请求处理中优先用ctx.loggerController、Service、Middleware 里处理一次请求时推荐用ctx.logger.info(some request data: %j, ctx.request.body); ctx.logger.warn(业务参数异常%j, ctx.query); ctx.logger.error(new Error(something wrong));为什么请求里推荐用ctx.logger因为它能带上请求上下文信息类似[userid/ip/traceId/12ms GET /api/user] message这样排查问题时可以知道哪个请求触发的日志请求耗时是多少请求路径是什么有没有 traceId 可以串联链路参数与格式化占位符ctx.logger.info([SessionController] 创建会话入口 %s,JSON.stringify({...}));第一个参数是格式化模板,%s是字符串占位符,第二个参数填进占位符位置。常用占位符:%s字符串、%d数字、%jJSON(自动序列化对象)。可简化:用%j省掉手动JSON.stringify:ctx.logger.info([SessionController] 创建会话入口 %j,{requestId,appId});3.2 应用级别用app.logger比如启动阶段、定时任务、应用级初始化逻辑// app.js module.exports app { app.logger.info(应用启动完成); app.logger.warn(某个配置缺失使用默认值); app.logger.error(new Error(启动阶段异常)); };3.3 框架/插件级别用coreLogger如果你是在写框架或插件不建议把框架内部日志打到业务日志里应该用app.coreLogger.info(plugin initialized); ctx.coreLogger.warn(framework warning);3.4 Agent 进程用agent.logger// agent.js module.exports agent { agent.logger.info(agent started); agent.logger.error(new Error(agent error)); };4. 错误日志要特别注意什么Egg 文档里有一个非常重要的建议ctx.logger.error(new Error(whoops));不要随便这样ctx.logger.error(something wrong);虽然字符串也能打印但如果你希望线上异常可追踪最好传Error对象。原因是Error对象有namemessagestackcause自定义属性源码中egg-logger会专门格式化Error输出完整堆栈相关实现可以看egg/packages/logger/src/utils.ts其中formatError()会把错误格式化成包含pid、hostname、stack 等信息的日志。5. 日志切割参考链接日志切割Egg 默认使用eggjs/logrotator进行日志切割。默认按天切割比如当前文件example-app-web.log到第二天会切成example-app-web.log.2026-07-24按大小切割例如egg-web.log超过 2GB 后切割const path require(path); module.exports appInfo { return { logrotator: { filesRotateBySize: [ path.join(appInfo.root, logs, appInfo.name, egg-web.log), ], maxFileSize: 2 * 1024 * 1024 * 1024, }, }; };按小时切割const path require(path); module.exports appInfo { return { logrotator: { filesRotateByHour: [ path.join(appInfo.root, logs, appInfo.name, common-error.log), ], }, }; };切割的定时任务(内置)Egg「约定优于配置」:插件把定时任务放在自己的app/schedule/目录,框架启动自动加载。位置:node_modules/eggjs/logrotator/dist/app/schedule/ ├── rotate_by_file.js → 按天切割 ├── rotate_by_size.js → 按大小切割 ├── rotate_by_hour.js → 按小时切割(默认关闭) └── clean_log.js → 删除过期日志任务文件cron触发时机干什么rotate_by_file.js1 0 0 * * *每天 00:00:01xxx.log→xxx.log.YYYY-MM-DD,建空文件clean_log.js0 0 * * *每天 00:00:00删除超过maxDays天的归档文件rotate_by_size.js每 60 秒轮询持续检查单文件超maxFileSize立即切cron 两种写法都支持:clean_log用标准 5 段(分 时 日 月 周),rotate_by_file用 6 段(最前多了秒)。这些任务本身就是 schedule 任务,所以会产生egg-schedule.log。保留天数与自动清理删除逻辑在clean_log.js的removeExpiredLogFiles:扫描日志目录所有文件;只挑后缀是日期格式的归档文件(如.2026-07-23);算过期线 今天往前推maxDays天;归档日期早于过期线的,直接fs.unlink删除。要点:只删带日期后缀的归档文件,永不删正在写入的活动文件。默认已开启清理,maxDays: 31(保留 31 天)。maxDays: 0表示永不删除、全部保留(才会无限堆积)。logrotator 默认配置logrotator:{disableRotateByDay:false,filesRotateByHour:null,hourDelimiter:-,filesRotateBySize:null,maxFileSize:50*1024*1024,// 50MBmaxFiles:10,// 按大小切割时最多保留数rotateDuration:60000,// 按大小轮询间隔 60smaxDays:31,// 保留天数,0 不删gzip:false,// 归档是否 gzip 压缩}自定义(在config/config.default.ts覆盖)config.logrotator{maxDays:7,// 只留 7 天maxFileSize:100*1024*1024,// 100MBgzip:true,// 归档压缩省空间};11. 源码视角Egg 日志初始化流程可以重点看这几个文件11.1 默认配置egg/packages/egg/src/config/config.default.ts这里定义config.logger { dir: path.join(appInfo.root, logs, appInfo.name), encoding: utf8, env: appInfo.env, level: INFO, consoleLevel: INFO, disableConsoleAfterReady: appInfo.env ! local appInfo.env ! unittest, outputJSON: false, buffer: true, appLogName: ${appInfo.name}-web.log, coreLogName: egg-web.log, agentLogName: egg-agent.log, errorLogName: common-error.log, coreLogger: {}, allowDebugAtProd: false, enableFastContextLogger: true, };11.2 创建 Loggersegg/packages/egg/src/lib/core/logger.ts这里会从app.config.logger读取配置创建EggLoggers生产环境保护 DEBUG应用 ready 后按配置关闭 console注册全局 logger应用关闭时清理全局 logger。11.3 Logger Manageregg/packages/logger/src/egg/loggers.ts这里创建errorLoggerloggercoreLoggercustom loggers并配置错误日志集中logger.duplicate(ERROR, concentrateLogger, { excludes: [console] });也就是说业务 logger 打一条 ERROR除了进入业务日志也会复制一份到common-error.log。12. 推荐实践12.1 业务请求日志ctx.logger.info(创建订单成功orderId%s, order.id);不要打印过大的对象// 不推荐 ctx.logger.info(request body: %j, ctx.request.body);如果 body 很大或有敏感字段应该筛选ctx.logger.info(创建订单请求%j, { userId: ctx.user.id, skuId: ctx.request.body.skuId, count: ctx.request.body.count, });12.2 错误日志推荐try { await service.doSomething(); } catch (err) { ctx.logger.error(err); throw err; }如果要补充上下文try { await service.pay(order); } catch (err) { ctx.logger.error([pay failed] orderId%s userId%s, order.id, ctx.user.id); ctx.logger.error(err); throw err; }12.3 不要滥用debugdebug适合开发和临时排查不适合长期在线上大量打开。12.4 不要在日志里打印敏感信息避免打印passwordtokencookie等12.5 自定义 logger 要克制只有当日志具有明确独立消费场景时才拆比如审计日志安全日志支付流水日志调度执行日志否则优先使用默认app.logger。13. 总结一句话Egg 的日志系统可以理解成业务代码调用 ctx.logger/app.logger ↓ EggLoggers 管理多个 logger ↓ 每个 logger 绑定多个 transporttransport负责判断当前日志级别是否应该输出 ↓ transport 根据日志级别、格式、上下文输出到文件/终端/JSON/远端 ↓ ERROR 日志额外集中到 common-error.log ↓ logrotator 负责日志切割

相关新闻

Spring AI Document类设计与企业级应用实践

Spring AI Document类设计与企业级应用实践

1. Spring AI Document核心功能解析在Spring AI框架中,Document类扮演着数据载体的关键角色。这个看似简单的POJO类实际上承载了AI模型处理过程中的结构化数据流转任务。我最近在几个企业级AI项目中深度使用了这个组件,发现其设计暗含了许多工程实践的智…

2026/7/27 6:49:19阅读更多 →
COMSOL细观多场耦合模拟隧道衬砌损伤演化

COMSOL细观多场耦合模拟隧道衬砌损伤演化

1. 项目背景与核心价值隧道衬砌结构在复杂地质环境中承受着热-湿-力多场耦合作用,传统宏观分析方法难以捕捉混凝土材料在细观尺度下的损伤演化机制。这个COMSOL案例通过建立细观尺度的多物理场耦合模型,实现了对混凝土衬砌结构损伤过程的精确模拟。我在实…

2026/7/27 6:49:19阅读更多 →
AI检测工具如何重塑内容创作生态与平台治理

AI检测工具如何重塑内容创作生态与平台治理

上周,一个做内容运营的朋友给我发来一条消息:“你看 Substack 那个新功能了吗?能直接告诉你一篇通讯稿有多少比例是 AI 写的。我们团队现在写东西都开始紧张了,生怕被标成‘高 AI 含量’。” 这条消息让我意识到,AI 检…

2026/7/27 6:49:19阅读更多 →
基于分层Q学习的无线通信抗干扰算法研究

基于分层Q学习的无线通信抗干扰算法研究

1. 项目概述 在无线通信领域,智能干扰已经成为通信安全的主要威胁之一。传统的固定频率干扰可以通过简单的跳频技术规避,但现代智能干扰机能够学习通信方的行为模式并动态调整干扰策略。面对这种挑战,我们开发了一种基于分层Q学习的联合抗干扰…

2026/7/27 9:50:24阅读更多 →
AP0316内置3W功放:扬声器麦克风共腔下的AEC与DSP协同设计

AP0316内置3W功放:扬声器麦克风共腔下的AEC与DSP协同设计

1. 集成设计的优势与挑战传统语音处理系统通常由分立组件构成:麦克风阵列 语音处理DSP 音频功放 供电管理。这种分离式架构的优点是各模块可以独立选型和调试,但缺点同样明显——物料清单(BOM)复杂、PCB布线密集、信号完整性挑…

2026/7/27 9:50:24阅读更多 →
A-29P模块:神经网络时频掩码与AEC协同在免提通话中的优化

A-29P模块:神经网络时频掩码与AEC协同在免提通话中的优化

1. 应用场景与技术挑战免提全双工通话设备(车载蓝牙通话、会议系统、矿山调度呼叫、可视门铃等)的核心挑战在于:在扬声器播放声音的同时,麦克风必须可靠地采集近端说话人语音而不被扬声器回音和环境噪声淹没。传统的单通道降噪方案…

2026/7/27 9:50:24阅读更多 →
AR-1106声源定位模组:TDOA算法与9600串口协议在摄像头联动中的应用

AR-1106声源定位模组:TDOA算法与9600串口协议在摄像头联动中的应用

1. 声源定位的应用价值与技术路线在AI追踪摄像头、声源跟随监控摄像头、语音机器人等应用中,系统不仅需要听到声音,还需要知道声音从哪里来——声源定位(Direction of Arrival,DOA)能力是实现声音引导目标追踪的核心。…

2026/7/27 9:50:24阅读更多 →
如何用XXMI启动器5分钟打造专属游戏体验:终极多游戏模组管理革命

如何用XXMI启动器5分钟打造专属游戏体验:终极多游戏模组管理革命

如何用XXMI启动器5分钟打造专属游戏体验:终极多游戏模组管理革命 【免费下载链接】XXMI-Launcher Modding platform for GI, HSR, WW and ZZZ 项目地址: https://gitcode.com/gh_mirrors/xx/XXMI-Launcher 在当今游戏模组管理的复杂世界中,XXMI启…

2026/7/27 9:50:24阅读更多 →
直通滤波算法原理与点云处理实践

直通滤波算法原理与点云处理实践

1. 直通滤波算法概述 直通滤波(Passthrough Filter)是点云处理中最基础且实用的滤波算法之一,主要用于在三维空间中对点云数据进行快速裁剪。它的核心思想是设定一个或多个轴向的数值范围,仅保留该范围内的点云数据,其…

2026/7/27 9:48:24阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/27 1:14:34阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/27 1:14:52阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/27 1:14:56阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:24阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:24阅读更多 →
2007-2023年各市区县生态文明建设示范区DID

2007-2023年各市区县生态文明建设示范区DID

数据简介 自改革开放以来,我国依赖高投入、高资源消耗和高污染等传统发展模式实现了经济短期内的快速增长, 然而这也导致了严重的生态环境危机。因此,国家有力于推动企业高质量经济发展,协同生态保护的方针,从而从201…

2026/7/27 0:00:24阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/25 23:03:25阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/26 19:05:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/26 19:05:21阅读更多 →