CWKSC's 翻譯文章

CIS 194 02 Homework

Featured image

Source: CIS 194: Homework 2

發生了嚴重錯誤!

▌Log file parsing 日誌文件解析

我們確實不確定發生了什麼,但我們確實設法恢復了日誌文件 error.log 。 它似乎在每一行上都包含一個不同的日誌消息。 每行以一個字符開頭,指示其表示的日誌消息的類型:

錯誤消息行中的整數將指示錯誤的嚴重性, 1 是您可能在明年夏天某個時候遇到的那種錯誤,而 100 是史詩般的災難性故障。 然後,所有類型的日誌消息都有一個整數時間戳,其後是文本內容,該文本內容一直行到行尾。 這是日誌文件的片段,包括信息和 2 級錯誤消息:

I 147 mice in the air, Im afraid, but you might catch a bat, and
E 2 148 #56k istereadeat lo d200ff] BOOTMEM

一切都很混亂。顯然,我們需要一個程序來解決這一混亂局面。 我們提出了一些數據類型來捕獲此日誌文件格式的結構:

data MessageType = Info
                 | Warning
                 | Error Int
                 deriving (Show, Eq)
                 
type TimeStamp = Int

data LogMessage = LogMessage MessageType TimeStamp String
                | Unknown String
                deriving (Show, Eq)

請注意,LogMessage 具有兩個構造函數:一個用於表示標準格式的日誌消息,另一個用於表示任何其他不適合正確格式的消息

我們為您提供了一個 Log.hs 模塊,其中包含這些數據類型聲明以及其他一些有用的功能。 下載 Log.hs,並將其放在要放置作業的同一文件夾中。 請命名您的作業作業 LogAnalysis.hs (如果要使其成為 literate Haskell 文檔,則命名為.lhs)。 LogAnalysis.hs 的前幾行應如下所示:

{-# OPTIONS_GHC -Wall #-}
module LogAnalysis where

import Log

它將文件設置為名為 LogAnalysis 的模塊,並從 Log.hs 導入該模塊,以便您可以使用其提供的類型和功能

▌練習 1

第一步是弄清楚如何解析單個消息。 定義函數

parseMessage :: String -> LogMessage

它從日誌文件中分析一行。 例如

parseMessage "E 2 562 help help"
    == LogMessage (Error 2) 562 "help help"

parseMessage "I 29 la la la"
    == LogMessage Info 29 "la la la"
    
parseMessage "This is not in the right format"
    == Unknown "This is not in the right format"

一旦我們可以解析一條日誌消息,就可以解析整個日誌文件。 定義函數

parse :: String -> [LogMessage]

它立即解析整個日誌文件,並以 LogMessages 列表的形式返回其內容

要測試您的函數,請使用 Log 模塊中提供的 testParse 函數,將其作為參數提供您的 parse 函數,要解析的行數以及要從中解析的日誌文件(該文件也應與您的分配位於同一文件夾中) 。 例如,將您的作業加載到 GHCi 中後,在提示符下鍵入以下內容:

testParse parse 10 "error.log"

不要重新發明輪子! (上周是這樣。)使用 Prelude 函數可以使您的解決方案盡可能簡潔,高級和實用。 例如,要將 "562" 之類的字符串轉換為 Int,可以使用 read 函數。 其他對您可能有用(或可能不有用)的功能包括 line, word, unwords, take, drop and (.)

▌將日誌按順序排列 / 整理日誌

不幸的是,由於錯誤消息是由遍布全球的多個位置的多台服務器生成的,包括雷電風暴,磁盤故障以及無聊而又無能的程序員,因此日誌消息嚴重混亂。 在我們進行一些整理之前,將無法弄清出什麼問題了! 我們設計了一種應該有用的數據結構 —— LogMessages 的二進制搜索樹:

data MessageTree = Leaf
                 | Node MessageTree LogMessage MessageTree

請注意,MessageTree 是一種遞歸數據類型: Node 構造函數本身以兩個子代作為參數,分別代表左右子樹以及一個 LogMessage 。 在此,Leaf 代表空樹

MessageTree 應該按時間戳排序:即,任何 NodeLogMessage 的時間戳都應大於左子樹中任何 LogMessage 的所有時間戳,而小於右子節點中任何 LogMessage 的所有時間戳

未知消息不應存儲在 MessageTree 中,因為它們沒有時間戳記

▌練習 2

定義函數

insert :: LogMessage -> MessageTree -> MessageTree

它將新的 LogMessage 插入現有的 MessageTree 中,從而產生一個新的 MessageTreeinsert 可以假定已給它排序的 MessageTree ,並且除了原始 MessageTree 的內容之外,還必須產生一個包含新 LogMessage 的新排序的 MessageTree

但是,請注意,如果為 insert 提供了一個 UnknownLogMessage ,則它應返回 MessageTree 不變

▌練習 3

一旦我們可以將單個 LogMessage 插入到 MessageTree 中,就可以從消息列表中構建完整的 MessageTree。 具體來說,定義一個函數

build :: [LogMessage] -> MessageTree

通過依次將消息插入到 MessageTree(從 Leaf 開頭)中,構建了一個包含列表中消息的 MessageTree

▌練習 4

最後,定義函數

inOrder :: MessageTree -> [LogMessage]

它接受一個已排序的 MessageTree 並生成其包含的所有 LogMessage 的列表,並按時間戳從最小到最大的順序進行排序。 (這被稱為 MessageTree 的有序遍歷。)

有了這些功能,我們現在可以刪除未知消息,並使用以下表達式對格式正確的消息進行排序:

inOrder (build tree)

【注意:有更好的方式對列表進行排序; 這只是讓您使用遞歸數據結構的一種練習!】

▌日誌文件驗屍

▌練習 5

現在我們可以對日誌消息進行排序,剩下要做的就是提取相關信息。 我們認為“相關”是指“嚴重程度至少為 50 的錯誤”。

寫一個函數

whatWentWrong :: [LogMessage] -> [String]

它採用 LogMessages 的未排序列表,並返回與嚴重性為 50 或更高的任何錯誤相對應的消息列表,並按時間戳排序。 (當然,您可以使用前面練習中的函數來進行排序。)

例如,假設我們的日誌文件如下所示:

I 6 Completed armadillo processing
I 1 Nothing to report
E 99 10 Flange failed!
I 4 Everything normal
I 11 Initiating self-destruct sequence
E 70 3 Way too many pickles
E 65 8 Bad pickle-flange interaction detected
W 5 Flange is due for a check-up
I 7 Out for lunch, back in two time steps
E 20 2 Too many pickles
I 9 Back from lunch

該文件作為 sample.log 提供。 有四個錯誤,其中三個嚴重程度大於 50。 sample.logwhatWentWrong 的輸出應為

[ "Way too many pickles"
, "Bad pickle-flange interaction detected"
, "Flange failed!"
]

您可以使用 log 模塊提供的 testWhatWentWrong 測試 whatWentWrong 函數。 您應該為您的解析函數,您的 whatWentWrong 函數以及要解析的日誌文件的名稱提供 testWhatWentWrong

▌Miscellaneous 雜項

▌Epilogue 結語 / 尾聲

▌練習6(可選)

由於各種原因,我們開始懷疑最近的混亂是由一個自私的黑客造成的。 你能弄清楚是誰做的嗎?

CWKSC

Author 作者

CWKSC

喜歡編程,會一點點鋼琴,會一點點畫畫,喜歡使用顏文字 About me 關於我

For any comments or discussions on my blog post, you can open an issue here

對於我博客文章的任何評論或討論,可以在這裏開一個 issue

Feel free to give your comments. OW<