服务器端日志规约和实践

一、日志级别

ALL、TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF

从左至右日志输出由多到少。

生产环境使用INFO日志级别,调试时可以设置为DEBUG级别。

针对Spring Boot的程序,使用配置中的logging.level.root控制默认日志级别。

启动时可以使用logging.level.root参数做临时设置。例如:

java -jar app.jar --logging.level.root=debug

二、日志分类

  1. 监控日志

监控系统内关键点的动作,DEBUG级别可做打点使用,ERROR级别记录程序异常。

  1. 业务日志

系统内业务操作日志输出,例如:下单、支付、后台上下架商品等重要的操作。

  1. 统计日志

根据统计需要,对用户操作进行记录,例如:登录、注册、浏览商品等。

三、日志的触发点和级别

  1. 监控日志
触发点 日志级别 例子
关键方法入口 DEBUG 记录参数
调用外部服务 DEBUG REST API调用返回数据
耗时和资源占用高的方法 DEBUG 记录处理时间、记录资源消耗
定时任务启动和结束 DEBUG 启动时间及状态、结束时间及状态
容错及恢复 DEBUG 用户目录不存在,重新建立用户目录
可处置的操作异常 WARN 用户登录失败
无法处置的程序异常 ERROR logger.error(各类参数或者对象 toString + "_" + e.getMessage(), e);
主程序启动和关闭 DEBUG 启动时间及状态、结束时间及状态
重要配置或环境变量 DEBUG 配置,环境变量
  1. 业务日志
触发点 日志级别 例子
业务操作执行后 INFO 关键业务操作记录执行结果,执行人
  1. 统计日志
触发点 日志级别 例子
需要进行统计的操作 INFO 记录用户访问信息,IP、耗时、下载量;记录资源用量信息

四、日志收集方式

1. Fluentd

将日志发送到远程日志中心,由Fluentd进行收集,Elasticsearch存储,Kibana展示。

附logback配置文件片段。
logger monitor/business/stats 分别对应 监控/业务/统计日志

<appender name="FLUENT" class="ch.qos.logback.more.appenders.FluencyLogbackAppender">
    <tag>${fluentTag}</tag>
    <remoteHost>${fluentHost}</remoteHost>
    <port>${fluentPort}</port>
    <fileBackupDir>${logPath}</fileBackupDir>
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern><![CDATA[%msg]]></pattern>
    </layout>
</appender>
<logger name="monitor" class="ch.qos.logback.classic.AsyncAppender" additivity="false">
    <appender-ref ref="FLUENT" />
    <appender-ref ref="STDOUT" />
</logger>
<logger name="business" class="ch.qos.logback.classic.AsyncAppender" additivity="false">
    <appender-ref ref="FLUENT" />
</logger>
<logger name="stats" class="ch.qos.logback.classic.AsyncAppender" additivity="false">
    <appender-ref ref="FLUENT" />
</logger>

2. 控制台

监控日志还可以输出到控制台。

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

3.文件

重要的日志可以输出到文件作为备份。

可以设置保存文件个数和磁盘占用总容量限制。

<appender name="FILE"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${logPath}/business.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- hourly rollover -->
        <fileNamePattern>${logPath}/business.%d{yyyy-MM-dd-HH}.log</fileNamePattern>
        <!-- keep 30 days' worth of history capped at 3GB total size -->
        <maxHistory>30</maxHistory>
        <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
</appender>

五、记录日志

参考阿里巴巴Java开发手册

应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架 SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger monitorLogger = LoggerFactory.getLogger("monitor");
private static final Logger businessLogger = LoggerFactory.getLogger("business");
private static final Logger statsLogger = LoggerFactory.getLogger("stats");

接下来按照 三、日志的触发点和级别 的说明,在程序中记录日志。

注意点:

  1. 使用占位符而不是字符串拼接

参考阿里巴巴Java开发手册

说明:logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
    如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象, 会执行 toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。 
正例:(条件) 
if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}     
正例:(占位符)
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
  1. 异常输出适当的日志

捕获不可控的异常,应该输出现场信息和异常堆栈信息,不要将异常再抛至上层,避免上层再次输出。

日志例:

logger.error(各类参数或者对象 toString + "_" + e.getMessage(), e);

异常堆栈信息是多行,在Kibana中会出现多条,不便于查看。建议在Fluent中添加合并插件,将异常堆栈信息合并为一行再输出到Elasticsearch。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335