日志染色方案

本文介绍了在服务增多和流量增长背景下,如何通过日志染色方案来优化微服务架构的日志定位和成本控制。方案利用Apollo配置规则,针对不同场景动态打印日志,通过网关拦截器和应用级别的拦截,实现高效问题排查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述
    服务增多,流量不断的增长,日志存储所需要的空间和存储成本也对应的增加
    当前系统架构逐步的走向微服务化,服务之间的调用交叉复杂,排查问题难度也是不断地增加,需要跨服务,跨系统来进行排查,日志定位,多系统协调
    对研发来说,生产和线上问题为第一要务。如何减少排查时间,提高定位速度,快速的勘察原因并解决问题,较少日志输出,节约成本。故提出了日志染色方案。
二、日常使用场景
    由于Apollo是热生效,通过Apollo实时修改配置,实现动态控制请求链路/应用日志打印
1、场景:特定URL的请求,会打印debug类型日志,甚至级别更低的日志
2、场景:特殊cookies的请求,会打印debug甚至级别更低的日志
3、场景:特殊请求参数的请求,会打印debug甚至级别更低的日志
4、场景:特殊请求头请求,会打印debug。。。。。。。
5、场景:异常但是属于正常场景,会打印warn甚至级别更低的日志
5、场景:异常需要特殊关注的日志,会打印error甚至级别更高的日志

三、方案总体设计
1、日常将日志设置为debgu级别,默认不会打印
2、在Apollo上配置日志打印规则,满足打印规则的日志请求会打印进dubug日志级别中
3、请求来到网关或者过滤器,检查规则,若满足在Apollo配置的规则,则打印日志
4、规则往下级调用应用传递,继续打印,完成整条链路日志的打印
5、应用日志上传日志云或者ELK,查找整条日志,方便查找问题
四、方案详细设计
网关设计:
    网关增加拦截器,拦截配置有规则的请求,并向下级应用传递日志打印请求头 X-TRACE-LOG-ID
拦截请求头规则 HeardersColorGatewayFilterFactory
拦截参数规则 ParamsColorGatewayFilterFactory
拦截Cookies规则 CookiesColorGatewayFilterFactory
截URL规则 URLColorGatewayFilterFactory
应用设计:
    实现带有 X-TRACE-LOG-ID打印日志:
1、应用启动将服务条件的Log设置成debug模式
2、增加拦截器请求,如果请求头含有X-TRACE-LOG-ID,则将请求头设置到MDC中
3、增加日志拦截器debug日志默认不打印,MDC含有请求头X-TRACE-LOG-ID才打印
五、具体实现

<think>我们讨论的是在Midway.js中实现代码染色功能。代码染色(Code Coloring)通常指的是在日志中为不同级别的日志信息添加颜色,以便于开发者快速识别日志级别(如错误、警告、信息等)。在Midway.js中,我们可以通过配置日志的格式化器(formatter)来实现。 Midway.js使用`@midwayjs/logger`作为日志模块,它基于Winston,因此我们可以利用Winston的格式化功能来实现代码染色。 ### 实现步骤 #### 1. 安装依赖 确保已经安装了`@midwayjs/logger`和`winston`(通常Midway自带,如果没有则安装): ```bash npm install @midwayjs/logger winston ``` #### 2. 配置日志格式化 在配置文件(如`src/config/config.default.ts`)中,我们可以通过`midwayLogger`配置项来自定义日志格式,包括颜色。 ```typescript import { MidwayConfig } from '@midwayjs/core'; import { format } from 'winston'; export default { midwayLogger: { default: { // 其他配置... format: format.combine( format.colorize(), // 启用颜色 format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.printf(({ level, message, timestamp }) => { return `${timestamp} [${level}] ${message}`; }) ), // 注意:如果使用文件传输,颜色代码可能会被写入文件,通常控制台输出才需要颜色 transports: [ // 控制台输出 { type: 'console', // 可以在这里单独为控制台设置格式 // 因为文件不需要颜色,所以颜色格式化通常只加在控制台传输上 }, // 文件输出(不需要颜色) // ...其他传输配置 ] } } } as MidwayConfig; ``` #### 3. 自定义格式化器(可选) 如果你需要更复杂的颜色方案,可以自定义一个格式化器。例如,为不同日志级别设置不同的颜色: ```typescript import { format } from 'winston'; const customFormat = format.combine( format.colorize({ all: true, // 为整个消息着色 level: true, // 为日志级别着色 message: true, // 为消息着色 colors: { info: 'green', warn: 'yellow', error: 'red', debug: 'blue' } }), format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.printf(({ level, message, timestamp }) => { return `${timestamp} [${level}] ${message}`; }) ); ``` 然后在配置中引用这个自定义格式化器。 #### 4. 配置传输器(Transports) 注意,颜色代码通常只在控制台(console)输出时有用,写入文件时颜色代码反而会干扰阅读。因此,我们通常只在控制台传输器上启用颜色。 在配置中,我们可以为不同的传输器设置不同的格式: ```typescript export default { midwayLogger: { default: { // ...其他配置 transports: [ { type: 'console', format: customFormat // 使用带颜色的格式 }, { type: 'file', dir: './logs', fileLogName: 'app.log', format: format.combine( // 文件传输不使用颜色 format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.printf(({ level, message, timestamp }) => { return `${timestamp} [${level}] ${message}`; }) ) } ] } } } as MidwayConfig; ``` #### 5. 使用日志 在代码中,正常使用日志即可: ```typescript import { Controller, Get, Inject } from '@midwayjs/core'; import { Logger } from '@midwayjs/logger'; @Controller('/') export class HomeController { @Inject() logger: Logger; @Get('/') async home() { this.logger.debug('This is a debug message'); this.logger.info('This is an info message'); this.logger.warn('This is a warning message'); this.logger.error('This is an error message'); return 'Hello Midway!'; } } ``` ### 效果 运行应用后,在控制台将看到不同级别的日志以不同颜色显示。 ### 注意事项 1. 颜色功能依赖于`winston`的`format.colorize`,它会在字符串中添加ANSI颜色代码,这些代码在支持ANSI的控制台(如终端)中会显示颜色,但在不支持的环境(如文件)中会显示为乱码。 2. 在生产环境中,通常我们只希望控制台输出带颜色,而文件日志则不需要颜色代码。 ### 生产环境配置建议 在生产环境中,我们可能希望根据环境变量来决定是否启用颜色(例如,只在非生产环境启用颜色)。我们可以通过条件判断来设置格式: ```typescript // src/config/config.default.ts import { MidwayConfig } from '@midwayjs/core'; import { format } from 'winston'; const isProd = process.env.NODE_ENV === 'production'; export default { midwayLogger: { default: { // ...其他配置 transports: [ { type: 'console', format: isProd ? format.combine( format.timestamp(), format.simple() ) : format.combine( format.colorize(), format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.printf(({ level, message, timestamp }) => { return `${timestamp} [${level}] ${message}`; }) ) }, // 文件传输... ] } } } as MidwayConfig; ``` 这样,在生产环境下控制台输出将不包含颜色,而在开发环境下则包含颜色。 ### 引用说明 在Midway.js中,日志模块的配置灵活且强大,通过结合Winston的格式化功能,我们可以轻松实现代码染色[^1][^4]。 §§相关问题§§ 1. 如何在Midway.js中自定义日志输出格式? 2. 如何在Midway.js中实现日志文件按天分割? 3. Midway.js如何将日志同时输出到控制台和文件? 4. 如何在Midway.js中为不同环境配置不同的日志级别?</think>在 Midway.js 中实现代码染色功能(即根据代码执行路径或条件标记不同逻辑分支),可以通过以下步骤配置和实现: ### 一、核心实现方案 #### 1. 使用 AOP 切面编程(推荐) ```typescript // src/aspect/trace.aspect.ts import { Aspect, IMethodAspect, JoinPoint, Provide } from '@midwayjs/decorator'; @Provide() @Aspect([/* 要染色的类或方法 */]) export class TraceAspect implements IMethodAspect { async around(point: JoinPoint) { const start = Date.now(); const ctx = point.ctx; // 请求上下文 try { // 执行前染色 ctx.trace = { path: `${point.target.constructor.name}.${point.methodName}`, startTime: start, tags: ['important'] // 自定义染色标签 }; const result = await point.proceed(...point.args); // 执行原方法 // 执行后染色 ctx.trace.duration = Date.now() - start; ctx.trace.success = true; return result; } catch (err) { // 错误染色 ctx.trace.error = err.message; ctx.trace.success = false; throw err; } } } ``` #### 2. 配置染色作用域 ```typescript // src/configuration.ts import { Configuration } from '@midwayjs/core'; import { TraceAspect } from './aspect/trace.aspect'; @Configuration({ imports: [/* 其他模块 */], importConfigs: [/* 配置文件 */], }) export class MainConfiguration { async onReady() { // 注册染色切面 this.app.getAspectManager().bindClass(TraceAspect, [ UserController, // 指定控制器 PaymentService, // 指定服务 /^Order.*Service/ // 正则匹配 ]); } } ``` ### 二、染色数据收集与可视化 #### 1. 日志集成染色数据 ```typescript // src/config/config.default.ts export default { midwayLogger: { default: { format: info => { const trace = info.ctx?.trace || {}; return `${info.timestamp} [${info.level}] [${trace.path || '-'}] ${info.message} | tags=${trace.tags?.join(',')} duration=${trace.duration || 0}ms`; } } } } ``` #### 2. 染色数据存储(Redis示例) ```typescript // src/service/trace.service.ts import { Provide, Inject } from '@midwayjs/core'; import { RedisService } from '@midwayjs/redis'; @Provide() export class TraceService { @Inject() redisService: RedisService; async record(traceData: object) { await this.redisService.lpush( 'code_traces', JSON.stringify({ ...traceData, timestamp: Date.now() }) ); } } // 在切面中调用 ctx.traceService.record(ctx.trace); ``` ### 三、染色数据可视化 #### 1. 添加染色端点 ```typescript // src/controller/trace.controller.ts import { Controller, Get, Inject } from '@midwayjs/core'; import { TraceService } from '../service/trace.service'; @Controller('/trace') export class TraceController { @Inject() traceService: TraceService; @Get('/') async getTraces() { const traces = await this.traceService.getRecentTraces(); return { success: true, data: traces }; } } ``` #### 2. 前端展示示例(React) ```jsx function TraceViewer() { const [traces, setTraces] = useState([]); useEffect(() => { fetch('/trace').then(res => res.json()) .then(data => setTraces(data)); }, []); return ( <div> {traces.map(trace => ( <div key={trace.id} className={trace.success ? 'success' : 'error'}> <h3>{trace.path}</h3> <p>Duration: {trace.duration}ms</p> <div>{trace.tags.map(tag => <span className="tag">{tag}</span>)}</div> </div> ))} </div> ); } ``` ### 四、生产环境增强建议 1. **染色采样率控制**(避免性能损耗) ```typescript // 在切面中添加 if (Math.random() < 0.1) { // 10%采样率 ctx.trace.sampled = true; // 记录染色数据 } ``` 2. **集成 OpenTelemetry** ```bash npm install @opentelemetry/api @midwayjs/otel ``` ```typescript // configuration.ts import { otel } from '@midwayjs/otel'; @Configuration({ imports: [otel], importConfigs: [/* config */] }) export class MainConfiguration {} ``` 3. **染色数据过滤** ```typescript // 只染色耗时超过100ms的请求 async around(point: JoinPoint) { if (ctx.trace?.duration > 100) { ctx.trace.slow = true; } } ``` ### 五、验证染色效果 1. 发起测试请求: ```bash curl http://localhost:7001/user/profile ``` 2. 查看染色日志: ``` 2023-08-15 14:30 [INFO] [UserController.getProfile] Request completed | tags=important duration=45ms ``` 3. 访问染色端点: ``` http://localhost:7001/trace ``` ### 六、注意事项 1. **性能影响**:染色操作会增加少量性能开销,建议生产环境开启采样率控制 2. **数据安全**:避免记录敏感信息(密码、token等) 3. **作用域控制**:使用 `@Scope(ScopeEnum.Request)` 确保每次请求独立上下文[^1] 4. **存储选择**:高并发场景建议使用 Redis 或 Elasticsearch 存储染色数据[^5] > 通过代码染色功能,开发者可以清晰识别关键执行路径和性能瓶颈,结合日志分割功能[^1],能够构建完整的可观测性体系,显著提升系统维护效率[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值