Python實(shí)現(xiàn)日志實(shí)時(shí)監(jiān)測(cè)的示例詳解
介紹
觀察者模式:是一種行為型設(shè)計(jì)模式。主要關(guān)注的是對(duì)象的責(zé)任,允許你定義一種訂閱機(jī)制,可在對(duì)象事件發(fā)生時(shí)通知多個(gè)"觀察"該對(duì)象的其他對(duì)象。用來處理對(duì)象之間彼此交互。
觀察者模式也叫發(fā)布-訂閱模式,定義了對(duì)象之間一對(duì)多依賴,當(dāng)一個(gè)對(duì)象改變狀態(tài)時(shí),這個(gè)對(duì)象的所有依賴者都會(huì)收到通知并按照自己的方式進(jìn)行更新。
觀察者設(shè)計(jì)模式是最簡(jiǎn)單的行為模式之一。在觀察者設(shè)計(jì)模式中,對(duì)象維護(hù)了一個(gè)依賴(觀察者)列表,以便主題可以使用觀察者定義的任何方法通知所有觀察者它所發(fā)生的變化。
可使用觀察者模式應(yīng)用場(chǎng)景
在廣播或者發(fā)布訂閱系統(tǒng)的情形中,你會(huì)看到觀察者設(shè)計(jì)模式的用法,它的主要使用場(chǎng)景如下:
1、分布式系統(tǒng)中實(shí)現(xiàn)事件服務(wù)。
2、廣播或發(fā)布/閱系統(tǒng)情形中。
2、用作新聞機(jī)器的框架。
3、股票監(jiān)測(cè)機(jī)器人。
觀察者模式類圖
觀察者模式類圖
1、發(fā)布者Publisher:向其他對(duì)象發(fā)送值得關(guān)注的事件。事件會(huì)在發(fā)布者自身狀態(tài)改變或執(zhí)行特定行為后發(fā)生。發(fā)布者中包含一個(gè)允許新訂閱者加入和當(dāng)前訂閱者離開列表的訂閱機(jī)制。
2、訂閱者Subscriber:定義通知接口。一般情況下,該接口僅包含一個(gè)update()更新方法。方法中可以有多個(gè)參數(shù),使發(fā)布者能在更新時(shí)傳遞事件詳細(xì)信息。
3、客戶端Client:分別創(chuàng)建發(fā)布者和訂閱者對(duì)象,然后為訂閱者注冊(cè),發(fā)布者更新。
觀察者模式示例
假如我們對(duì)應(yīng)用函數(shù)運(yùn)行狀態(tài)進(jìn)行監(jiān)測(cè),當(dāng)發(fā)生異常時(shí)報(bào)警記錄,可通過觀察者模式進(jìn)行信息訂閱:1、短信 2、日志 3、郵件
代碼實(shí)現(xiàn)---subscription_model.py
1、創(chuàng)建訂閱者類
Subscriber訂閱者:所有希望關(guān)注發(fā)布者狀態(tài)變化的其他對(duì)象。
這里提供了三個(gè)主要的訂閱者(觀察者)接口,跟蹤著同一個(gè)發(fā)布者類的事件。主要包括:
1)、每個(gè)具體訂閱者_(dá)_init()方法使用attach()方法向發(fā)布者進(jìn)行注冊(cè)以獲取信息更新。
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、日志訂閱(文件存儲(chǔ)) 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)改變通知其他對(duì)象,為發(fā)布者添加訂閱機(jī)制,每個(gè)對(duì)象都能訂閱或取消訂閱者事件流。
主要包括:
1)self.__subscribers = []:一個(gè)用于存儲(chǔ)訂閱對(duì)象列表
2)供訂閱者來注冊(cè)NewsPublisher或刪除訂閱用戶。
3)幾個(gè)用于添加、刪除或查看列表中訂閱者的公有方法。
4)notifySubscribers(self):用于通知所有訂閱者出現(xiàn)新的信息,發(fā)送者會(huì)遍歷訂閱列表并通過內(nèi)部調(diào)用具體訂閱者實(shí)現(xiàn)的update()方法來實(shí)現(xiàn)。
5)創(chuàng)建新消息和返回最新消息。
#創(chuàng)建發(fā)布者 class?NewsPublisher: ????def?__init__(self): ????????self.__subscribers?=?[] ????????self.__latestNews?=?None ???? ????#將訂閱者添加到隊(duì)列中 ????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ā)送通知給相關(guān)的主題訂閱者 ????def?notifySubscribers(self): ????????for?sub?in?self.__subscribers: ????????????#update()方法由具體的觀察者或訂閱者實(shí)現(xiàn)的 ????????????sub.update()??#推送更新 ???? ????#創(chuàng)建新消息 ????def?addNews(self,news): ????????self.__latestNews?=?news ???? ????#返回最新消息,并通知觀察者 ????def?getNews(self): ????????return?"Got?News:",self.__latestNews
3、應(yīng)用客戶端-Map_server_client.py
訂閱者通常需要一些上下文信息正確處理更新。因此,發(fā)布者通常會(huì)將一些上下文數(shù)據(jù)作為通知方法的參數(shù)傳遞。
這里給第一篇文章留下的尾巴補(bǔ)充一下,客戶端實(shí)例化get_Map_model方法添加帶參數(shù)裝飾器,@fail_data(msg='地圖加載失敗')添加接口調(diào)用失敗處理機(jī)制,追加日志記錄。這里可以進(jìn)一步將更多細(xì)節(jié)參數(shù)添加到日志中,裝飾器傳參并在接口中聲明通知方法及參數(shù),這樣發(fā)布者在發(fā)出通知時(shí)傳遞一些上下文數(shù)據(jù)。
from?apps.tools.subscription_model?import?NewsPublisher,LoggerSubscriber,EmailSubscriber import?functools #如果加載失敗,調(diào)用訂閱者 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("這個(gè)函數(shù)正常執(zhí)行:%s"?%?origin_func.__name__) ????????????????return?u ????????????except?Exception?as?e: ????????????????info?=?f"{msg}:{e.__doc__}" ????????????????""" ????????????????接口調(diào)用失敗處理機(jī)制,追加日志 ????????????????""" ????????????????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、測(cè)試
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()
結(jié)果
class '__main__.LoggerSubscriber';
Subscribers ['LoggerSubscriber']
LoggerSubscriber ('Got News:', '地圖加載失??!')
2022-04-05 16:38:00.667 | INFO | __main__:update:81 - ('Got News:', '地圖加載失?。?#39;)
以上就是實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的發(fā)布訂閱模式,發(fā)布者與訂閱者之間是松耦合的,添加新訂閱者無需修改發(fā)布者。所有具體訂閱者類都實(shí)現(xiàn)了同樣接口。
到此這篇關(guān)于Python實(shí)現(xiàn)日志實(shí)時(shí)監(jiān)測(cè)的示例詳解的文章就介紹到這了,更多相關(guān)Python日志監(jiān)測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)清除文件夾中重復(fù)視頻
本文將利用Python中的os、hashlib、shutil模塊實(shí)現(xiàn)對(duì)文件夾中的重復(fù)視頻進(jìn)行清除,實(shí)現(xiàn)文件夾中無重復(fù)文件情況發(fā)生,需要的可以參考一下2022-05-05python實(shí)現(xiàn)QQ郵箱/163郵箱的郵件發(fā)送
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)QQ郵箱和163郵箱的郵件發(fā)送,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Python拋出引發(fā)異常(raise)知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了關(guān)于Python拋出引發(fā)異常(raise)知識(shí)點(diǎn)總結(jié)內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。2021-06-06Python遞歸及尾遞歸優(yōu)化操作實(shí)例分析
這篇文章主要介紹了Python遞歸及尾遞歸優(yōu)化操作,結(jié)合實(shí)例形式分析了Python遞歸及尾遞歸優(yōu)化相關(guān)概念、原理、應(yīng)用與操作技巧,需要的朋友可以參考下2020-02-02Pandas之read_csv()讀取文件跳過報(bào)錯(cuò)行的解決
這篇文章主要介紹了Pandas之read_csv()讀取文件跳過報(bào)錯(cuò)行的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS淺析
這篇文章主要給大家介紹了關(guān)于Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧2018-05-05