目录html
一般使用的日志框架有 Log4J 等。java
如何在 Spring Boot 中添加日志框架呢?Spring Boot 自带了一款名为 Spring Boot Logging 的插件,它已经为咱们提供了日志实现。linux
Spring Boot 使用 Commons Logging 做为内部的日志框架,而它是一个日志接口,在实际应用中,咱们须要为该接口提供相应的日志实现。Spring 的默认日志实现是 Java.Util.Logging,它是 JDK 自带的日志包,通常场景下不多被用到。Spring Boot 也提供了 Log4J, Logback 这类流行的日志实现,咱们只要添加简单的配置,就能开启对这些日志的实现。nginx
在 Java 应用程序中,日志通常分为 5 个级别: ERROR,WARN,INFO,DEBUG,TRACE。redis
Spring Boot Logging 默认输出到 INFO
级别,若是但愿日志能够输出到 DEBUG
级别,须要在 application.yml
中添加以下配置spring
logging: level: root: DEBUG
在 java 文件中添加docker
import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... private static Logger logger = LoggerFactory.getLogger(HelloController.class); ... logger.debug("log ...");
就能够在运行代码时看到 debug 级别的日志了。shell
若是不想关注 Spring Boot 框架的日志,则可将日志级别统一设置成 ERROR
,此时只会输出 ERROR
级别的日志。随后,将 Spring Boot 应用程序指定的包设置成 DEBUG
级别的日志,就能看到只有指定包的日志了。json
logging: level: root: ERROR demo: msa: DEBUG
默认状况下日志框架会将日志输出到控制台中,须要在 application.yml
文件中加入下面配置,才能将日志输出到文件中。浏览器
logging: level: root: ERROR demo: msa: DEBUG file: hello.log
首先须要在 pom.xml
中添加以下 Maven 配置,就能在 Spring Boot 中集成 Log4J。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
在第一段中,先排除掉默认的 Logback 日志功能。在第二段的 dependency 配置中,咱们自行添加 spring-boot-starter-log4j2
依赖,它是 Spring Boot 提供的 Log4J 插件。
配置完成 Maven 依赖配置后,下面须要在 resources
目录下添加 log4j2.xml
文件,具体内容以下
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appenders> <File name="file" fileName="${sys:user.home}/logs/hello.log"> <PatternLayout pattern="%d{HH:mm:ss:SSS} %p %c (%L) - %m%n"/> </File> </appenders> <loggers> <root level="ERROR"> <appender-ref ref="file"/> </root> <logger name="demo.msa" level="DEBUG" /> </loggers> </configuration>
这个配置文件分红两部分, appenders
和 loggers
。经过以上配置,就将 Log4j 集成到 Spring Boot 应用中。虽然日志已经成功输出到了文件中,但咱们的微服务是以 Docker 容器的方式来运行的,此时输出的日志文件仍然和应用程序在一个 Docker
容器中,咱们得想办法将日志文件输出到 Docker 容器外。也就是将数据和程序分离,以便后续更方便的获取并分析日志内容。
最经常使用的方法就是,经过 Docker 数据卷的方式,将文件路径挂载到 Docker 容器上,这样日志文件天然与 Docker 文件分离了。启动命令以下
[tomcat@ ~]$ docker run -v ~/logs:/root/logs -d -p 18080:8081 demo.msa/mesa-hello:0.0.1-SNAPSHOT
这样就能够随时在宿主机上查看 Docker 容器内部的日志了。但咱们还须要到文件中去查看,使用 docker logs 的方式获取日志内容则不会有此限制,一块儿来看下。
使用 docker logs
命令能够随时查看 Docker 容器内部应用程序运行时产生的日志,这样就能够避免首先进入 Docker 容器,在打开应用程序的过程了。
Docker logs 的执行过程以下: 它会监控容器中操做系统的标准输出设备 (STDOUT
), 一旦 STDOUT
有产生,就会将这些数据传输到另外一个设备中,该设备在 Docker 的世界中被称为日志驱动(Logging Driver)。
以 nginx 为例,经过下面 Docker 命令启动 Nginx 容器
docker run -d -p 80:80 --name nginx nginx
打开浏览器,在地址栏输入 http://localhost:80
,就能够看到 nginx 的首页。这时就可使用 docker logs
命令,查看 Nginx 容器的日志。
docker logs -f nginx
其中 -f
是指监控日志尾部的意思。
由此看出,只要 Docker 容器内部的应用程序在控制台中有日志输出,就能经过 docker logs
命令来查看响应的日志。那么 Docker 是如何作到的呢?
首先来执行下 命令
docker info |grep "Logging Driver"
能够获得 Docker 当前设置的日志驱动类型,就是 json-file
。
json-file
表示 JSON 文件,就是说 Docker 容器内部的应用程序输出的日志,将自动写入一个 JSON 文件中,并存放在 /var/lib/docker/containers/<container_id>
目录中 <container_id>-json.log
,它就是要找的日志文件。
json-file
只是 Docker 日志驱动的一个默认选项,除了这个选项,咱们还能够显式的指定其余的类型:
none
不输出任何日志syslog
容器输出的日志写入宿主机的 Syslog
中咱们能够在 docker run
命令中经过 --log-driver
参数来设置具体的 Docker 日志驱动。而且能够经过 --log-opt
参数来指定对应日志驱动的相关选项。就拿默认的 json-file 来讲,能够这样来启动 Docker 容器。
docker run -d -p 80:80 --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 --name nginx nginx:1.14
--log-opt
参数有两个选项:
max-file
表示 JSON 文件最多为 3 个max-size
表示 JSON 文件最大为 10M,超过 10M 会自动生成新文件在上面这些日志驱动类型,最为经常使用的是 Syslog, 它是 Linux 的日志系统,不少日志分析工具均可以从 Syslog 获取日志。好比流行的 ELK 日志中心,它包括下面 3 个部分
在这 3 个组件中, Logstash 用于收集日志, Syslog 写入的日志可转发到 Logstash 中,随后会存储到 Elasticsearch 中。
默认状况下,Linux 操做系统已经安装了 syslog 软件包,叫作 Rsyslog。Rsyslog 是 syslog 标准的一种实现。
能够经过下面命令能够查看 Rsyslog 是否已经安装。
rsyslogd -v
若是要开启 Rsyslog 服务,必须对 Rsyslog进行配置,打开配置文件
vi /etc/rsyslog.conf
手工开启(去掉配置前面的注释),启动 TCP 连接的 Rsyslog 的 514 端口。
# Provides TCP syslog reception $ModLoad imtcp $InputTCPServerRun 514
配置文件修改完毕后,手工重启 Rsyslog 服务。
service rsyslog restart or systemctl restart rsyslog
检查下本地是否对外开启了 514 端口。
[root@ ~]# netstat -anpt |grep 514 tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN 63516/rsyslogd tcp 0 0 :::514 :::* LISTEN 63516/rsyslogd
下面就启动 Nginx 容器,并选择 Syslog 做为日志驱动。
docker run -d -p 80:80 --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --name nginx nginx
其中
--log-driver
表示指定 Syslog 为日志驱动--log-opt
指定了 Docker 环境能够经过 TCP 协议链接本地的 514 端口可使用下面命令来查看 linux 系统日志文件,该文件的内容就是 Syslog 所生成的日志
tail -f /var/log/messages
一般会在一台宿主机上同时运行多个 Docker 容器,若是每一个容器都经过 Syslog 来聚合日志,那么在系统日志文件经过 Docker 容器的 ID 是很难识别出是哪一个容器的。如何能区分某条日志是来自哪一个容器呢?
Docker 日志驱动已经为咱们提供了支持,只须要在 --log-opt
参数中添加一个 tag 选项,并在这个选项上给出恰当的命名,就能更好的识别出相应的日志。
docker run -d -p 80:80 --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="nginx" nginx:1.14
将 tag 选项设置成 nginx (容器名称),就能在日志中看到带有 nginx 的标识,这样咱们能够更加容易的识别这条日志来自 Nginx 容器。
若是不指定 tag 选项,则默认的 tag 为容器 ID 的前 12 个字符。也能够在 tag 选项中使用 Docker 已经提供的模板标签,可将这些标签理解为 tag 选项中的占位符。
{{.ID}}
: 容器 ID 的前 12 个字符{{.FullID}}
容器 ID 的完整名称{{.Name}}
容器名称{{.ImageID}}
容器镜像 ID 的前 12 个字符{{.ImageName}}
容器镜像名称下面将这些 tag 标签来个大融合
docker run -d -p 80:80 -v /etc/localtime:/etc/localtime --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx:1.14
docker run -d -p 80:80 -v /etc/localtime:/etc/localtime --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx:1.14
重点是 -v /etc/localtime:/etc/localtime
固然还有其余方法,可参考这篇连接 http://www.cnblogs.com/zengming/p/10190317.html
Docker 容器中的应用程序 Application 将日志吸入到标准输出设备 STDOUT
, Docker Daemon 负责从 STDOUT 中获取日志,并将日志写入对应的日志驱动中。
当应用程序的日志从 Docker 容器内部写入宿主机的 Syslog 中后,后面咱们要作的就是将 Syslog 中的日志转发到 ELK 平台的 Logstash 中,从而创建咱们须要的日志中心
Elastic 官方推出了 6 款开源产品
Logstash 是一款开源的数据收集引擎,它既提供了实时管道数据能力,也提供了灵活的插件机制。咱们能够自由选择已有的插件,也能自行开发所需的插件。咱们使用 Logstash 更多的时候都在作参数配置,以实现咱们所需的功能。
从系统架构的角度来看,它提供了 3 个内部组件,分别是输入组件,过滤组件,输出组件,并且每一个组件都提供了插件机制。能够将这些组件及其插件想象成一个管道(pipeline),数据从数据源(Data Source)流向 INPUTS,FILTERS,OUTPUT,最终到达 Elasticsearch 中存储。
上面 3 个组件包含的经常使用插件以下: