查询条件:HTTP 方法为 GET 请求,cs-uri-stem 值为 /xztl/index.html,cs-uri-query 值为 subject=yy&grade=3&volume=a:
在 Node.js 中,只需用 indexOf 方法查询 ' GET /xztl/index.html subject=yy&grade=3&volume=a' 这个字符串是否在每一行中出现即可。
在 Log Parser 中,则需要用 WHERE 从句查询同时满足 HTTP 方法为 GET 请求、cs-uri-stem 值为 /xztl/index.html、cs-uri-query 值为 subject=yy&grade=3&volume=a 这三种条件的请求,这样工作量就大很多。
# 格式说明见下面的基本语法一节
.\LogParser.exe `
"SELECT cs-uri-stem AS Stem, count(*) AS Hits `
FROM 'c:\Project\IIS Logs\W3SVC2_hxhz\log\u_ex*.log' `
WHERE cs-method = 'GET' `
AND Stem = '/xztl/index.html' `
AND cs-uri-query = 'subject=yy&grade=3&volume=a' `
GROUP BY Stem" `
-i:W3C
在 Node.js 中,用正则表达式的 test 方法,检查每一行是否匹配 '/ GET \/tspt\/abcd\/v\d+\.html/' 这个正则表达式。
在 Log Parser 中,则要在查询条件中用上 LIKE 语法:
.\LogParser.exe `
"SELECT DISTINCT cs-uri-stem AS Stem `
FROM 'c:\Project\IIS Logs\W3SVC8_xinlan\log\u_ex*.log' `
WHERE Stem LIKE '/tspt/abcd/v%.html'" `
-i:W3C
比如一本书被访问的静态资源包括 /tspt/abcd/v1.html,/tspt/abcd/video/1/1.ts。这样的话,就必须用 ' GET \/tspt\/abcd\/v\d+\.html/' 这个正则来匹配,如果用 ' GET \/tspt\/abcd\/v' 这个正则,就会将 HTML 页面之外的访问数也统计进来。
# 格式说明见下面的基本语法一节
.\LogParser.exe `
"SELECT DISTINCT cs-uri-stem `
FROM 'c:\Project\IIS Logs\W3SVC8_xinlan\log\u_ex2102*.log' `
WHERE cs-uri-stem LIKE '/tspt/skjggyyzdbcjs/v%' `
ORDER BY cs-uri-stem" `
-i:W3C -rtp:-1
.\LogParser.exe `
"SELECT cs-uri-stem AS Uri, COUNT(*) `
FROM 'c:\Project\IIS Logs\W3SVC4-gyxq\2020-06\u_ex*.log' `
WHERE Uri = '/tspt/xztx/android-preview-pdf.html' `
OR Uri = '/tspt/xztx/download.html' `
OR Uri = '/tspt/xztx/mobile-read.html' `
OR Uri = '/tspt/xztx/mobile-read-android.html' `
OR Uri = '/tspt/xztx/preview.html' `
GROUP BY Uri"
Uri COUNT(ALL *)
----------------------------------- ------------
/tspt/xztx/download.html 23819
/tspt/xztx/preview.html 44839
/tspt/xztx/mobile-read.html 32796
/tspt/xztx/mobile-read-android.html 240
/tspt/xztx/android-preview-pdf.html 82
Statistics:
-----------
Elements processed: 7188238
Elements output: 5
Execution time: 18.74 seconds
SELECT distinct cs(User-Agent) `
FROM '[LOGFILEPATH]' `
WHERE cs-uri-stem='/tspt/xztxkx3b/index.html' `
OR cs-uri-stem='/tspt/xztxkx4b/index.html' `
OR cs-uri-stem='/tspt/xztxkx5b/index.html' `
OR cs-uri-stem='/tspt/xztxkx6b/index.html' `
OR cs-uri-stem='/tspt/xztxkxa3b/index.html' `
OR cs-uri-stem='/tspt/xztxkxa4b/index.html' `
OR cs-uri-stem='/tspt/xztxkxa5b/index.html' `
OR cs-uri-stem='/tspt/xztxkxa6b/index.html' `
OR cs-uri-stem='/tspt/xztxyy3b/index.html' `
OR cs-uri-stem='/tspt/xztxyy4b/index.html' `
OR cs-uri-stem='/tspt/xztxyy5b/index.html' `
OR cs-uri-stem='/tspt/xztxyy6b/index.html' `
统计带宽流量
下面的命令,可统计每单位时间内(1 分钟)服务器的带宽流量:
.\LogParser.exe `
"SELECT TO_LOCALTIME(QUANTIZE(time, 60)) as Minute, `
DIV(DIV(MUL(1.0, SUM(sc-bytes)), 131072), 60) as Mb `
FROM 'c:\Project\IIS Logs\temp\5.log' `
GROUP BY Minute `
ORDER BY Minute" `
-o:CSV >> "c:\Project\IIS Logs\temp\5.csv"
IIS 日志 vs. CNZZ 数据
自己在用 IIS 日志统计图书配套资源访问数的时候,统计的是每个 HTML 页面。而由于微信之类 APP 的缓存原因,有时用户打开页面时,不会向服务端请求 HTML,而是直接读取缓存中的 HTML。
但是 CNZZ 的统计脚本即使被缓存,也会照常向其服务器发送统计请求。
所以两相对比,用 IIS 日志统计出来的图书配套资源访问数,是比 CNZZ 要少的。但是 IIS 日志记录的请求信息更完整,比如用户原始 IP、浏览器 UserAgent 等等。
因此,在对外报告各业务访问数时,报告 CNZZ 统计出来的数据就行。对内统计访问数时,则报告 IIS 统计出来的数据。
方案对比:Node.js vs. Log Parser
相等查询
查询条件:
HTTP
方法为GET
请求,cs-uri-stem
值为/xztl/index.html
,cs-uri-query
值为subject=yy&grade=3&volume=a
:indexOf
方法查询' GET /xztl/index.html subject=yy&grade=3&volume=a'
这个字符串是否在每一行中出现即可。WHERE
从句查询同时满足HTTP
方法为GET
请求、cs-uri-stem
值为/xztl/index.html
、cs-uri-query
值为subject=yy&grade=3&volume=a
这三种条件的请求,这样工作量就大很多。用好学好知 2021 年 4 月份的 IIS 日志进行查询,30 天的日志一共 17.6G,对比两种方案的速度。
可以看出来,在相等查询时,Node.js 比 Log Parser 快太多了。
相似查询
对于比较旧的图书配套资源,URL 是类似下面的格式:
URL 中的 (1),代表着这里可以是任意数字,比如一本书制作了 10 个配套资源,这里就是 1~10。对于这种情况,自然就要用相似查询了。
test
方法,检查每一行是否匹配'/ GET \/tspt\/abcd\/v\d+\.html/'
这个正则表达式。用新蓝网 2021 年 1~6 月 182 天的日志进行查询,共 3.7G。
经过对比,Node.js 再次完胜!以后做 IIS 日志统计就用 Node.js 了!
备用工具:Log Parser
微软自己出的 Log Parser,查看前一节的对比数据,可知其效率比 Node.js 低很多。
日常使用 Log Parser 的话,可以用来查看某本书的配套资源都有哪些路径被访问到。
比如一本书被访问的静态资源包括 /tspt/abcd/v1.html,/tspt/abcd/video/1/1.ts。这样的话,就必须用
' GET \/tspt\/abcd\/v\d+\.html/'
这个正则来匹配,如果用' GET \/tspt\/abcd\/v'
这个正则,就会将 HTML 页面之外的访问数也统计进来。为了避免出现这种情况,就有必要先用 Log Parser 把
cs-uri-stem
字段先过一遍,看看 HTML 和其他静态资源都是什么格式的 URI,然后才好确定在 Node.js 中应该用怎样的方式处理。!!重大问题!!
用下面的语句查询 2021 年 2 月某本图书的配套资源页面访问情况时,可以正常查询到结果。
但如果日志范围由之前的
u_ex2102*.log
扩大到u_ex*.log
,也就是查询 2021 年全部的日志,那么输出结果为 0。目前还找不到问题的原因在哪里,为了避免此问题,之后用 Log Parser 查询半年或一年的日志时,每次只查询一个月的,而不是一次性查询完。主要语法
统计页面访问数
下面的代码,统计的是 2020 年 6 月,5个行知天下答案页面的访问数。
6 月份的 IIS 日志文件总体积为 2.94GB,共有 718 万多条的记录,Log Parser 用 19 秒的时间,就统计出了 5 个页面的访问数,效率还是很高的。
统计 UserAgent
下面的代码,统计的是行知天下下册二维码页面,独立的访客 UserAgent。将数据进一步处理,即可得知 Android、iOS 不同版本系统的用户数量及占比。
如果将该数据以月份为单位进行观察,则可进一步得知用户更换新设备的情况。
统计带宽流量
下面的命令,可统计每单位时间内(1 分钟)服务器的带宽流量:
如果要更改单位时间为小时或者秒,把上面代码中的 60 改成 3600 或者 1 就行。
而上面的 131072,是因为 1048576 bytes 等于 1Mbytes 又等于 8Mbits,所以 bytes 换算成 Mbits 就是 1:131072 的关系。
参考资料:Average bandwidth per second by half hour
解析带 X-Forwarded-For 字段的日志
在用 Log Parser 解析 IIS 日志的时候,发现遇到带 X-Forwarded-For 字段的日志会解析失败,报错信息为:Unknown field X-Forwarded-For found in #Fields directive。
Google 了一下 logparser Unknown field X-Forwarded-For found in #Fields directive,在 Query IIS logs with extra fields using LogParser 中给出的建议是设置日志输入格式为 -i:W3C,试了一下果然解决问题了,示例代码如下:
IIS module | Elasticsearch
这个模块可以将 IIS 导入并进行分析,还会处理成能够在 Kibana 中进行可视化展示的数据。
参考链接:https://www.elastic.co/guide/en/beats/filebeat/master/filebeat-module-iis.html
无效数据
各种爬虫
含阿里云爬虫 UserAgent 特征值
cs(User-Agent) 字段包含 YisouSpider 的,都是阿里云的爬虫,这样的数据没有统计价值,在用 LogParser 处理时需要去除。
含阿里云 IP 的数据
还有的访问数据,IP 来源为阿里云,但 cs(User-Agent) 是下面这种看起来正常的类型,也需要排除。
这就需要将阿里云的 IP 从统计过程中去掉。
关键字:阿里云的IP段
参考链接:谁有阿里云所有的IP段
校内 IP
石大(华东)网络 IP 地址
可用工具
CIDR 与 IPv4 地址间的转换
自研系统实现思路
事件模型设计思路(案例)
parse 不用关心数据接口,client 端随意传入相关结构即可。
但是,建议 client 要为每一种类型的数据设计一个数据模型。
也可以把每条数据称为事件模型。
事件模型用来描述操作行为,事件模型包括事件(Event)核心实体。
Event 实体
一个 Event 描述内容为:一个用户在某个时间点,某个地方,以某种方式完成了某个具体的事情。从这可以看出,一个完整的 Event,包含了如下关键因素。
代码中对应的字段如下:
required 字段必须强制带上。
你也可以扩展可选字段。拓展可选字段根据具体需求。
comment 字段作为描述字符串存在,尽可能表述出前后数据的差异。