我一直在撰寫一個日志決議器來從一些日志中獲取一些資訊,然后在其他地方使用它。這個想法是在一系列日志檔案上運行它,并將有用的資訊存盤在資料庫中以備將來使用。我使用的語言是 python(3.8)
從日志中提取的資訊型別是 json 型別的字串,我將其存盤在字典中、普通的字母數字字串、時間戳(我們將其轉換為日期時間物件)、整數和浮點數 - 有時作為字典型別格式的值。
我創建了一個 parse_logs(filepath) 方法,它接受一個檔案路徑并回傳一個包含所有訊息的字典串列。一條訊息可以由上述多種型別組成,為了決議這些日志,我撰寫了許多方法來將訊息從日志行隔離到一個字串串列中,然后操作構成訊息的那些行串列提取各種資訊。
這導致了一個parse_logs(filepath: str) -> list具有多個輔助函式的主函式(例如extract_datetime_from_header(header_line: str) -> datetime ,extract_message(messages: list) -> list并且process_message(message: list) -> dict 每個函式都執行特定的操作,但對我正在處理的專案的任何其他部分都沒有用,因為它們非常特定于輔助此功能。唯一的我想做的另外一件事(至少現在)是獲取這些訊息并將它們的資訊保存在資料庫中。
- 所以,我正在考慮組織我的代碼的兩種主要方式:一種是創建一個 LogParser 類,它將有一個日志路徑和一個訊息串列作為屬性,所有函式作為類方法。(在這種情況下,輔助類的縮進級別應該是多少?它們應該是它們自己的方法還是應該只是在它們應該啟用的方法中定義的函式?)。另一個只是有一個基本函式(并將所有輔助函式嵌套在其中,因為我假設我不希望它們作為獨立函式匯入)并且只使用路徑作為引數運行該方法,它將回傳將訊息串列傳遞給呼叫者函式,該函式將獲取串列,對其進行決議并將每條訊息移動到資料庫中的位置。-我的另一件事 我考慮的是是否對資料使用資料類而不是字典。速度差異并不重要,因為它是一個腳本,每天只運行幾次作為 cronjob,如果它需要 5 秒或 20 秒來運行也沒那么重要(除非差異更大,我'只在半 MB 的日志示例上測驗過它,而不是預期的 4-6 GB)我最后關心的是將訊息物件保留在記憶體中并將它們直接提供給資料庫撰寫器。我已經做了一些測驗和估計,我預計 150MB 似乎是最壞情況下的合理上限(即一個充滿有用資料的日志,比我們目前擁有的最大日志大 40% -所以即使我們擴大到那個數量的三倍,
因此,綜上所述,我想詢問有關如何處理組織代碼的最佳實踐,即:
- 類/oop 方式是否比僅僅撰寫完成作業的函式更好?它更具可讀性/可維護性嗎?
- 我應該使用資料類還是堅持使用字典?兩者的優點/缺點是什么?哪個更易于維護,哪個更高效?
- 如果我關心處理來自資料庫而不是來自這些物件(字典或資料類)的資料,那么哪種方法更有效?
- 在資料庫事務完成之前將訊息物件保留在記憶體中是否可以,或者我應該以不同的方式處理它?我曾想過在完成對單個日志的決議后執行單個事務(但有人告訴我,這可能會導致可伸縮性差,因為訊息的臨時串列會不斷增加記憶體中的內容,直到它們用于資料庫事務 - 單個大事務也可能反過來很慢)或將每條訊息在決議時寫入(作為字典物件)到磁盤中的檔案中,然后決議該中介(是正確的詞? ) 檔案到將處理資料庫事務并分批執行的函式(有人告訴我這也不是一個好習慣),或在決議訊息時直接寫入資料庫(在每條訊息之后或小批量寫入,以便總訊息串列不會變得太大)。我什至考慮過一條生產者/消費者路線,并保留一個共享變數,生產者(日志決議器)將附加到消費者(資料庫寫入者)將使用的共享變數,直到日志被完全決議。但是這條路線不是我以前做過的事情(除了幾次面試問題,這相當簡單,除錯或維護起來很困難,所以我現在沒有那么有信心去做)。關于上述內容的最佳做法是什么?甚至考慮過一條生產者/消費者路線,并保留一個共享變數,生產者(日志決議器)將附加到該變數,而消費者(資料庫寫入者)將消費,直到日志被完全決議。但是這條路線不是我以前做過的事情(除了幾次面試問題,這相當簡單,除錯或維護起來很困難,所以我現在沒有那么有信心去做)。關于上述內容的最佳做法是什么?甚至考慮過一條生產者/消費者路線,并保留一個共享變數,生產者(日志決議器)將附加到該變數,而消費者(資料庫寫入者)將消費,直到日志被完全決議。但是這條路線不是我以前做過的事情(除了幾次面試問題,這相當簡單,除錯或維護起來很困難,所以我現在沒有那么有信心去做)。關于上述內容的最佳做法是什么?
Thank you very much for your time! I know it's a bit of a lot that I've asked, but I did feel like writing down all of the thoughts that I had and read some people's opinions on them. Till then I'm gonna try to do an implementation for all of the above ideas (except perhaps the producer/consumer) and see which feels more maintainable, human readable and intuitively correct to me.
uj5u.com熱心網友回復:
- 類/oop 方式是否比僅僅撰寫完成作業的函式更好?它更具可讀性/可維護性嗎?
我認為不一定有最好的方法。我已經看到以下作業同樣出色:
OOP:您將擁有一個
Parser使用實體變數來共享決議狀態的類。決議器可以是執行緒安全的,也可以不是。閉包:您將使用嵌套函式在輸入和決議狀態上創建閉包。
功能:您將輸入和決議狀態傳遞給回傳決議狀態的函式(例如 AST 更新的游標索引)。
- 我應該使用資料類還是堅持使用字典?兩者的優點/缺點是什么?哪個更易于維護,哪個更高效?
AST 通常以 2 種方式表示(同質與異質):
同構:您將有一個
ASTNode { type, children }類來表示所有節點型別。異構:每種型別都有一個具體的節點類。
您的方法是兩者的混合,因為作為鍵/值存盤,字典對于指向其他節點而不是串列索引可能更具表現力,但所有節點仍然用相同的底層型別表示。我通常喜歡使用自定義類的#2,因為它們可以自我記錄樹的結構,盡管在動態型別的語言中可能沒有多少好處。
至于性能,IDK Python 足夠好,但快速谷歌搜索似乎指出字典總體上是最高性能的。
- 如果我關心處理來自資料庫而不是來自這些物件(字典或資料類)的資料,那么哪種方法更有效?
如果記憶體中的 AST 消費者不感興趣并且您不會有太多的 AST 處理操作,那么我想在 AST 表示上投入大量時間和精力就不太重要了,盡管如果您只有幾種節點使其明確從一開始就不應該付出巨大的努力。
- 在資料庫事務完成之前將訊息物件保留在記憶體中是否可以...
老實說,當您談論運行時和記憶體優化時,這真的取決于。我想說避免陷入過早的優化。這些日志可能有多大?記憶體溢位可能嗎?操作是否如此耗時以至于崩潰并且不得不重新開始是不可接受的?
這些都是可以幫助您確定哪種方法最合適的問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/404786.html
標籤:
