LogParser微軟開發的一個強大的日志分析軟件,他的大名還是在和微軟合作項目的時候聽說的,但當時只是為了分析iis日志使用,可以很方便的把iis日志導入數據庫中。
最近做的一個exchange監控系統時候需要分析log日志又把他拎了出來詳細研究了一下。
LogParser主用分為以下幾塊:
- Input Formats
- Output Formats
- Query Syntax
Input Formats 可根據分析log文件格式不同選用內置的一些解析器,其中最常用的CSV格式。
Output Formats 輸出文件的格式,主用用在命令行模式下把處理的數據進行導出處理時使用。
Query Syntax 在用logparser分析日志文件時可把文件理解成數據庫的表,可以執行一些基本的sql語句來對日志文件進行查詢過濾等操作。
LogParser另一個強大之處是可以轉換成COM+,使其他語言可以進行調用,例如exchange日志進行分析時,我就是用.net來對日志進行二次處理的。
本次Exchange日志分析思路:
由於exchange服務器是多台集群,所以日志會分散在多台服務器上,並且日志是不重復的,所以利用.net通過網絡鄰居訪問多台服務器日志目錄,然后對目錄進行定時抓取日志,利用LogParser對日志進行簡單過濾,然后倒入到數據庫中。前台通過倒入的原始數據進行數據分析。
基本代碼實現:
1 using (IdentityScope c = new IdentityScope("mossadmin", "inet", "password")) //通過網絡鄰居訪問時提供域中號密碼 2 { 3 var logs = System.IO.Directory.GetFiles(LogPath, "*.log") //遍歷目錄內所有文件,篩選出大於等於上次更新文件 4 .Where(f => int.Parse(f.Substring(f.LastIndexOf('\\') + 7, 8)) >= _config.fileDT) 5 .OrderBy(f => int.Parse(f.Substring(f.LastIndexOf('\\') + 7, 8))) 6 .ToList(); 7 8 if (logs.Count > 0) 9 { 10 DelOldLog(_config); 11 logs.ForEach(f => 12 { 13 bind(f,_config.MacName); 14 _config.fileDT = int.Parse(f.Substring(f.LastIndexOf('\\') + 7, 8)); 15 _config.modifyDT = new FileInfo(f).LastWriteTime; 16 }); 17 } 18 }
LogParser處理:
1 static void bind(string logPath,string macName) 2 { 3 LogQuery oLogQuery = new LogQuery();//調用LogPaser日志查詢類庫 4 5 TsvInputFormat oTsvInputFormat = new TsvInputFormat();//聲明日志格式類型 6 LogRecordSet oRecordSet; 7 string query = string.Empty; 8 9 DataTable dt = new DataTable(); 10 #region 所有的條數--Log中包含“reccode=”的行數 11 query = @"select * from '" + logPath + "' where [event-id]='RECEIVE'"; 12 13 oTsvInputFormat.nSkipLines = 4; 14 oTsvInputFormat.iCodepage = 65001; 15 16 oRecordSet = oLogQuery.Execute(query, oTsvInputFormat); 17 for (int i = 0; i < oRecordSet.getColumnCount(); i++) 18 { 19 dt.Columns.Add(oRecordSet.getColumnName(i)); 20 } 21 dt.Columns.Add("MacName"); 22 //取得所有的資料 23 for (; !oRecordSet.atEnd(); oRecordSet.moveNext()) 24 { 25 DataRow dr = dt.NewRow(); 26 for (int i = 0; i < oRecordSet.getColumnCount()-1; i++) 27 { 28 dr[oRecordSet.getColumnName(i)] = oRecordSet.getRecord().getValue(oRecordSet.getColumnName(i)); 29 } 30 dr["MacName"] = macName; 31 dt.Rows.Add(dr); 32 } 33 34 oRecordSet.close(); 35 #endregion 36 37 SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.UseInternalTransaction); 38 sqlbulkcopy.DestinationTableName = "LM_webLog";//數據庫中的表名 39 sqlbulkcopy.WriteToServer(dt); 40 41 Console.WriteLine(dt.Rows.Count + ":" + logPath); 42 43 44 }
Exchange日志格式:
#Software: Microsoft Exchange Server #Version: 14.0.0.0 #Log-type: Message Tracking Log #Date: 2012-12-19T00:02:50.276Z #Fields: date-time,client-ip,client-hostname,server-ip,server-hostname,source-context,connector-id,source,event-id,internal-message-id,message-id,recipient-address,recipient-status,total-bytes,recipient-count,related-recipient-address,reference,message-subject,sender-address,return-path,message-info,directionality,tenant-id,original-client-ip,original-server-ip,custom-data
Exchange的日志格式和標准的csv稍有不同,可看到文件頭部都有一些注釋的文件,在利用LogParser處理時一直沒辦法讀取出正確的列來,然后在研究自帶的幫助文檔時才發現原來它可以指定跳過多少行進行處理。在一切都google的年代越來越少認真的去看自帶的幫助文檔了,這個以后要改掉不能太依賴google了。
oTsvInputFormat.nSkipLines = 4; //跳過前四行進行處理 oTsvInputFormat.iCodepage = 65001;//文件編碼格式
總結:
Logparser在文本類型日志處理時確實足夠強大,基本上能識別任何格式的數據,結合.net一切使用在做數據分析,數據導入時是很強大的工具,並且速度飛快。