日志服务数据加工最佳实践: 使用正则与grok解析Ngnix日志

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 本篇介绍日志服务数据加工最佳实践: 使用正则表达式与grok解析Ngnix日志, 使用grok自带的400+模式实现最简化解析


本部分实践案例,旨在通过一种场景多种解决方案的对比,选择出一种最快最好的解决方案。本专题主要讲解正则解析方面的场景实践。

场景:解析Nginx日志

以下以一条Nginx日志为例,向大家展开如何解析Nginx日志的多种方案。

203.208.60.89 - - [04/Jan/2019:16:06:38 +0800] "GET /atom.xml HTTP/1.1" 200 273932 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

需求

1、从Nginx日志中提取出clientip、ident、auth、timestamp、verb、request、url、httpversion、response、bytes、referrer、agent信息
2、对解析出来的url进行再提取,提取出url_proto、url_host、url_param
3、对解析出来的url_param进行再提取,提取出url_path、url_query信息

原始日志

在控制台收集到的日志格式是string格式,如下所示:

__source__:  30.43.16.15
__tag__:__client_ip__:  12.120.75.140
__tag__:__receive_time__:  1563443076
content: 203.208.60.89 - - [04/Jan/2019:16:06:38 +0800] "GET http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0 HTTP/1.1" 200 273932 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

LOG DSL编排

本部分将提供两种方案,解决以上需求。

方案一:正则解析

1、针对需求1解析Nginx日志的加工编排如下:

e_regex("content",r'(?P<ip>\d+\.\d+\.\d+\.\d+)( - - \[)(?P<datetime>[\s\S]+)\] \"(?P<verb>[A-Z]+) (?P<request>[\S]*) (?P<protocol>[\S]+)["](?P<code>\d+) (?P<sendbytes>\d+) ["](?P<refere>[\S]*)["] ["](?P<useragent>[\S\s]+)["]')

预览处理日志:

ip: 203.208.60.89
datetime: 04/Jan/2019:16:06:38 +0800
verb: GET
request: http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0
protocol: HTTP/1.1
code: 200
sendbytes: 273932
refere: -
useragent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

2、针对需求2解析第一步加工后得到的url的加工编排如下:

e_regex('url',r'(?P<url_proto>(\w+)):\/\/(?P<url_domain>[a-z0-9.]*[^\/])(?P<uri_param>(.+)$)')

预览处理日志:

url_proto: http
url_domain: cdn1cdedge0001.coxlab.net
uri_param: /_astats?application=&inf.name=eth0

3、针对需求3解析第二步得到的url参数的加工编排如下:

e_regex('uri_param',r'(?P<uri_path>\/\_[a-z]+[^?])\?(?<uri_query>(.+)$)')

预览处理日志:

uri_path: /_astats
uri_query: application=&inf.name=eth0

4、综上LOG DSL规则可以如以下形式:

"""第一步:初步解析Nginx日志"""
e_regex("content",r'(?P<ip>\d+\.\d+\.\d+\.\d+)( - - \[)(?P<datetime>[\s\S]+)\] \"(?P<verb>[A-Z]+) (?P<request>[\S]*) (?P<protocol>[\S]+)["](?P<code>\d+) (?P<sendbytes>\d+) ["](?P<refere>[\S]*)["] ["](?P<useragent>[\S\s]+)["]')
"""第二步:解析第一步得到的url"""
e_regex('url',r'(?P<url_proto>(\w+)):\/\/(?P<url_domain>[a-z0-9.]*[^\/])(?P<uri_param>(.+)$)')
"""第三步:解析第二步的到的url参数"""
e_regex('uri_param',r'(?P<uri_path>\/\_[a-z]+[^?])\?(?<uri_query>(.+)$)')

预览综上处理后的日志如下:

__source__:  30.43.16.15
__tag__:__client_ip__:  12.120.75.140
__tag__:__receive_time__:  1563443076
content: 203.208.60.89 - - [04/Jan/2019:16:06:38 +0800] "GET http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0 HTTP/1.1" 200 273932 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
ip: 203.208.60.89
datetime: 04/Jan/2019:16:06:38 +0800
verb: GET
request: http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0
protocol: HTTP/1.1
code: 200
sendbytes: 273932
refere: -
useragent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
url_proto: http
url_domain: cdn1cdedge0001.coxlab.net
uri_param: /_astats?application=&inf.name=eth0
uri_path: /_astats
uri_query: application=&inf.name=eth0                        

方案二:Grok解析

1、使用grok模式解析Nginx日志,只需要COMBINEDAPACHELOG模式即可。

模式 规则 说明
COMMONAPACHELOG `%{IPORHOST:clientip} %{HTTPDUSER:ident} %{USER:auth} [%{HTTPDATE:timestamp}] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})? %{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes} -)` 解析出clientip、ident、auth、timestamp、verb、request、httpversion、response、bytes字段内容
COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent} 解析出上一行中所有字段,另外还解析出referrer、agent字段

针对需求1解析Nginx日志的加工编排如下:

e_regex('content',grok('%{COMBINEDAPACHELOG}'))

预览处理日志:

clientip: 203.208.60.89
ident: -
auth: -
timestamp: 04/Jan/2019:16:06:38 +0800
verb: GET
request: http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0
httpversion: 1.1
response: 200
bytes: 273932
referrer: "-"
agent: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

2、解析request只需要使用grok的以下几种模式组合即可完成解析:

模式 规则 说明
URIPROTO [A-Za-z]+(\+[A-Za-z+]+)? 匹配url中的头部分,如http://hostname.domain.tld/_astats?application=&inf.name=eth0会匹配到http
USER [a-zA-Z0-9._-]+ 匹配字母、数字和._-组合
URIHOST %{IPORHOST}(?::%{POSINT:port})? 匹配IPORHOST和POSINT
URIPATHPARAM %{URIPATH}(?:%{URIPARAM})? 匹配url参数部分

针对需求2解析第一步加工后得到的request的加工编排如下:

e_regex('request',grok("%{URIPROTO:uri_proto}://(?:%{USER:user}(?::[^@]*)?@)?(?:%{URIHOST:uri_domain})?(?:%{URIPATHPARAM:uri_param})?"))

预览处理日志:

url_proto: http
url_domain: cdn1cdedge0001.coxlab.net
uri_param: /_astats?application=&inf.name=eth0

3、解析url_param可以使用grok的以下模式即可完成解析:

模式 规则 说明
GREEDYDATA .* 匹配任意或多个除换行符

针对需求3解析第二步得到的url参数的加工编排如下:

e_regex('url_param',grok("%{GREEDYDATA:uri_path}\?%{GREEDYDATA:uri_query}"))

预览处理日志:

uri_path: /_astats
uri_query: application=&inf.name=eth0

4、综上LOG DSL规则可以如以下形式:

"""第一步:初步解析Nginx日志"""
e_regex('content',grok('%{COMBINEDAPACHELOG}'))
"""第二步:解析第一步得到的url"""
e_regex('request',grok("%{URIPROTO:uri_proto}://(?:%{USER:user}(?::[^@]*)?@)?(?:%{URIHOST:uri_domain})?(?:%{URIPATHPARAM:uri_param})?"))
"""第三步:解析第二步的到的url参数"""
e_regex('url_param',grok("%{GREEDYDATA:uri_path}\?%{GREEDYDATA:uri_query}"))

预览综上处理后的日志如下:

__source__:  30.43.16.15
__tag__:__client_ip__:  12.120.75.140
__tag__:__receive_time__:  1563443076
content: 203.208.60.89 - - [04/Jan/2019:16:06:38 +0800] "GET http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0 HTTP/1.1" 200 273932 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
clientip: 203.208.60.89
ident: -
auth: -
timestamp: 04/Jan/2019:16:06:38 +0800
verb: GET
request: http://cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0
httpversion: 1.1
response: 200
bytes: 273932
referrer: "-"
agent: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
url_proto: http
url_domain: cdn1cdedge0001.coxlab.net
uri_param: /_astats?application=&inf.name=eth0
uri_path: /_astats
uri_query: application=&inf.name=eth0                        

对比

综上所述,可以看出使用正则解析和Grok模式解析Nginx日志两种方案优劣。

正则方案

对于不是很熟悉的开发人员使用正则解析日志效率会比较低,而且学习成本会比较大,另外一点是灵活性不够,比如在request内容改成

http://twiss@cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0

那么还使用以上正则

(?P<url_proto>(\w+)):\/\/(?P<url_domain>[a-z0-9.]*[^\/])(?P<uri_param>(.+)$)

request则会解析成

url_proto: http
url_domain: twiss@
uri_param: cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0

很显然,如果还使用原来的正则模式的话,解析出来的内容是不符合要求的。因此,还需要修改正则模式才能正常解析。由此可见,灵活的使用正则的解析的难度比较高。

Grok方案

Grok模式解析对于开发人员是友好的,对于非开发人员亦然如此。Grok学习成本低,只需要了解哪些模式代表的哪些字段类型就可以轻松解析你想解析的日志内容。Grok学习曲线低,可以通过用户文档中GROK参考来学习实践。

Grok灵活性高,比如还是以上述正则方案中例子为参考:

request内容改成

http://twiss@cdn1cdedge0001.coxlab.net/_astats?application=&inf.name=eth0

Grok模式不变

e_regex('request',grok("%{URIPROTO:uri_proto}://(?:%{USER:user}(?::[^@]*)?@)?(?:%{URIHOST:uri_domain})?(?:%{URIPATHPARAM:uri_param})?"))

request则会解析成

url_proto: http
user: twiss
url_domain: cdn1cdedge0001.coxlab.net
uri_param: /_astats?application=&inf.name=eth0

在Grok模式不变的情况下,request添加user的情况下,还是能够正确解析出正确的日志内容。

结论

从灵活性、高效性、低成本、学习曲线等方面对比, GROK都要比直接使用正则表达式要有优势. 但是GROK模式的本质其实还是正则表达式, 但是数据加工已经提供了400种模式包装了场景的正则, 建议优先使用. 当然在需要的情况下, 也可以混合使用GROK与正则甚至自行编写需要的正则.

进一步参考

欢迎扫码加入官方钉钉群获得实时更新与阿里云工程师的及时直接的支持:
image

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
13天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
121 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
1月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
224 3
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1630 14
|
24天前
|
XML JSON 监控
告别简陋:Java日志系统的最佳实践
【10月更文挑战第19天】 在Java开发中,`System.out.println()` 是最基本的输出方法,但它在实际项目中往往被认为是不专业和不足够的。本文将探讨为什么在现代Java应用中应该避免使用 `System.out.println()`,并介绍几种更先进的日志解决方案。
47 1
|
1月前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
31 0
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
46 2
|
1月前
|
数据可视化
Tensorboard可视化学习笔记(一):如何可视化通过网页查看log日志
关于如何使用TensorBoard进行数据可视化的教程,包括TensorBoard的安装、配置环境变量、将数据写入TensorBoard、启动TensorBoard以及如何通过网页查看日志文件。
197 0
|
1月前
|
存储 分布式计算 NoSQL
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
大数据-136 - ClickHouse 集群 表引擎详解1 - 日志、Log、Memory、Merge
40 0
|
1月前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
54 0
|
2月前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。

相关产品

  • 日志服务
  • 推荐镜像

    更多