Python實現(xiàn)日志實時監(jiān)測的示例詳解
介紹
觀察者模式:是一種行為型設計模式。主要關注的是對象的責任,允許你定義一種訂閱機制,可在對象事件發(fā)生時通知多個"觀察"該對象的其他對象。用來處理對象之間彼此交互。
觀察者模式也叫發(fā)布-訂閱模式,定義了對象之間一對多依賴,當一個對象改變狀態(tài)時,這個對象的所有依賴者都會收到通知并按照自己的方式進行更新。
觀察者設計模式是最簡單的行為模式之一。在觀察者設計模式中,對象維護了一個依賴(觀察者)列表,以便主題可以使用觀察者定義的任何方法通知所有觀察者它所發(fā)生的變化。
可使用觀察者模式應用場景
在廣播或者發(fā)布訂閱系統(tǒng)的情形中,你會看到觀察者設計模式的用法,它的主要使用場景如下:
1、分布式系統(tǒng)中實現(xiàn)事件服務。
2、廣播或發(fā)布/閱系統(tǒng)情形中。
2、用作新聞機器的框架。
3、股票監(jiān)測機器人。
觀察者模式類圖
觀察者模式類圖
1、發(fā)布者Publisher:向其他對象發(fā)送值得關注的事件。事件會在發(fā)布者自身狀態(tài)改變或執(zhí)行特定行為后發(fā)生。發(fā)布者中包含一個允許新訂閱者加入和當前訂閱者離開列表的訂閱機制。
2、訂閱者Subscriber:定義通知接口。一般情況下,該接口僅包含一個update()更新方法。方法中可以有多個參數(shù),使發(fā)布者能在更新時傳遞事件詳細信息。
3、客戶端Client:分別創(chuàng)建發(fā)布者和訂閱者對象,然后為訂閱者注冊,發(fā)布者更新。
觀察者模式示例
假如我們對應用函數(shù)運行狀態(tài)進行監(jiān)測,當發(fā)生異常時報警記錄,可通過觀察者模式進行信息訂閱:1、短信 2、日志 3、郵件
代碼實現(xiàn)---subscription_model.py
1、創(chuàng)建訂閱者類
Subscriber訂閱者:所有希望關注發(fā)布者狀態(tài)變化的其他對象。
這里提供了三個主要的訂閱者(觀察者)接口,跟蹤著同一個發(fā)布者類的事件。主要包括:
1)、每個具體訂閱者__init()方法使用attach()方法向發(fā)布者進行注冊以獲取信息更新。
2)、具體訂閱者的update()更新消息。
#抽象訂閱者 from?abc?import?ABCMeta,abstractmethod class?Subscriber(metaclass=ABCMeta): ????#向具體訂閱者發(fā)送消息的方法 ????@abstractmethod ????def?update(self): ????????pass #具體訂閱者 #1、短信訂閱者 class?SMSSubscriber(Subscriber): ????def?__init__(self,publisher): ????????self.publisher?=?publisher ????????self.publisher.attach(self) ????def?update(self): ????????print(type(self).__name__,self.publisher.getNews()) #2、郵件訂閱者 class?EmailSubscriber(Subscriber): ????def?__init__(self,?publisher): ????????self.publisher?=?publisher ????????self.publisher.attach(self) ????def?update(self): ????????print(type(self).__name__,self.publisher.getNews()) ????????info?=?self.publisher.getNews() ????????#?發(fā)送郵件 ????????Sender_mail(info).sender_mail() #3、日志訂閱(文件存儲) class?LoggerSubscriber(Subscriber): ????def?__init__(self,?publisher): ????????log_dir?=?os.path.expanduser(r".\apps\Mapview\logs") ????????log_file?=?os.path.join(log_dir,?"file_{time}.log") ????????logger.add(log_file,?rotation="100KB",?retention=2) ????????self.publisher?=?publisher ????????self.publisher.attach(self) ????def?update(self): ????????print(type(self).__name__,self.publisher.getNews()) ????????info=self.publisher.getNews() ????????logger.info(f"{info}")
2、創(chuàng)建發(fā)布者類
Publisher發(fā)布者:將自身的狀態(tài)改變通知其他對象,為發(fā)布者添加訂閱機制,每個對象都能訂閱或取消訂閱者事件流。
主要包括:
1)self.__subscribers = []:一個用于存儲訂閱對象列表
2)供訂閱者來注冊NewsPublisher或刪除訂閱用戶。
3)幾個用于添加、刪除或查看列表中訂閱者的公有方法。
4)notifySubscribers(self):用于通知所有訂閱者出現(xiàn)新的信息,發(fā)送者會遍歷訂閱列表并通過內部調用具體訂閱者實現(xiàn)的update()方法來實現(xiàn)。
5)創(chuàng)建新消息和返回最新消息。
#創(chuàng)建發(fā)布者 class?NewsPublisher: ????def?__init__(self): ????????self.__subscribers?=?[] ????????self.__latestNews?=?None ???? ????#將訂閱者添加到隊列中 ????def?attach(self,subscriber): ????????self.__subscribers.append(subscriber) ???? ????#從訂閱的主題里面移除 ????def?detach(self): ????????return?self.__subscribers.pop() ????#生成觀察者列表 ????def?subscribers(self): ????????return?[type(x).__name__?for?x?in?self.__subscribers] ????#發(fā)送通知給相關的主題訂閱者 ????def?notifySubscribers(self): ????????for?sub?in?self.__subscribers: ????????????#update()方法由具體的觀察者或訂閱者實現(xiàn)的 ????????????sub.update()??#推送更新 ???? ????#創(chuàng)建新消息 ????def?addNews(self,news): ????????self.__latestNews?=?news ???? ????#返回最新消息,并通知觀察者 ????def?getNews(self): ????????return?"Got?News:",self.__latestNews
3、應用客戶端-Map_server_client.py
訂閱者通常需要一些上下文信息正確處理更新。因此,發(fā)布者通常會將一些上下文數(shù)據(jù)作為通知方法的參數(shù)傳遞。
這里給第一篇文章留下的尾巴補充一下,客戶端實例化get_Map_model方法添加帶參數(shù)裝飾器,@fail_data(msg='地圖加載失敗')添加接口調用失敗處理機制,追加日志記錄。這里可以進一步將更多細節(jié)參數(shù)添加到日志中,裝飾器傳參并在接口中聲明通知方法及參數(shù),這樣發(fā)布者在發(fā)出通知時傳遞一些上下文數(shù)據(jù)。
from?apps.tools.subscription_model?import?NewsPublisher,LoggerSubscriber,EmailSubscriber import?functools #如果加載失敗,調用訂閱者 def?publisher(info): ????news_publisher?=?NewsPublisher() ????#?for?Subscribers?in?[EmailSubscriber,?LoggerSubscriber]: ????for?Subscribers?in?[LoggerSubscriber]: ????????#?eval(LoggerSubscriber)(news_publisher) ????????Subscribers(news_publisher) ????????print("\nSubscribers",?news_publisher.subscribers()) ????????news_publisher.addNews(f"{info}") ????????news_publisher.notifySubscribers() #處理異常的裝飾器 def?fail_data(msg='地圖加載失敗'): ????def?catch_exception(origin_func): ????????@functools.wraps(origin_func) ????????def?wrapper(*args,?**kwargs): ????????????try: ????????????????u?=?origin_func(*args,?**kwargs) ????????????????print("這個函數(shù)正常執(zhí)行:%s"?%?origin_func.__name__) ????????????????return?u ????????????except?Exception?as?e: ????????????????info?=?f"{msg}:{e.__doc__}" ????????????????""" ????????????????接口調用失敗處理機制,追加日志 ????????????????""" ????????????????print(info) ????????????????publisher(info) ????????????????#?news_publisher?=?NewsPublisher() ????????????????#?LoggerSubscriber(news_publisher) ????????????????#?print("\nSubscribers",?news_publisher.subscribers()) ????????????????#?news_publisher.addNews(f"{info}") ????????????????#?news_publisher.notifySubscribers() ????????return?wrapper ????return?catch_exception
4、測試
if?__name__?==?'__main__': ????from?loguru?import?logger ????from?apps.tools.Sender_Email?import?Sender_mail ????news_publisher?=NewsPublisher() ????for?Subscribers?in?[LoggerSubscriber]: ????????print(Subscribers) ????????Subscribers(news_publisher) ????print("\nSubscribers",news_publisher.subscribers()) ????news_publisher.addNews("地圖加載失??!") ????news_publisher.notifySubscribers()
結果
class '__main__.LoggerSubscriber';
Subscribers ['LoggerSubscriber']
LoggerSubscriber ('Got News:', '地圖加載失敗!')
2022-04-05 16:38:00.667 | INFO | __main__:update:81 - ('Got News:', '地圖加載失?。?#39;)
以上就是實現(xiàn)了一個簡單的發(fā)布訂閱模式,發(fā)布者與訂閱者之間是松耦合的,添加新訂閱者無需修改發(fā)布者。所有具體訂閱者類都實現(xiàn)了同樣接口。
到此這篇關于Python實現(xiàn)日志實時監(jiān)測的示例詳解的文章就介紹到這了,更多相關Python日志監(jiān)測內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python實現(xiàn)QQ郵箱/163郵箱的郵件發(fā)送
這篇文章主要為大家詳細介紹了Python實現(xiàn)QQ郵箱和163郵箱的郵件發(fā)送,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS淺析
這篇文章主要給大家介紹了關于Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧2018-05-05