随着系统访问量的增大,集群化的部署方式使得每个 rails log
文件都是写在各自的服务器硬盘上,这给排查错误造成很大的困扰,只能挨个服务器去找日志信息。 这个时候就需要一个工具来将日志收集起来统一处理。ELK 就是一个很好的日志处理分析工具。
ELK
是 Elasticsearch
、Logstash
和 Kibana
三种软件产品的首字母缩写。这三者都是开源软件,通常配合使用,而且又先后归于 Elastic.co
公司名下,所以被简称为 ELK Stack
。根据 Google Trend
的信息显示,ELK Stack
已经成为目前最流行的集中式日志解决方案。
在这种架构中,只有一个 Logstash
、Elasticsearch
和 Kibana
实例。Logstash
通过输入插件从多种数据源(比如日志文件、标准输入 Stdin
等)获取数据,再经过滤插件加工数据,然后经 Elasticsearch
输出插件输出到 Elasticsearch
,通过 Kibana
展示。这种架构适合初学者学习 ELK
的工作模式,搭建最简单的工作模式。
这种架构是对上面架构的扩展,把一个 Logstash
数据搜集节点扩展到多个,分布于多台机器,将解析好的数据发送到 Elasticsearch server
进行存储,最后在 Kibana
查询、生成日志报表等。
这种架构在日常中应用的比较少;因为需要在各个服务器上部署 Logstash,而它比较消耗 CPU 和内存资源,所以比较适合计算资源丰富的服务器,否则容易造成服务器性能下降,甚至可能导致无法正常工作。
filebeat
作为日志收集器
这种架构是对上面架构的优化,filebeat
比 logstash
更轻量,占用资源更少,通过filebeat
采集日志,经logstash
处理之后传递给Elasticsearch
,通过 Kibana
展示。
一些大型项目日志访问频繁,产生的日志文件比较多,对日志的分析要求较高,对稳定性与可靠性要求较高,可以在 filebeat
与 logstash
之间插入一层队列, 先将数据传递给消息队列,然后通过 logstash
拉取消息队列数据, 处理之后传递给ES集群处理。
gem "lograge"
gem "logstash-event"
config/initializers/lograge.rb
配置如下Rails.application.configure do
config.lograge.enabled = true
config.lograge.formatter = Lograge::Formatters::Logstash.new
config.lograge.keep_original_rails_log = true
config.lograge.logger = ActiveSupport::Logger.new "#{Rails.root}/log/lograge_#{Rails.env}.log"
end
如果使用 grape
,grape的日志并不会写入文件中需要另外处理
gem grape_logging
到gemfileclass API < Grape::API
use GrapeLogging::Middleware::RequestLogger,
instrumentation_key: 'api',
include: [
GrapeLogging::Loggers::Response.new,
GrapeLogging::Loggers::FilterParameters.new,
GrapeLogging::Loggers::ClientEnv.new,
GrapeLogging::Loggers::RequestHeaders.new
]
...
end
config/initializers/instrumentation.rb
配置如下, 将日志按照格式发给Lograge# Subscribe to grape request and log with a logger dedicated to Grape
ActiveSupport::Notifications.subscribe('api') do |name, starts, ends, notification_id, payload|
info = {
name: name,
status: payload[:status],
method: payload[:method],
path: payload[:path],
params: payload[:params],
host: payload[:host],
db: payload[:time][:db],
view: payload[:time][:view],
total: payload[:time][:total],
remote_ip: payload[:ip],
format: "json",
user_agent: payload[:ua],
origin: payload[:headers]["Referer"],
logtime: Time.current,
}.to_json
Lograge.logger.info info
end
filebeat.yml
主要配置如下filebeat.inputs:
- type: log
enabled: true
paths:
- /var/www/xxx/xxx/log/lograge_production.log
fields:
appname: appname
log_type: application
env: production
fields_under_root: true
output.logstash:
hosts: [remote_logstash_ip:5044"]
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~town-square
path路径为lograge
根据规则生成的 json
日志路径
logstash
logstash.yml
主要配置如下input {
beats {
port => 5044
}
}
filter {
if [log_type] == "application" {
json {
source => "message"
}
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
index => "%{[appname]}-%{[env]}-%{+YYYY.MM.dd}"
hosts => ['127.0.0.1:9200']
}
}