Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何使用Spark解析可能跨越多行的日志行_Regex_Scala_Apache Spark_Multiline - Fatal编程技术网

Regex 如何使用Spark解析可能跨越多行的日志行

Regex 如何使用Spark解析可能跨越多行的日志行,regex,scala,apache-spark,multiline,Regex,Scala,Apache Spark,Multiline,我正在开发一个Spark/Scala应用程序,它可以读取和解析自定义日志文件。我在分析多行日志条目时遇到问题。以下是我的代码片段: case class MLog(dateTime: String, classification: String, serverType: String, identification:String, operation: String) val PATTERN = """(?s)(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3}

我正在开发一个Spark/Scala应用程序,它可以读取和解析自定义日志文件。我在分析多行日志条目时遇到问题。以下是我的代码片段:

case class MLog(dateTime: String, classification: String, serverType: String, identification:String, operation: String)
val PATTERN = """(?s)(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3})\s+(\w+)s+\[(.*)\]\s+\[(.*)\]\s+(.*)"""


def parseLogLine(log: String): MLog={
     val res = PATTERN.findFirstMatchIn(log)
     if (res.isEmpty) {
     throw new RuntimeException("Cannot parse log line: " + log)

     MLog(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5))
}

sc.textFile("/mydirectory/logfile").map(parseLogLine).foreach(println)
日志文件中的某些条目跨越多行。正则表达式适用于单行条目,但当读取多行条目时,如下图所示

2015-08-31 00:10:17,682 WARN  [ScheduledTask-10] [name=custname;mid=9999;ds=anyvalue;] datasource - Scheduled DataSource import failed.                 
com.xxx.common.service.ServiceException: system failure: Unable to connect to ANY server: LdapDataSource{id=xxx, type=xxx, enabled=true, name=xxx, host=xxx port=999, connectionType=ssl, username=xxx, folderId=99999}
我收到这个错误:

无法分析日志行:com.xxx.common.service.ServiceException:系统故障:无法连接到任何服务器:LdapDataSource{id=xxx,type=xxx,enabled=true,name=xxx,host=xxx port=999,connectionType=ssl,username=xxx,folderId=99999}


如何让Spark从日志文件中读取多行日志条目?

由于输入文件很小,您可以使用
SparkContext.wholeTextFiles

// Parse a single file and return all extracted entries
def parseLogFile(log: String): Iterator[MLog] = {
    val p: scala.util.matching.Regex = ???
    p.findAllMatchIn(log).map(
        m => MLog(m.group(1), m.group(2), m.group(3), m.group(4), m.group(5))
    )
}

val rdd: RDD[MLog] = sc
   .wholeTextFiles("/path/to/input/dir")
   .flatMap{case (_, txt) => parseLogFile(txt)}

单个文件有多大?这些能适合一个工人吗?是的。文件很小,大约40MB。该函数将打印出单行条目,但当它到达多行条目时,由于我提到的错误而失败。谢谢!成功了!如果我想使用sc.textFiles方法呢?随着时间的推移,日志文件可能会变得非常大,我想确保我仍然可以使用相同的代码。如果你能处理一些信息丢失,你可以简单地
mapPartitions
并删除不完整的记录。如果没有,您可以编写自定义Hadoop输入格式或
mapPartitions
,并在以后修复跨越两个分区的记录。最后,您可以尝试配置日志记录,以使输入文件保持一个工作人员可以处理的合理大小。如何确定文件是否足够小,可以由wholeTextFiles()处理?(我的文件是~250 MB…)@c-rod这里是一个使用文本文件的示例,其中主要区别是使用正则表达式方法
findFirstMatchIn
,它返回选项[Match],而不是返回迭代器[Match]的
findAllMatchIn
,并使用
map
而不是
flatmap
。在
wholeTextFiles
示例中,您需要一个迭代器,因为它将包含文件中的所有匹配项,因此需要平面映射该迭代器。使用textFile,您只需映射行即可。请参阅:注意textFile方法将拆分行,因此没有多行。你需要完整的文件