Log日志详解分析

1、log日志的用途

问题追踪:通过日志不仅仅包括我们程序的一些bug,也可以在安装配置时,通过日志可以发现问题。

状态监控:通过实时分析日志,可以监控系统的运行状态,做到早发现问题、早处理问题。

安全审计:审计主要体现在安全上,通过对日志进行分析,可以发现是否存在非授权的操作。

2、log日志级别

日志可分为五个级别
DEBUG :为程序的调试信息,最低级
INFO :为一般要显示的信息,比如登录登出
ERROR:为严重错误 主要是程序的错误
WARN :为一般警告,比如session丢失
FATAL:崩溃,整个程序终止运行

3、什么时候需要输出日志

日志并不是越多越详细就越好。在分析运行日志,查找问题时,我们经常遇到该出现的日志没有,无用的日志一大堆,或者有效的日志被大量无意义的日志信息淹没,查找起来非常困难。那么什么时候输出日志呢?以下列出了一些常见的需要输出日志的情况,而且日志的级别基本都是>=INFO,至于Debug级别日志的使用场景,本节没有专门列出,需要具体情况具体分析,但也是要追求“恰如其分”,不是越多越好。

1. 系统启动参数、环境变量

系统启动的参数、配置、环境变量、System.Properties等信息对于软件的正常运行至关重要,这些信息的输出有助于安装配置人员通过日志快速定位问题,所以程序有必要在启动过程中把使用到的关键参数、变量在日志中输出出来。在输出时需要注意,不是一股脑的全部输出,而是将软件运行涉及到的配置信息输出出来。比如,如果软件对jvm的内存参数比较敏感,对最低配置有要求,那么就需要在日志中将-Xms -Xmx -XX:PermSize这几个参数的值输出出来。

2. 异常捕获处

在捕获异常处输出日志,大家在基本都能做到,唯一需要注意的是怎么输出一个简单明了的日志信息。这在后面的问题问题中有进一步说明。

3. 函数获得期望之外的结果时

一个函数,尤其是供外部系统或远程调用的函数,通常都会有一个期望的结果,但如果内部系统或输出参数发生错误时,函数将无法返回期望的正确结果,此时就需要记录日志,日志的基本通常是warn。需要特别说明的是,这里的期望之外的结果不是说没有返回就不需要记录日志了,也不是说返回false就需要记录日志。比如函数:isXXXXX(),无论返回true、false记录日志都不是必须的,但是如果系统内部无法判断应该返回true还是false时,就需要记录日志,并且日志的级别应该至少是warn。

4. 关键操作

关键操作的日志一般是INFO级别,如果数量、频度很高,可以考虑使用DEBUG级别。以下是一些关键操作的举例,实际的关键操作肯定不止这么多。

删除:删除一个文件、删除一组重要数据库记录……

添加:和外系统交互时,收到了一个文件、收到了一个任务……

处理:开始、结束一条任务……

4、日志输出的内容

ERROR:错误的简短描述,和该错误相关的关键参数,如果有异常,要有该异常的StackTrace。

WARN:告警的简短描述,和该错误相关的关键参数,如果有异常,要有该异常的StackTrace。

INFO:言简意赅地信息描述,如果有相关动态关键数据,要一并输出,比如相关ID、名称等。

DEBUG:简单描述,相关数据,如果有异常,要有该异常的StackTrace。

在日志相关数据输出的时要特别注意对敏感信息的保护,比如修改密码时,不能将密码输出到日志中。

5、 注意事项

1. 日志信息不明确

实际开发时没有记录任务id和任务名称,软件部署后现错误后,根据该日志记录不能确认哪一条任务错误,给进一步的分析原因带来困难。

2. 特殊异常处理

对于静态工具类函数中的异常处理,最简单的方式就是不捕获、不记录日志,直接向上抛出,如果认为异常类型太多,或者意义不明确,可以抛出自定义异常类的实例。

3. 日志输出顺序

另外需要明确一点:日志系统是一个多线程公用的系统,在两行日志输出之间有可能会被插入其他线程的日志记录,不会按照我们的意愿顺序输出。

4. 临时调试日志

对于临时调试日志,建议在日志的输出信息中添加一些特殊的连续字符,也可以用自己的名称、代号,这样可以在调试完毕后,提交代码之前,方便地找到所有临时代码,一并删除。

6、xml文件配置

logback-spring.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义日志文件的存储地址 -->
    <property name="LOG_HOME" value="../pro_col_logs/user" />
&lt;!--&lt;property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" /&gt;--&gt;
&lt;!-- 控制台输出 --&gt;
&lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"&gt;
    &lt;encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"&gt;
        &lt;!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符
        &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n&lt;/pattern&gt;--&gt;
        &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n&lt;/pattern&gt;
    &lt;/encoder&gt;
&lt;/appender&gt;

&lt;!-- 按照每天生成日志文件 --&gt;
&lt;appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
    &lt;rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"&gt;
        &lt;!--日志文件输出的文件名 --&gt;
        &lt;FileNamePattern&gt;${LOG_HOME}/user-%d{yyyy-MM-dd}.%i.log&lt;/FileNamePattern&gt;
        &lt;!--日志文件保留天数 --&gt;
        &lt;MaxHistory&gt;30&lt;/MaxHistory&gt;
        &lt;maxFileSize&gt;50MB&lt;/maxFileSize&gt;
    &lt;/rollingPolicy&gt;
    &lt;encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"&gt;
        &lt;!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --&gt;
        &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n&lt;/pattern&gt;
    &lt;/encoder&gt;
    &lt;!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 --&gt;
    &lt;filter class="ch.qos.logback.classic.filter.LevelFilter"&gt;
        &lt;level&gt;DEBUG&lt;/level&gt;
        &lt;!--抓到该级别的就拦截--&gt;
        &lt;onMatch&gt;DENY&lt;/onMatch&gt;
        &lt;!-- 上面没抓到的就放行--&gt;
        &lt;onMismatch&gt;ACCEPT&lt;/onMismatch&gt;
    &lt;/filter&gt;
&lt;/appender&gt;

&lt;!-- 滚动记录文件--&gt;
&lt;!-- level为 DEBUG 日志,时间滚动输出  --&gt;
&lt;appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
    &lt;!-- 正在记录的日志文档的路径及文档名 --&gt;
    &lt;file&gt;${LOG_HOME}/user-debug.log&lt;/file&gt;
    &lt;!--日志文档输出格式--&gt;
    &lt;encoder&gt;
        &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n&lt;/pattern&gt;
        &lt;charset&gt;UTF-8&lt;/charset&gt; &lt;!-- 设置字符集 --&gt;
    &lt;/encoder&gt;
    &lt;!-- 日志记录器的滚动策略,按日期,按大小记录 --&gt;
    &lt;rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"&gt;
        &lt;!-- 日志归档 --&gt;
        &lt;fileNamePattern&gt;${LOG_HOME}/user-debug-%d{yyyy-MM-dd}.%i.log&lt;/fileNamePattern&gt;
        &lt;timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"&gt;
            &lt;maxFileSize&gt;100MB&lt;/maxFileSize&gt;
        &lt;/timeBasedFileNamingAndTriggeringPolicy&gt;
        &lt;!-- 日志文档保留天数 --&gt;
        &lt;maxHistory&gt;15&lt;/maxHistory&gt;
        &lt;!-- 限制日志文件总容量 --&gt;
        &lt;totalSizeCap&gt;10GB&lt;/totalSizeCap&gt;
    &lt;/rollingPolicy&gt;
    &lt;!-- 此日志文档只记录debug级别的 --&gt;
    &lt;filter class="ch.qos.logback.classic.filter.LevelFilter"&gt;
        &lt;level&gt;debug&lt;/level&gt;
        &lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;
        &lt;onMismatch&gt;DENY&lt;/onMismatch&gt;
    &lt;/filter&gt;
&lt;/appender&gt;

&lt;!-- 生成 error html格式日志开始 --&gt;
&lt;appender name="HTML" class="ch.qos.logback.core.FileAppender"&gt;
    &lt;filter class="ch.qos.logback.classic.filter.ThresholdFilter"&gt;
        &lt;!--设置日志级别,过滤掉info日志,只输入error日志--&gt;
        &lt;level&gt;ERROR&lt;/level&gt;
    &lt;/filter&gt;
    &lt;encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"&gt;
        &lt;layout class="ch.qos.logback.classic.html.HTMLLayout"&gt;
            &lt;pattern&gt;%p%d%msg%M%F{32}%L&lt;/pattern&gt;
        &lt;/layout&gt;
    &lt;/encoder&gt;
    &lt;file&gt;${LOG_HOME}/user-error-log.html&lt;/file&gt;
&lt;/appender&gt;
&lt;!-- 生成 error html格式日志结束 --&gt;


&lt;!--myibatis log configure --&gt;
&lt;logger name="com.apache.ibatis" level="TRACE" /&gt;
&lt;logger name="java.sql.Connection" level="DEBUG" /&gt;
&lt;logger name="java.sql.Statement" level="DEBUG" /&gt;
&lt;logger name="java.sql.PreparedStatement" level="DEBUG" /&gt;

&lt;logger name="com.byd" level="DEBUG" /&gt;

&lt;!-- 日志输出级别 --&gt;
&lt;root level="INFO"&gt;
    &lt;appender-ref ref="STDOUT" /&gt;
    &lt;appender-ref ref="FILE" /&gt;
    &lt;appender-ref ref="HTML" /&gt;
    &lt;appender-ref ref="DEBUG_FILE" /&gt;
&lt;/root&gt;

</configuration>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

在这里插入图片描述

7、linux下查看日志命令

7.1 linux查看日志的常用命令包括

tail/head、cat/tac、less/more、grep/sed、wc

 
 
  • 1
1. tail命令:用于显示文件的末尾内容。
tail -f filename --> 实时监控日志
tail -10f filename --> 实时监控10行日志信息
tail -n 100 filename —> 查看尾部最后100行日志信息
tail -n +100 filename — >查看日志100行之后的日志信息

 
 
  • 1
  • 2
  • 3
  • 4
2. head命令:用于显示文件的开头内容。
head -n 100 filename —> 查看文本开始的头100行信息
head -n -100 filename —> 查看文本最后100行信息以上的内容

 
 
  • 1
  • 2
3. cat命令:用于将文件内容输出到终端。

例如:cat filename 将显示文件filename的全部内容。

cat filename --> 查看全部文本信息
cat -n filename |tail -n +100|head -n 20 —> 查看100-120行之间的内容
tac – 从文本的尾部往头部展示日志内容

 
 
  • 1
  • 2
  • 3
4. less命令:用于以可滚动的方式查看大型文件。

例如:less filename 将打开文件filename,您可以使用上下箭头和Page Up/Page Down键来浏览文件。

/keyword -->搜索
n/shift+n键–>向下查找
快捷键:ctrl+F/ctrl+B–>向前/后翻页
less +/keyword logfile.log–>搜索关键字
直接定位:
less +100g xx.log --> 直接定位到第100行
less +GG xx.log --> 定位到最后一行
less +100P xx.log --> 定位到第100个字节的位置
less +100p xx.log --> 直接定位到50%的位置
more -10 filename 设定每页展示10条数据信息。

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
5. grep命令:用于在文件中搜索特定的内容。
grep是一种强大的文本搜索工具,使用正则表达式搜索文本且把匹配的行打印出来。

grep “match_pattern” file1,file2,file3 —>多个文本中查找
grep “match_pattern” filename --color=auto -->标记匹配颜色(always never auto三种)
grep -v “match _pattern”filename -->输出除之外的所有行
grep -E “[1-9]+” --> 使用正则表达式
grep -o -E “[a-z]+.” line --> 只输出匹配到的内容
grep -c “text” filename --> 统计文件或者文本中包含匹配字符串的行数
grep “text” -n filename --> 输出包含匹配字符串的行数
sed是一种非交互式的编辑器,sed会逐行处理文件并将结果发送到屏幕。
sed -n ‘1p’ filename --> 只打印文件第一行
sed -n ‘1,10p’ filname --> 查看文件1-10行内容
sed ‘1d’ filename --> 删除文本第一行内容
sed ‘s/希望替换的内容/被替换的内容/g’ --> 替换字符串
sed ‘s/1/one /g’ filename 将1替换为one
sed -n ‘/2019-08-06 22:43/,/2019-08-06 22:44/p’ filename --> 查看时间区间内的日志记录;
n1 log.file| sed -n ‘1,10p’ --> 查看日志的1-20行内容。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7.2 常用场景

1. 匹配关键字,排查错误

grep

grep -w “keyword" filelog.log -2 --color -n > /tmp/tmp.log
grep -w   "keyword" filelog.log -2 --color  -n  | less

 
 
  • 1
  • 2

-w 全匹配;-2 关键字上下2行;–color 关键字着色;-n 输出行号

2. 查看某个时间段的日志信息
 grep '2019-08-06 22' filename

 
 
  • 1

cat结合grep

cat log.file |grep -n '2019-08-06 22:43'

 
 
  • 1

sed结合grep

sed -n '2013:15:00:01/,/2013:16:59:58/p' xxxx.log | grep "Exception" -n -5 --color

 
 
  • 1
3. 查看日志最后一次出现关键字’test’的日志记录
grep 'test' -A 10  log.file | tail -n 11

 
 
  • 1

这里需要了解到grep命令的几个参数含义:
grep ‘name’ -A 10 显示匹配内容和后面的10行
grep ‘name’ -B 10 显示匹配内容和前面的10行
grep ‘name’ -C 10 显示匹配内容和前后面的10行
tail -n 11命令则是将当前显示的10行内容以及匹配的那一行内容展示出现

4. 统计一份日志里面出现‘keyword’关键字的行数
grep 'keyword' ./log.file |wc -l

 
 
  • 1
5. wc命令常用的几个参数

-l 匹配的行数
-w 匹配的字数
-m 匹配的字符数目

后端专属技术群
构建高质量的技术交流社群,欢迎从事编程开发、技术招聘HR进群,也欢迎大家分享自己公司的内推信息,相互帮助,一起进步!
文明发言,以交流技术、职位内推、行业探讨为主
广告人士勿入,切勿轻信私聊,防止被骗

图片

关注公众号,拉你进群
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值