news 2026/6/6 10:08:14

【架构实战】日志体系设计:从ELK到可观测性的演进

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【架构实战】日志体系设计:从ELK到可观测性的演进

一、一次线上故障排查花了4小时

2020年,用户反馈下单失败,但监控系统一切正常。

我登录服务器,用grep查日志。结果发现日志分散在8台机器上,每台机器的日志格式还不一样。花了2小时才找到报错的那条日志,又花了2小时才定位到原因——一个第三方支付接口超时。

从那以后,我们引入了统一的日志体系,同样的故障,现在10分钟就能定位。


二、日志规范

2.1 日志级别

日志级别使用规范: ERROR:系统错误,需要立即处理 - 未捕获的异常 - 外部服务不可用 - 数据不一致 WARN:潜在问题,需要关注 - 业务异常(用户输入错误) - 性能降级 - 接近阈值 INFO:关键业务流程 - 请求开始/结束 - 业务状态变更 - 外部调用 DEBUG:调试信息(生产环境关闭) - 方法入参/出参 - 中间变量 - SQL语句

2.2 日志格式

/** * 统一日志格式 */@ConfigurationpublicclassLogConfig{/** * JSON格式日志(推荐) */@BeanpublicLoggingEventJsonFormatjsonFormat(){returnLoggingEventJsonFormat.builder().timestamp("@timestamp").level("level").thread("thread").logger("logger").message("message").traceId("traceId").spanId("spanId").build();}}// 日志输出示例:// {"@timestamp":"2024-01-01T12:00:00.000Z","level":"INFO","thread":"http-nio-8080-1","logger":"com.example.OrderService","message":"订单创建成功","traceId":"abc123","spanId":"def456","orderId":"ORD001","userId":"USR001","amount":99.9}

2.3 MDC链路追踪

/** * MDC链路追踪 */@ComponentpublicclassTraceFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletRequesthttpRequest=(HttpServletRequest)request;// 从请求头获取TraceIdStringtraceId=httpRequest.getHeader("X-Trace-Id");if(traceId==null){traceId=UUID.randomUUID().toString().replace("-","");}// 设置MDCMDC.put("traceId",traceId);MDC.put("spanId",generateSpanId());MDC.put("userId",getCurrentUserId(httpRequest));try{chain.doFilter(request,response);}finally{MDC.clear();}}}/** * Feign传递TraceId */@ConfigurationpublicclassFeignTraceConfig{@BeanpublicRequestInterceptortraceInterceptor(){returntemplate->{StringtraceId=MDC.get("traceId");if(traceId!=null){template.header("X-Trace-Id",traceId);}};}}

三、ELK架构

3.1 架构图

┌─────────────────────────────────────────────────────────────────┐ │ ELK架构 │ │ │ │ ┌─────────┐ ┌─────────────┐ ┌──────────┐ │ │ │ 应用 │───▶│ Logstash │───▶│Elastic- │ │ │ │ 日志 │ │ (收集过滤) │ │ search │ │ │ └─────────┘ └─────────────┘ └──────────┘ │ │ │ │ │ │ │ ┌─────────────┐ │ │ │ └─────────────▶│ Filebeat │────────┘ │ │ │ (轻量采集) │ │ │ └─────────────┘ │ │ │ │ │ ┌─────────────┐ │ │ │ │ Kibana │◀─────┘ │ │ │ (可视化) │ │ │ └─────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────┘

3.2 Filebeat配置

# filebeat.ymlfilebeat.inputs:-type:logenabled:truepaths:-/var/log/app/*.logfields:app:order-serviceenv:productionfields_under_root:truemultiline:pattern:'^\d{4}-\d{2}-\d{2}'negate:truematch:afteroutput.logstash:hosts:["logstash:5044"]compression_level:3processors:-add_host_metadata:~-add_cloud_metadata:~

3.3 Logstash配置

# logstash.confinput{beats{port=>5044}}filter{# 解析JSON格式日志json{source=>"message"target=>"log"}# 提取TraceIdmutate{add_field=>{"traceId"=>"%{[log][traceId]}"}}# 过滤DEBUG日志if[log][level]=="DEBUG"{drop{}}# 添加时间戳date{match=>["[log][@timestamp]","ISO8601"]target=>"@timestamp"}}output{elasticsearch{hosts=>["elasticsearch:9200"]index=>"app-logs-%{+YYYY.MM.dd}"template=>"/usr/share/logstash/templates/app-logs.json"template_overwrite=>true}}

四、日志告警

4.1 基于ElastAlert的告警

# error_alert.yamlname:Error Log Alerttype:frequencyindex:app-logs-*# 5分钟内ERROR日志超过10条告警num_events:10timeframe:minutes:5filter:-term:log.level:"ERROR"# 排除已知的非关键错误filter:-term:log.level:"ERROR"-not:query:query_string:query:"message: *ConnectionReset*"alert:-"dingtalk"dingtalk:webhook:"https://oapi.dingtalk.com/robot/send?access_token=xxx"message:"⚠️ ERROR日志告警\n应用: {app}\n环境: {env}\n数量: {num_hits}\n最近一条: {message}"

4.2 日志监控大盘

/** * 日志指标统计 */@Service@Slf4jpublicclassLogMetricsService{@AutowiredprivateMeterRegistrymeterRegistry;/** * 记录业务指标到日志 */publicvoidlogBusinessMetric(StringmetricName,doublevalue,String...tags){// 记录到监控系统TagsmetricTags=Tags.of(tags);meterRegistry.counter("business."+metricName,metricTags).increment(value);// 同时记录到日志(用于ELK分析)log.info("BusinessMetric: name={}, value={}, tags={}",metricName,value,Arrays.toString(tags));}}

五、踩坑实录

坑1:日志太多导致磁盘满

DEBUG日志在生产环境开着,每天产生100GB日志,磁盘很快就满了。

解决:生产环境关闭DEBUG,设置日志滚动和自动清理。

坑2:日志格式不统一

每个服务日志格式不一样,ELK解析困难。

解决:统一JSON格式,强制规范。

坑3:日志中打印敏感信息

日志里打印了用户密码和手机号,被安全扫描发现。

解决:日志脱敏,禁止打印敏感信息。

坑4:异步日志丢失

使用异步日志,应用崩溃时缓冲区的日志丢失。

解决:配置ImmediateFlush,关键日志同步写入。

坑5:日志影响性能

在循环中打印日志,QPS下降了30%。

解决:避免在热路径打印日志,使用isDebugEnabled判断。


六、总结

日志体系要点:

环节方案
规范统一格式、级别、脱敏
采集Filebeat + Logstash
存储Elasticsearch
展示Kibana
告警ElastAlert
链路MDC + TraceId

最佳实践:

  1. 统一JSON格式日志
  2. MDC传递链路信息
  3. 生产环境关闭DEBUG
  4. 日志脱敏
  5. 告警及时

血的教训:

好的日志体系不是锦上添花,是雪中送炭。出问题时,日志是你唯一的救命稻草。

思考题:你的日志体系是怎样的?排查问题快吗?


个人观点,仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 10:07:15

用Python和OpenCV实战霍夫圆检测:从Canny边缘到圆心定位的完整流程

PythonOpenCV实战:工业级霍夫圆检测全流程优化指南在自动化质检、医学影像分析等领域,圆形物体的精准检测往往是关键的第一步。传统图像处理方法中,霍夫圆变换因其稳定性和可解释性,至今仍是许多工业场景的首选方案。本文将带您从…

作者头像 李华
网站建设 2026/6/6 10:05:02

医疗生成式AI的隐私保护分层防御架构

1. 项目概述:当生成式AI撞上医疗隐私,我们到底在解决什么问题?生成式AI在医疗健康领域的应用正以肉眼可见的速度铺开——从自动生成病历摘要、辅助医学影像标注,到为基层医生提供实时诊疗建议,甚至参与新药分子结构的初…

作者头像 李华
网站建设 2026/6/6 10:04:42

软件SHE模块在AUTOSAR CP中的定位与工作量评估

朋友,在前面关于加密栈的讨论中,我们明确了CMAC等加密算法的实现位于Crypto Driver中,而上层Csm负责作业调度。现在你把问题推进了一步:如果要开发一个软件SHE模块,它属于Crypto Driver还是库?开发工作量有…

作者头像 李华
网站建设 2026/6/6 10:03:54

p-Laplacian方程在完美导电问题中的梯度估计与应用

1. 项目概述在复合材料研究中,p-Laplacian完美导电问题是一个具有重要理论和应用价值的课题。当两个完美导体在均匀介质中紧密排列时,其间的电场分布会呈现复杂的数学特性。本文基于Hongjie Dong和Longjuan Xu的最新研究,系统分析了不同边界条…

作者头像 李华