课时3: Nginx 日志分析 | 学习笔记

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 快速学习课时3: Nginx 日志分析,介绍了课时3: Nginx 日志分析系统机制, 以及在实际应用过程中如何使用。

开发者学堂课程【DevOps 日志分析实战课时3: Nginx 日志分析】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/302/detail/3520


课时3: Nginx 日志分析


内容介绍

一、介绍

二、数据加工

三、举例

四、总结


一、介绍

阿里日志服务是面向日志场景提供了完整的解决方案,包括数据实时采集、数据加工、智能查询分析、数据分发,数据加工是阿里云日志服务提供了一项面向日志实施行处理的一项功能,提供了200多个函数,用来解决日制行处理过程中遇到的过滤、复制、分裂、补漏、孵化、转换等场景:

image.png

本次的主题是以 nginx 日制为例,主要介绍数据加工功能。


二、数据加工

数据加工的交互界面如下:

image.png

点开查询界面,界面上方有一个数据加工的开关,打开开关就可以进行数据加工的代码编写,右边是预览数据,会对数据加工的函数进行执行,查看效果,有两种预览的模式:第一种是快速预览,第二种是高级预览,一般情况下可以使用快速预览。

image.png

如果在数据加工的函数中,用到了数据孵化,用到了资源函数,可能会连接数据库或OSS。

快速预览模式,不会真正的去连数据库或者 oss,需要用围表数据,直接填入模拟数据的方式进行模拟,如果需要真实的连 oss 或 MySQL,需要用高级预览的方式,真实的运行。

在数据加工中需要支持哪些函数,需要点进dsl简介中查看,在左侧帮助文档中有函数总览,点开函数总览,可以看到完整的数据加工支持的函数列表,根据函数的场景,进行了分类,可以根据场景,选择相应的函数进行数据加工。


三、举例

首先给日志设置一个新的字段,例如设置一个a字段是 hello:

e_set(“a”,”hello”)

可以预览到新增了一个字段,在原始的数据里没有字段,在写完数据加工的作业以后,出现了保存数据加工的按钮,点击保存数据加工,进行下一个配置,就可以完成数据加工任务的上限。

1.如何使用正则提取字段

极简的方式采集了的 nginx 的日志,所有的数据内容都会放在字段里面,这样的日志内容非常不利于数据分析,可以先通过正则的方式把,把内容抽取成相应的字段,用到函数是 e_regex:

e_regex(“content" , (?<remote_addr>[0-9:\.]*)·(?<remote_user>[a-zA-Z0-9\-_]*)\[(?<local_time>[a-z4-Z0-9\/:\-\+]')\]

"(?<request>[^""]*)”(<status>[0-9]*)(?<body_bytes_sent>[0-9\-]*)“(?<refer>[^"]*)""(?<http_user_agent>[^""]")"")

先来听写的语句,第一个参数是需要被正则抽取的字段;

image.png

第二个内容是正则表达式,指定了有名捕获组,捕获到的字段的名字就是remote_addr,content 会被捕获,并且被命名为 remote addr 的字段,通过快速预览,看到以下效果:

local_time : 20/Feb/2019:04:19:09+0800

refer : www.bho.com

remote_addr: 111.205.218.44

remote_user : -

request : GET /api/service?

这是第一步,观察可以发现 localtime 不容易阅读,想变成比较常见的日期格式,可以使用以下几个方式:

image.png

(1)用于设置字段值

e_set("字段名","固定值或表达式函数")

(2)将时间字符串解析为日期时间对象

dt_strptime(tf 如 v(字段名),"格式化字符串”)

(3)将日期时间对象按照指定格式转换为字符串

dt_strftime(日期时间表达式"格式化字符串”)

image.png

语句如下:

e_set("local_time", dt_strftime(dt_strptime(v("local_time"),""%d/%b/%Y:%H:%M:%S%z")""%Y-%m-%d %H:%M:%S”))

首先在用 dt_strptime 取出 localtime 的内容,用指定格式解析,解析完以后得到一个日期时间格式的对象,对象可以被格式化,换成比较常见的日期格式 ,%d%b 就是对应了时间的格式,最终会把它再设回 localtime 字段,使用快速预览查看效果如下:

image.png

local_time : 2019-02-2004:19:09

第三步,request请求里面包含了三部分内容,第一部分是request method,第二部分是request url,是一个经过url的编码,第三部分是hpp的请求版本,首先可以三个字段通过正则的方式,解析成三个字段,还可以对url中的url进行urldecode处理,把真实请求字段转换回来,还可以抽取成的日志阶段方便后续做分析,用一下三行语句可以实现:

e_regex("request","(?<request_method>[^ls]*)(?<request_uri>[^\s]*)(?<http_version>[^ls]*)")

e_set( ""request_uri", url_decoding(v( ""request__uri")))

e_kv( "request_uri", prefix="uri_")

如果想注释掉一块代码,可以在选中以后,如果是在 mac 上,可以按下command+/,如果是 windows 电脑,可以用 ctrl+\。先把内容注释掉,通过 e_regex抽取,把 HP 的 version 抽取出来, URL 编码的可以进行一次解码操作,使用的是URLdecoding 的函数,函数输入需要一个 URLdecoding 的字符串,字符串来自request uri,通过 request 的 url,可以对日志里面的字段进行取值,取出完传给URL decoding,decode 以后再设置回 request uri,

效果如下:

request_uri : /apl/service?action=buy&item_id=278&item_name=

测试商品_278

此时 URL 已经还原成原始请求的样子,对该请求的KY进行抽取,可以使用 E_KV 指令,该指令可以对 request uri 里面的请求参数进行提取:

e_kv"request_uri", prefix=uri_"D

效果如下:

uri_action : buy

uri_item_id : 278

uri_itern_name:测试商品_278

前面加了一个前缀:uri_,是由 prefix 指定的,如果不指定 prefix 的话,会直接使用get请求中的k的名字作为抽取后的字段的名字。后续可能跟现在的字段冲突,为了统一,可以加 prefix,方便识别是这 url 里面参数解析出来的字段。

CP 请求里面也有 code 码,code 码对于每一次请求表达了返回的状态,每个code码有一份真实的含义,针对不同的 code 码有一个 code 码的类别,以及类别的英文说明以及 description,可以把映射列表跟日志装起来,做日志孵化的工作。

把 status 字段扩展,把它更多的信息放在在的日志里面,方便做更多的分析。孵化会用到以下三种式子:

#用来做字段孵化,类似 sql 里join 的功能

e_table_map(“表格对象",

"源字段映射列表“."自标字段列表")

#用来把csv文件解析成table对象

e_tab _parse_csv(cSV文本数据,sep=., quote=""")

#code的映射关系维度表是一个csv文件,存在oss上,使用

res_oss_file

res_oss_file(endpoint="OSS的endpoint", ak_id="OSS的AK_ID".

ak_key=-oSS的AK_KEY-, bucket="OSS的bucket" , file=-

在 OSS 中存的文件地址",

change_detect_interval="定时更新时间默认为0")

第一种是 e_table_map,e_table_map 的第一个参数需要传入一个表格对象,可以通过下面两个函数来获得,第二个参数是原字段映射,第三个字段是目标字段映射, table 对象可以通过 table  house csv 函数拿到,可以传入一个 csv 的文本,把它变成一个 table 对象,提供给 e_table_map 用,csv 文件支持从 oss 去把 csv 文件拉取下来,里面的参数就是相应的 oss 访问的一些参数,

代码如下:

e_table_map(

tab_parse_csv(

res_oss_file(endpoint="oss-cn-shanghai.aliyuncs.com",ak_id="",ak_key=",

bucket="ali-sls-etl-test",

file="http_code.csv , format='text')),(status , code")].

i(alias," http_code_alias"),

(description ," http_code_desc").(category ," http_code_category")”)

最外层使用 e_table_map 做孵化,第一个参数是一个 table对象,来自于 table pass csv, csv 的内容来自 oss,下面是 oss 是访问的 antoine,文件的格式是文本,第二个参数表示的是源字段映射关系,日志里面的状态码是 status,但是 csv 文件里面名字叫 code,通过 status code 映射,就可以做一些关联。

第三个参数是的目标字段映射,可以有 alias,distribution 和 catalog,分别对应围标里面的 alias,catalogue discribing 这三个字段,这三个字段在孵化以后,可以取一个新的名字,也可以使用原始的名字。使用快速预览的时候,如果遇到孵化的场景,不会真实的去拉 oss 的文件,所以此时快速预览会失败,在第9行处理的时候,遇到一个问题,可以使用直接贴入尾表数据,做模拟,贴上之后再做一次快速预览,就已经不报错了,有三个新的字段已经映射出来。再做一些模拟,改 code 码,看映射的效果,通过快速预览,数据可以更改的,快速预览的时候,数据来自于 dect,例如301改成502。

可以使用高级晕染的方式,高级预览会比快速预览会慢一点,因为真实的跑数据加工的流程,使用高级预览的话,没法使用模拟的数据去做修改,因为会真实拉原始数据去加工。

xsid 和 key 是为空,因为 hpco 的 csv 文件是 public 可读,所以这里可以不填 xsid和 key,所以这里可以不填 xsid 和 t 如果是一个,如果是私有的权限,需要设置相应的xsid 和 key。agent 字段包含了客户端的 agent 信息,包括浏览器操作系统等信息,有函数来对数据进行解析,可以使用数据加工中的 uso 函数进行解析,解析完成以后,获得到的是一个对象,可以再对象进行处理,最终可以得到相应的解析效果,但是中间会用到一个临时字段,保存了结构,可以使用 e_drop_fileds 来做临时的字段清理。

e_set(""ua",ua_parse_all(v("http_user_agent"")))

# e_json("ua",fmt='full ' ,sep='_')

#e_drop_fields("ua" ,regex=False)

e_set(""ua",ua_parse_all(v("http_user_agent"")))得到的是 json,里面包含了解析结果,能把浏览器的信息解析出来,包括浏览器版本号以及操作系统以及的版本号信息,解析完以后,不符合的要求,因为要做分析的时候,可能需要把里面的操作系统以及浏览器的信息提取到第1层,可以使用 json 函数,对 json 进行打平处理。

第一个字段是输入 UA,UA 是日志字段,format 就是按照全路线进行打平,打平的时候,可以使用一个分格符,效果如下:

ua device_familily : Mac

ua device_model : Mac

ua_os_family : Mac os x

ua_os_maior : 10

ua_os_minor : 6

通过 e_json 以后,中间临时字段已经没用,想要的信息都已经解析到第一层,所以可以使用 e drop fields,进行丢弃。这里指定了一regex=false,表示不是使用正则方式去匹配。

最后一个场景,针对非200的错误进行投递,因为一般情况下的日志,访问请求都是200的请求,如果出现了非200的请求,那么服务端或者整个服务有异常情况,这种情况需要关注的,可以把这一类非200类的错误,投递到指定的log,以便后面去做分析。

条件判断 if

e_if(条件1如e_match(...)"。,"操作1如e_regex(.…)"."条件2","操作2".…)

判断是否相等

op_ne(v(字段名1'), v("字段名2"))

# output发送到目标名称,目标名称在数据加工保存任务的时候配置对应的logstore信息

e_output(name=“指定的目标名称")

日志投递会用到EM来做条件判断,判断code码是否是满足2xx的场景,n e可以判断的HBcodeamis,就是孵化以后产生的字段,已经对code码进行了分类,所以只要对字段进行判断, opne就是表示not equal,最后是e_ oppot,需要指定一个目标名称,在保存任务的时候会用到目标名称,需要保持一致。

代码如下:

e_if(op_ne(v("http_code_alias""),J2xx"),e_output(name="nginx-log-bad""))

判断是否等于2xx,如果不等于2xx的话,就去投递,条件如果满足的话,就做后面事情,后面事情就是做 e_output,把日志分发到目标,分发到目标以后,一个完整的日志就处理完了,如果说没有满足2XX的话,会默认继续执行,代码执行后输出目标发生了变化,变成了ngs logbed,就是变成了目标名称,日志是502的日志,它属于5xx,所以需要被关注的,会投递到 INDEX LOGONBED 目标,默认情况下会投递到target0,target0也就是在任务保存的时候的第一个 logstore。

点击保存后需要取一个名字,例如叫 nginx,第一个需要填的 target0,日志处理完以后,默认就会进入 target0,需要设定投递的 logostore,例如默认投递的是Nginx-log-default,点击确定,还要再建一个异常来接收非200的异常日制,保存,默认情况下数据加工的流程完以后,会进入第一个 logostore,对于满足条件的会进入Nginx-log-bad 里面,名称需要跟负责这里指定的内容保持一致。

加工的范围,例如可以选择从现在开始加工,点击确定,任务创建完成。任务创建完成以后,可以通过以下两种方式看到:

第一个是可以通过左侧的数据加工,叫 NBC ,还可以在 instagram logger 下的数据处理加工,此处展示了数据加工的状态,这里有原 logstore 信息以及存储目标logstore 信息,以原 logstore 消费的点位信息,以及数据加工的速率,以及每个延迟和速度情况,如果加工过程中有一些错误,会展示在日常详情里面。Shard 是加工订阅到的下载的列表,与上面的 shard 列表是一致的。开索引会方便做查询分析,加工任务启动后,会开始有一些指标打印出来。如果没有2xx的日志,所以就不会投递过来,可以稍微等一会。

2.查询可视化,以及报警设置

如果要查看所有异常日制的扣 code 分类,可以通过查询分析属性设置,来生成索引,点自动生成索引,可以建立相应的索引,建完索引以后,就可以 code 字段进行统计,就可以进行相应的分析和报警,建立完索引以后,索引的生效是对后面新系列的数据生效的,此时可以查看能否使用 SQL 查询,查询页面如下:

image.png

查询的数据比总条数要少一些,是因为没有建立索引的时候,这些数据不会统计进去,需要对数据再进行可视化,例如想把它变成丙图,可以再点饼图,此时就会出现饼图:

image.png

按照 code 分类,做完图以后,想把它变成仪表盘,也方便后续直接去查看,可以点击添加到仪表盘,选择新建仪表盘,例如建立如下仪表盘:

操作类型:新建仪表盘

仪表盘名称:错误日志仪表盘

图表名称:错误 code 统计 t

点击确定,左侧有一个仪表盘的 tag,有创建的错误日志,如果想对仪表,做一些调整,例如改查询时间,甚至可以调整图表的位置布局大小,可以点编辑,然后点保存。

假设需要对错误的 code,再进行报警,仪表盘上面已经有一个报警的按钮,可以点创建,例如可以做一个错误码报警,点击添加,选择仪表是错误 code 统计,下面是一个触发条件,触发条件可以用c的值,例如大于500 就需要报警,报警触发的频率以及每次查询多久的时间范围,根据实际情况选择,按照下一步提示,可以支持把报警信息发到短信,语音以及阿里云站点的通知中心,例如可以把它发到指定的邮箱,点击,例如写一个合法的邮箱,主题是报警,写一条 message,可以引用一些变量信息

image.png

报警在启用以后,会有统计的报表。

image.png


四、总结

以最常见的 Nginx 日志作为例,介绍数据加工在日志的转化、处理、富化、转发等场景下相关的函数使用,参考的内容∶

a) SLS 数据加工整体简介:https://help.aliyun.com/document detail/125384.html

b)SLS 数据加工函数总览:https://help.aliyun.com/document detail/159702.html

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
运维 监控 应用服务中间件
LNMP详解(十五)——Nginx日志分析实战
LNMP详解(十五)——Nginx日志分析实战
34 0
|
1月前
|
运维 应用服务中间件 Shell
LNMP详解(十六)——Nginx日志切割
LNMP详解(十六)——Nginx日志切割
26 5
|
2月前
|
存储 JSON 应用服务中间件
Higress的日志收集中,底层用的是Envoy,可不可以实现类似NGINX的rsyslog发送?
【2月更文挑战第30天】Higress的日志收集中,底层用的是Envoy,可不可以实现类似NGINX的rsyslog发送?
22 2
|
12天前
|
弹性计算 应用服务中间件 Shell
切割 Nginx 日志文件
【4月更文挑战第28天】
20 0
|
12天前
|
弹性计算 应用服务中间件 Shell
切割Nginx 日志文件
【4月更文挑战第29天】
20 1
|
1月前
|
存储 应用服务中间件 nginx
nginx日志定时切割 按年月日
nginx日志定时切割 按年月日
18 0
|
1月前
|
网络协议 应用服务中间件 Linux
centos7 Nginx Log日志统计分析 常用命令
centos7 Nginx Log日志统计分析 常用命令
151 2
|
1月前
|
运维 监控 应用服务中间件
LNMP详解(十四)——Nginx日志详解
LNMP详解(十四)——Nginx日志详解
30 2
|
1月前
|
存储 监控 数据可视化
Nginx+Promtail+Loki+Grafana Nginx日志展示
通过这些步骤,你可以将Nginx的日志收集、存储、查询和可视化整合在一起。这样,你就可以在Grafana中轻松地创建和展示Nginx日志的图表和面板。
43 3
|
4天前
|
C++
JNI Log 日志输出
JNI Log 日志输出
12 1