使用Data Lake Analytics快速分析OSS上的日志文件
程序员文章站
2022-07-14 20:38:46
...
背景
Data Lake Analytics (后文简称 DLA)是Serverless化的云上交互式查询分析服务,用户可以通过标准的SQL语句对存储在OSS, OTS, RDS等介质上的数据进行快速地查询分析。
日志文件在大数据分析中的地位举足轻重。对于一个服务来说,其日志文件往往记录了其运行的所有详细信息。无论是故障排除,状态监控,还是预测告警,都离不开对日志文件的查询分析。由于OSS的高性价比,越来越多的用户倾向把大量的日志文件存储在OSS中。DLA可以无需移动OSS上的日志文件,直接对其做查询分析。
本文将介绍如何使用DLA对常见格式的日志文件做查询。
使用DLA查询日志文件
DLA可以分析的日志文件需要满足下面的条件:
- 日志文件是纯文本的格式,每行可以映射为表中的一条记录;
- 每行的内容有固定的模式,可以用一个正则表达式去匹配
目前对日志文件的支持还仅限于OSS数据源,因此需要用户预先将日志文件保存于OSS中。
对日志文件建表时,最麻烦的一步就是写正则表达式。下面将以常见的日志文件为例,给出每种文件类型的正则表达式供大家参考。
Apache WebServer 日志
文件内容
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
127.0.0.1 - - [26/May/2009:00:00:00 +0000] "GET /someurl/?track=Blabla(Main) HTTP/1.1" 200 5864 - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.65 Safari/525.19"
正则表达式
([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\") ([^ \"]*|\"[^\"]*\"))?
建表语句
CREATE EXTERNAL TABLE webserver_log(
host STRING,
identity STRING,
userName STRING,
time STRING,
request STRING,
status STRING,
size INT,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\") ([^ \"]*|\"[^\"]*\"))?"
)
STORED AS TEXTFILE
LOCATION 'oss://mybucket/datasets/path/to/webserver.log';
查询结果
mysql> select * from webserver_log;
+-----------+----------+-------+------------------------------+---------------------------------------------+--------+------+---------+--------------------------------------------------------------------------------------------------------------------------+
| host | identity | userName | time | request | status | size | referer | agent |
+-----------+----------+-------+------------------------------+---------------------------------------------+--------+------+---------+--------------------------------------------------------------------------------------------------------------------------+
| 127.0.0.1 | - | frank | [10/Oct/2000:13:55:36 -0700] | "GET /apache_pb.gif HTTP/1.0" | 200 | 2326 | NULL | NULL |
| 127.0.0.1 | - | - | [26/May/2009:00:00:00 +0000] | "GET /someurl/?track=Blabla(Main) HTTP/1.1" | 200 | 5864 | - | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.65 Safari/525.19" |
+-----------+----------+-------+------------------------------+---------------------------------------------+--------+------+---------+--------------------------------------------------------------------------------------------------------------------------+
Ngnix访问日志
以NGINX文档中提到的format为例:https://docs.nginx.com/nginx/admin-guide/monitoring/logging/#
文件内容
127.0.0.1 - - [14/May/2018:21:58:04 +0800] "GET /?stat HTTP/1.1" 200 182 "-" "aliyun-sdk-java/2.6.0(Linux/2.6.32-220.23.2.ali927.el5.x86_64/amd64;1.6.0_24)" "-"
127.0.0.1 - - [14/May/2018:21:58:04 +0800] "GET /?prefix=&delimiter=%2F&max-keys=100&encoding-type=url HTTP/1.1" 200 7202 "https://help.aliyun.com/product/70174.html" "aliyun-sdk-java/2.6.0(Linux/2.6.32-220.23.2.ali927.el5.x86_64/amd64;1.6.0_24)" "-"
正则表达式
([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) (\".*?\") (-|[0-9]*) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) (\".*?\") (-|[0-9]*) (-|[0-9]*)
建表语句
CREATE EXTERNAL TABLE ngnix_log(
remote_address STRING,
identity STRING,
remote_user STRING,
time_local STRING,
request STRING,
status STRING,
body_bytes_sent INT,
http_referer STRING,
http_user_agent STRING,
gzip_ratio STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\") ([^ \"]*|\"[^\"]*\"))? ([^ \"]*|\"[^\"]*\")"
)
STORED AS TEXTFILE
LOCATION 'oss://mybucket/datasets/path/to/ngnix_log';
查询结果
mysql> select * from ngnix_log;
+----------------+----------+-------------+------------------------------+-----------------------------------------------------------------------+--------+-----------------+----------------------------------------------+---------------------------------------------------------------------------------+------------+
| remote_address | identity | remote_user | time_local | request | status | body_bytes_sent | http_referer | http_user_agent | gzip_ratio |
+----------------+----------+-------------+------------------------------+-----------------------------------------------------------------------+--------+-----------------+----------------------------------------------+---------------------------------------------------------------------------------+------------+
| 127.0.0.1 | - | - | [14/May/2018:21:58:04 +0800] | "GET /?stat HTTP/1.1" | 200 | 182 | "-" | "aliyun-sdk-java/2.6.0(Linux/2.6.32-220.23.2.ali927.el5.x86_64/amd64;1.6.0_24)" | "-" |
| 127.0.0.1 | - | - | [14/May/2018:21:58:04 +0800] | "GET /?prefix=&delimiter=%2F&max-keys=100&encoding-type=url HTTP/1.1" | 200 | 7202 | "https://help.aliyun.com/product/70174.html" | "aliyun-sdk-java/2.6.0(Linux/2.6.32-220.23.2.ali927.el5.x86_64/amd64;1.6.0_24)" | "-" |
+----------------+----------+-------------+------------------------------+-----------------------------------------------------------------------+--------+-----------------+----------------------------------------------+---------------------------------------------------------------------------------+------------+
Aapache Log4j 日志
以Hadoop默认生成的日志文件为例。
文件内容
2018-11-27 17:45:23,128 INFO org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler: Minimum allocation = <memory:1024, vCores:1>
2018-11-27 17:45:23,128 INFO org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler: Maximum allocation = <memory:8192, vCores:4>
2018-11-27 17:45:23,154 INFO org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration: max alloc mb per queue for root is undefined
2018-11-27 17:45:23,154 INFO org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration: max alloc vcore per queue for root is undefined
正则表达式
^(\\d{4}-\\d{2}-\\d{2})\\s+(\\d{2}.\\d{2}.\\d{2}.\\d{3})\\s+(\\S+)\\s+(\\S+)\\s+(.*)$
建表语句
CREATE EXTERNAL TABLE log4j_log(
date STRING,
time STRING,
level STRING,
class STRING,
details STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "^(\\d{4}-\\d{2}-\\d{2})\\s+(\\d{2}.\\d{2}.\\d{2}.\\d{3})\\s+(\\S+)\\s+(\\S+)\\s+(.*)$"
)
STORED AS TEXTFILE
LOCATION 'oss://oss-cn-beijing-for-openanalytics-test-2/datasets/jinluo/nginx/log4j_sample.log';
查询结果
mysql> select * from log4j_log;
+------------+--------------+-------+--------------------------------------------------------------------------------------------------+-------------------------------------------------+
| date | time | level | class | details |
+------------+--------------+-------+--------------------------------------------------------------------------------------------------+-------------------------------------------------+
| 2018-11-27 | 17:45:23,128 | INFO | org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler: | Minimum allocation = <memory:1024, vCores:1> |
| 2018-11-27 | 17:45:23,128 | INFO | org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler: | Maximum allocation = <memory:8192, vCores:4> |
| 2018-11-27 | 17:45:23,154 | INFO | org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration: | max alloc mb per queue for root is undefined |
| 2018-11-27 | 17:45:23,154 | INFO | org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration: | max alloc vcore per queue for root is undefined |
+------------+--------------+-------+--------------------------------------------------------------------------------------------------+-------------------------------------------------+
总结
对于写日志文件的正则表达式:
- 正则表达式中的每个字段用 () 作为边界,日志中通常每个字段以空格分隔。
- 建表语句中定义的列的个数要和正则表达式中的字段数完全匹配。
- 通常,数字可以用 ([0-9]*) 或者 (-|[0-9]*) 匹配,字符串用(1*) 或者 (".*?") 匹配