ELK收集监控nginx请求日志_unrecognized character escape ‘x

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
img

正文

整理下实施ELK最起码要实现的需求:

  • 查询条件(精确匹配):一级域名、二级域名、客户真实IP、HTTP状态码、HTTP方法、request_time、response_time、代理IP、body_bytes_sent
  • 查询条件(模糊匹配):url(如查找SQL注入关键字)、refere(流量来源)、agent(如查找搜索引擎)
  • 近期(1周、1个月)内整体请求量走势情况;
  • 如果发现总体走势异常,要很方便找到那个域名走势异常;
  • 过去一个周期内(1天、1周、1月)所有请求构成,按不同域名出饼图;
  • 实时监控爬虫IP过高的频率访问(如单个IP1分钟请求超过100次报警);
  • 实时监控500状态请求情况(如单个域名1分钟出现30个500就报警);
  • ……

2.拓扑

nginx需要配置syslog协议输出;
logstash作为syslog服务器,收集日志,输出2个方向:elastersearch入库,本地文件;
elasticsearch需要设计好模型,目的:支持不同字段的查找需求(精确或模糊,甚至某个字段同时要支持精确+模糊,不过我没用到)、空间不浪费;
kibana可视化,主要是配置Discovery\Visualize;
elastalert,配置各种规则,实现实时监控需求。

3.nginx配置

nginx.conf
日志以json格式输出,方便logstash解析;
因为syslog协议一条消息最大2K,因此有些变了做了阶段(_short后缀的变量);
level1domain、level2domain分别指一级域名、二级域名;

log_format main_json ‘{“project”:“ l e v e l 1 d o m a i n " , " d o m a i n " : " {level1domain}","domain":" level1domain","domain":"{level1domain}_ l e v e l 2 d o m a i n " , " r e a l i p " : " {level2domain}","real_ip":" level2domain","realip":"real_ip”,“http_x_forwarded_for”:“KaTeX parse error: Double subscript at position 7: http_x_̲forwarded_for",…time_iso8601”,"
request":“ r e q u e s t s h o r t " , " r e q u e s t b o d y " : " request_short","request_body":" requestshort","requestbody":"request_body_short”,“status”: s t a t u s , " b o d y b y t e s s e n t " : " status,"body_bytes_sent":" status,"bodybytessent":"body_bytes_sent",“http_referer”:“ h t t p r e f e r e r s h o r t " , " u p s t r e a m r e s p o n s e t i m e " : " http_referer_short","upstream_response_time":" httpreferershort","upstreamresponsetime":"upstream_re
sponse_time”,“request_time”:“ r e q u e s t t i m e " , " h t t p u s e r a g e n t " : " request_time","http_user_agent":" requesttime","httpuseragent":"http_user_agent”}’;

location.conf

#取前750个字节
if ( $request ~ “^(.{0,750})” ) {
set $request_short $1;
}
#取前750个字节
if ( $request_body ~ “^(.{0,750})” ) {
set $request_body_short $1;
}
#取前100个字节
set $http_referer_short “-”;
if ( $http_referer ~ “^(.{1,100})” ) {
set $http_referer_short KaTeX parse error: Expected 'EOF', got '}' at position 4: 1; }̲ #从http_x_forward_for中获取第一个IP,作为客户端实际IP
set $real_ip $remote_addr;
if ( $http_x_forwarded_for ~ “^(\d+.\d+.\d+.\d+)” ) {
set $real_ip KaTeX parse error: Expected 'EOF', got '}' at position 4: 1; }̲ #server_name的格…level1domain
#解析一级域名之前的部分为$level2domain
set $level1domain unparse;
set $level2domain unparse;
if ( s e r v e r n a m e   " ( . + ) ( ˙ [ 0 − 9 a − z A − Z ] + ) ( ˙ c o m ∣ c n ) server_name ~ "^(.+)\.([0-9a-zA-Z]+)\.(com|cn) servername "(.+)(˙[09azAZ]+)(˙comcn)" ) {
set $level1domain $2;
set $level2domain $1;
}
if ( s e r v e r n a m e   " ( [ 0 − 9 a − z A − Z ] + ) ( ˙ c o m ∣ c n ) server_name ~ "^([0-9a-zA-Z]+)\.(com|cn) servername "([09azAZ]+)(˙comcn)" ) {
set $level1domain $1;
set $level2domain none;
}
#syslog输出配置
access_log syslog:local7:info:logstash_ip:515:nginx main_json;

4.logstash配置

安装:

安装jdk8
解压logstash-6.2.1.tar.gz
查看插件:
./logstash-plugin list | grep syslog
安装非默认插件
./logstash-plugin install logstash-filter-alter
测试:

./logstash -e ‘input { stdin { } } output { stdout {} }’

启动:
启动logstash:nohup ./bin/logstash -f mylogstash.conf & disown

配置:

mylogstash.conf

input {
syslog {
type => “system-syslog”
port => 515
}
}

filter {
#在json化之前,使用mutte对\x字符串进行替换,防止以下错误:ParserError: Unrecognized character escape ‘x’ (code 120)
mutate {
gsub => [“message”, “\x”, “\\x”]
}
json {
source => “message”
#删除无用字段,节约空间
remove_field => “message”
remove_field => “severity”
remove_field => “pid”
remove_field => “logsource”
remove_field => “timestamp”
remove_field => “facility_label”
remove_field => “type”
remove_field => “facility”
remove_field => “@version”
remove_field => “priority”
remove_field => “severity_label”
}
date {
#用nginx请求时间替换logstash生成的时间
match => [“time_local”, “ISO8601”]
target => “@timestamp”
}
grok {
#从时间中获取day
match => { “time_local” => “(?.{10})” }
}
grok {
#将request解析成2个字段:method\url
match => { “request” => “%{WORD:method} (?.* )” }
}
grok {
#截取http_referer问号前的部分,问号后的信息无价值,浪费空间
match => { “http_referer” => “(?-|%{URIPROTO}😕/(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?)” }
}
mutate {
#解析出新的字段后,原字段丢弃
remove_field => “request”
remove_field => “http_referer”
rename => { “http_user_agent” => “agent” }
rename => { “upstream_response_time” => “response_time” }
rename => { “host” => “log_source” }
rename => { “http_x_forwarded_for” => “x_forwarded_for” }
#以下2个字段以逗号分隔后,以数组形式入库
split => { “x_forwarded_for” => ", " }
split => { “response_time” => ", " }
}
alter {
#不满足elasticsearch索引模型的,入库会失败,因此做以下数据转换
condrewrite => [
“x_forwarded_for”, “-”, “0.0.0.0”,
“x_forwarded_for”, “unknown”, “0.0.0.0”,
“response_time”, “-”, “0”,
“real_ip”, “”, “0.0.0.0”
]
}
}

output {
#入库,以template指定的模型作为索引模型
elasticsearch {
hosts => [“elasticsearch_ip:9200”]
index => “nginx-%{day}”
manage_template => true
template_overwrite => true
template_name => “mynginx”
template => “/root/logstash/mynginxtemplate.json”
codec => json
}
#本地文件放一份,作为ELK的补充
file {
flush_interval => 600
path => ‘/nginxlog/%{day}/%{domain}.log’
codec => line { format => ‘<%{time_local}> <%{real_ip}> <%{method}> <%{url}> <%{status}> <%{request_time}> <%{response_time}> <%{body_bytes_sent}> <%{request_body}> <%{referer}> <%{x_f
orwarded_for}> <%{log_source}> <%{agent}>’}
}
}

mynginxtemplate.json

{
“template”: “nginx-*”,
“settings”: {
“index.number_of_shards”: 8,
“number_of_replicas”: 0,
“analysis”: {
“analyzer”: {
#自定义stop关键字,不收集http等字段的索引
“stop_url”: {
“type”: “stop”,
“stopwords”: [“http”,“https”,“www”,“com”,“cn”,“net”]
}
}
}
},
“mappings” : {
“doc” : {
“properties” : {

index:true 分词、生产搜索引擎

analyzer:指定索引分析器

“referer”: {
“type”: “text”,
“norms”: false,
“index”: true,
“analyzer”: “stop_url”
},
“agent”: {
“type”: “text”,
“norms”: false,
“index”: true
},

IP字段类型

“real_ip”: {
“type”: “ip”
},
“x_forwarded_for”: {
“type”: “ip”
},

keyword,作为完整字段索引,不可分词索引

“status”: {
“type”: “keyword”
},
“method”: {
“type”: “keyword”
},
“url”: {
“type”: “text”,
“norms”: false,
“index”: true,
“analyzer”: “stop_url”
},
“status”: {
“type”: “keyword”
},
“response_time”: {
“type”: “half_float”
},
“request_time”: {
“type”: “half_float”
},
“domain”: {
“type”: “keyword”
},
“project”: {
“type”: “keyword”
},
“request_body”: {
“type”: “text”,
“norms”: false,
“index”: true
},
“body_bytes_sent”: {
“type”: “long”
},
“log_source”: {
“type”: “ip”
},
“@timestamp” : {
“type” : “date”,
“format” : “dateOptionalTime”,
“doc_values” : true
},
“time_local”: {
“enabled”: false
},
“day”: {
“enabled”: false
}
}
}
}
}

5.elasticsearch配置

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
y": {
“enabled”: false
}
}
}
}
}

5.elasticsearch配置

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-1Pu9DnFg-1713300920603)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值