2015-09-04 15 views
4

我正在開發可讀取和解析自定義日誌文件的Spark/Scala應用程序。我在解析多行日誌條目時遇到問題。以下是我的代碼片段:如何使用可能跨越多行的Spark解析日誌行

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} 

我收到此錯誤:

Cannot parse log line: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}

我怎樣才能得到星火閱讀多日誌文件中的行日誌條目?

+0

單個文件有多大?這些適合一個工人嗎? – zero323

+0

是的。該文件很小 - 大約40MB。該函數將打印出單行條目,但是當它到達多行條目時,它會因我提到的錯誤而失敗。 –

回答

2

由於輸入文件很小,您可以使用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)} 
+0

謝謝!這工作!如果我想使用sc.textFiles方法怎麼辦?隨着時間的推移日誌文件可能會變得非常大,我想確保我仍然可以使用相同的代碼。 –

+0

一般來說,沒有一種方法可以處理多行記錄。如果你可以處理一些信息丟失,你可以簡單地'mapPartitions'並刪除不完整的記錄。如果沒有,您可以編寫自定義Hadoop輸入格式或'mapPartitions'並稍後修復跨越兩個分區的記錄。最後,您可以嘗試配置您的日誌記錄,以便將輸入文件保持在可由單個工作人員處理的合理大小。 – zero323

+0

如何確定一個文件是否足夠小以便由整個文本文件()處理? (我的文件是〜250 MB ...) – jimijazz