21

我知道周围还有其他工具,例如 awstats 或 splunk,但我想知道 R 中是否正在进行一些严肃的(网络)服务器日志文件分析。我可能不是第一个想到在 R 中做这件事的人,但 R 仍然有很好的可视化功能和不错的空间包。你知道吗?或者是否有一个 R 包/代码可以处理可以构建的最常见的日志文件格式?或者这只是一个非常糟糕的主意?

4

5 回答 5

14

在为我们的网络运营人员构建分析工具箱的项目中,我大约在两个月前构建了其中一个。如果我开源它,我的雇主没有问题,所以如果有人感兴趣,我可以把它放在我的 github repo 上。我认为如果我构建一个 R 包,它对这个群体最有用。不过,我将无法立即执行此操作,因为我需要研究有关使用非 R 代码构建包的文档(这可能就像在 /exec 中扔 python 字节码文件以及合适的 python 运行时一样简单,但是我不知道)。

我真的很惊讶我需要承担这样的项目。至少有几个优秀的开源和免费日志文件解析器/查看器(包括优秀的 Webalyzer 和 AWStats),但都没有解析服务器错误日志(解析服务器访问日志是两者的主要用例)。

如果你不熟悉错误日志或者它们与访问日志的区别,总之,Apache 服务器(likewsie、nginx 和 IIS)会记录两个不同的日志,并默认将它们彼此相邻地存储在磁盘的同一目录中。在 Mac OS X 上,该目录位于 /var 中,就在 root 之下:

$> pwd
   /var/log/apache2

$> ls
   access_log   error_log

对于网络诊断,错误日志通常比访问日志有用得多。由于许多字段中数据的非结构化性质,它们也恰好更难以处理,更重要的是,因为解析后留下的数据文件是不规则的时间序列——您可能有多个键控条目到单个时间戳,然后下一个条目在三秒后,依此类推。

我想要一个应用程序,我可以在原始错误日志(任何大小,但通常一次几百 MB)中折腾一些有用的东西从另一端出来——在这种情况下,它必须是一些预先打包的分析和也是 R 中可用于命令行分析的数据立方体。鉴于此,我在 python 中编写了原始日志解析器,而处理器(例如,对解析器输出进行网格化以创建常规时间序列)以及所有分析和数据可视化,我在 R 中编写。

我一直在构建分析工具很长一段时间,但仅在过去四年中我才使用 R。所以我的第一印象——在解析原始日志文件并在 R 中加载数据帧时,R 是一种乐趣使用它以及它如何非常适合此类任务。一些受欢迎的惊喜:

  • 序列化。在 R 中持久化工作数据是一个命令(保存)。我知道这一点,但我不知道这种二进制格式的效率如何。您的实际数据:每解析 50 MB 的原始日志文件,.RData 表示约为 500 KB--100 : 1 压缩。(注意:我通过使用 data.table 库并将压缩级别参数手动设置为 save 函数将其进一步降低到大约 300 : 1);

  • IO。我的数据仓库严重依赖一个轻量级的数据结构服务器,它完全驻留在 RAM 中并异步写入磁盘,称为 redis。该项目本身只有大约两年的历史,但在 CRAN 中已经有一个 R 的 redis 客户端(由 BW Lewis 提供,截至本文的版本为 1.6.1);

  • 主要数据分析. 该项目的目的是为我们的网络运营人员构建一个库。我的目标是“一个命令=一个数据视图”类型的界面。例如,我使用出色的 googleVis 包创建了一个具有可排序列的专业外观的可滚动/分页 HTML 表格,其中我加载了一个聚合数据的数据框(> 5,000 行)。只是那些少数交互式元素——例如,对列进行排序——提供了有用的描述性分析。另一个例子,我为一些基本的数据处理和类似表格的函数写了很多精简的包装器;例如,这些功能中的每一个都绑定到选项卡式网页上的可点击按钮。同样,这在 R 中是一种乐趣,部分原因是该函数通常不需要包装器,

最后一个项目符号的几个示例:

# what are the most common issues that cause an error to be logged?

err_order = function(df){
    t0 = xtabs(~Issue_Descr, df)
    m = cbind( names(t0), t0)
    rownames(m) = NULL
    colnames(m) = c("Cause", "Count")
    x = m[,2]
    x = as.numeric(x)
    ndx = order(x, decreasing=T)
    m = m[ndx,]
    m1 = data.frame(Cause=m[,1], Count=as.numeric(m[,2]),
                    CountAsProp=100*as.numeric(m[,2])/dim(df)[1])
    subset(m1, CountAsProp >= 1.)
}

# calling this function, passing in a data frame, returns something like:


                        Cause       Count    CountAsProp
1  'connect to unix://var/ failed'    200        40.0
2  'object buffered to temp file'     185        37.0
3  'connection refused'                94        18.8


使用 googleVis 为交互式分析显示的主数据立方体:使用 googleVis 显示

使用 googleVis 为交互式分析显示的主数据立方体

的列联表(来自 xtab 函数调用)

在此处输入图像描述

于 2011-07-13T01:50:28.130 回答
9

这实际上是一个绝妙的主意。R 还具有非常好的日期/时间功能,可以进行聚类分析或使用各种机器学习算法,具有三种不同的正则表达式引擎来解析等 pp。

这可能不是一个新颖的想法。几年前,我与使用 R 进行主动(而不是被动)日志文件分析的人进行了简短的电子邮件联系:阅读日志,(在他们的情况下)构建时间序列模型,预测热点。这显然是个好主意。它是能源部实验室之一,但我不再有 URL。即使在时间模式之外,这里也可以做很多事情。

于 2011-04-14T14:48:12.347 回答
4

我已经使用 R 加载和解析 IIS 日志文件并取得了一些成功,这是我的代码。

Load IIS Log files
require(data.table)

setwd("Log File Directory")

# get a list of all the log files
log_files <- Sys.glob("*.log")

# This line
# 1) reads each log file
# 2) concatenates them
IIS <- do.call( "rbind", lapply( log_files,  read.csv, sep = " ", header = FALSE, comment.char = "#", na.strings = "-" ) )

# Add field names - Copy the "Fields" line from one of the log files :header line 
colnames(IIS) <- c("date", "time", "s_ip", "cs_method", "cs_uri_stem", "cs_uri_query", "s_port", "cs_username", "c_ip", "cs_User_Agent", "sc_status", "sc_substatus", "sc_win32_status", "sc_bytes", "cs_bytes", "time-taken")

#Change it to a data.table
IIS <- data.table( IIS )

#Query at will
IIS[, .N, by = list(sc_status,cs_username, cs_uri_stem,sc_win32_status) ]
于 2014-04-25T15:00:11.277 回答
1

我最近使用 R 进行了日志文件分析。这不是真正复杂的事情,主要是描述性表。R 的内置函数足以胜任这项工作。
问题是数据存储,因为我的日志文件大约 10 GB。Revolutions R 确实提供了处理此类大数据的新方法,但我最终决定使用 MySQL 数据库作为后端(实际上通过标准化将大小减小到 2 GB)。
这也可以解决您在 R 中读取日志文件的问题。

于 2011-04-15T07:06:04.933 回答
1
#!python

import argparse
import csv
import cStringIO as StringIO

class OurDialect:
    escapechar = ','
    delimiter = ' '
    quoting = csv.QUOTE_NONE


parser = argparse.ArgumentParser()
parser.add_argument('-f', '--source', type=str, dest='line', default=[['''54.67.81.141 - - [01/Apr/2015:13:39:22 +0000] "GET / HTTP/1.1" 502 173 "-" "curl/7.41.0" "-"'''], ['''54.67.81.141 - - [01/Apr/2015:13:39:22 +0000] "GET / HTTP/1.1" 502 173 "-" "curl/7.41.0" "-"''']])
arguments = parser.parse_args()

try:
    with open(arguments.line, 'wb') as fin:
        line = fin.readlines()
except: 
    pass
finally:
    line = arguments.line

header = ['IP', 'Ident', 'User', 'Timestamp', 'Offset', 'HTTP Verb', 'HTTP Endpoint', 'HTTP Version', 'HTTP Return code', 'Size in bytes', 'User-Agent']

lines = [[l[:-1].replace('[', '"').replace(']', '"').replace('"', '') for l in l1] for l1 in line]

out = StringIO.StringIO()

writer = csv.writer(out)
writer.writerow(header)

writer = csv.writer(out,dialect=OurDialect)
writer.writerows([[l1 for l1 in l] for l in lines])

print(out.getvalue())

演示输出:

IP,Ident,User,Timestamp,Offset,HTTP Verb,HTTP Endpoint,HTTP Version,HTTP Return code,Size in bytes,User-Agent
54.67.81.141, -, -, 01/Apr/2015:13:39:22, +0000, GET, /, HTTP/1.1, 502, 173, -, curl/7.41.0, -
54.67.81.141, -, -, 01/Apr/2015:13:39:22, +0000, GET, /, HTTP/1.1, 502, 173, -, curl/7.41.0, -

使用 read.csv 可以轻松地将这种格式读入 R。而且,它不需要任何 3rd 方库。

于 2016-04-09T03:55:10.873 回答