Python实现日志实时监测的示例详解


Posted in Python onApril 06, 2022

介绍

观察者模式:是一种行为型设计模式。主要关注的是对象的责任,允许你定义一种订阅机制,可在对象事件发生时通知多个"观察"该对象的其他对象。用来处理对象之间彼此交互。

观察者模式也叫发布-订阅模式,定义了对象之间一对多依赖,当一个对象改变状态时,这个对象的所有依赖者都会收到通知并按照自己的方式进行更新。

观察者设计模式是最简单的行为模式之一。在观察者设计模式中,对象维护了一个依赖(观察者)列表,以便主题可以使用观察者定义的任何方法通知所有观察者它所发生的变化。

可使用观察者模式应用场景

在广播或者发布订阅系统的情形中,你会看到观察者设计模式的用法,它的主要使用场景如下:

1、分布式系统中实现事件服务。

2、广播或发布/阅系统情形中。

2、用作新闻机器的框架。

3、股票监测机器人。

观察者模式类图

Python实现日志实时监测的示例详解

观察者模式类图

1、发布者Publisher:向其他对象发送值得关注的事件。事件会在发布者自身状态改变或执行特定行为后发生。发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅机制。

2、订阅者Subscriber:定义通知接口。一般情况下,该接口仅包含一个update()更新方法。方法中可以有多个参数,使发布者能在更新时传递事件详细信息。

3、客户端Client:分别创建发布者和订阅者对象,然后为订阅者注册,发布者更新。

观察者模式示例

假如我们对应用函数运行状态进行监测,当发生异常时报警记录,可通过观察者模式进行信息订阅:1、短信 2、日志 3、邮件

代码实现---subscription_model.py

1、创建订阅者类

Subscriber订阅者:所有希望关注发布者状态变化的其他对象。

这里提供了三个主要的订阅者(观察者)接口,跟踪着同一个发布者类的事件。主要包括:

1)、每个具体订阅者__init()方法使用attach()方法向发布者进行注册以获取信息更新。

2)、具体订阅者的update()更新消息。

#抽象订阅者
from abc import ABCMeta,abstractmethod
class Subscriber(metaclass=ABCMeta):
    #向具体订阅者发送消息的方法
    @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()
        # 发送邮件
        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、创建发布者类

Publisher发布者:将自身的状态改变通知其他对象,为发布者添加订阅机制,每个对象都能订阅或取消订阅者事件流。

主要包括:

1)self.__subscribers = []:一个用于存储订阅对象列表

2)供订阅者来注册NewsPublisher或删除订阅用户。

3)几个用于添加、删除或查看列表中订阅者的公有方法。

4)notifySubscribers(self):用于通知所有订阅者出现新的信息,发送者会遍历订阅列表并通过内部调用具体订阅者实现的update()方法来实现。

5)创建新消息和返回最新消息。

#创建发布者
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]

    #发送通知给相关的主题订阅者
    def notifySubscribers(self):
        for sub in self.__subscribers:
            #update()方法由具体的观察者或订阅者实现的
            sub.update()  #推送更新
    
    #创建新消息
    def addNews(self,news):
        self.__latestNews = news
    
    #返回最新消息,并通知观察者
    def getNews(self):
        return "Got News:",self.__latestNews

3、应用客户端-Map_server_client.py

订阅者通常需要一些上下文信息正确处理更新。因此,发布者通常会将一些上下文数据作为通知方法的参数传递。

这里给第一篇文章留下的尾巴补充一下,客户端实例化get_Map_model方法添加带参数装饰器,@fail_data(msg='地图加载失败')添加接口调用失败处理机制,追加日志记录。这里可以进一步将更多细节参数添加到日志中,装饰器传参并在接口中声明通知方法及参数,这样发布者在发出通知时传递一些上下文数据。

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("这个函数正常执行:%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:', '地图加载失败!')

以上就是实现了一个简单的发布订阅模式,发布者与订阅者之间是松耦合的,添加新订阅者无需修改发布者。所有具体订阅者类都实现了同样接口。

到此这篇关于Python实现日志实时监测的示例详解的文章就介绍到这了,更多相关Python日志监测内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python海龟绘图实例教程
Jul 24 Python
利用Python和OpenCV库将URL转换为OpenCV格式的方法
Mar 27 Python
python3 cvs将数据读取为字典的方法
Dec 22 Python
Python不同目录间进行模块调用的实现方法
Jan 29 Python
对python dataframe逻辑取值的方法详解
Jan 30 Python
pyqt远程批量执行Linux命令程序的方法
Feb 14 Python
python学生管理系统学习笔记
Mar 19 Python
Python实现不规则图形填充的思路
Feb 02 Python
基于pygame实现童年掌机打砖块游戏
Feb 25 Python
解决python DataFrame 打印结果不换行问题
Apr 09 Python
Python3利用openpyxl读写Excel文件的方法实例
Feb 03 Python
Python 如何实现文件自动去重
Jun 02 Python
Python使用PyYAML库读写yaml文件的方法
Apr 06 #Python
python+pytest接口自动化之token关联登录的实现
Python图像处理库PIL详细使用说明
Apr 06 #Python
Python可变与不可变数据和深拷贝与浅拷贝
Apr 06 #Python
Python 全局空间和局部空间
Apr 06 #Python
Selenium浏览器自动化如何上传文件
Apr 06 #Python
在Python 中将类对象序列化为JSON
Apr 06 #Python
You might like
PHP文件读写操作之文件写入代码
2011/01/13 PHP
ThinkPHP后台首页index使用frameset时的注意事项分析
2014/08/22 PHP
windows下apache搭建php开发环境
2015/08/27 PHP
PHP实现分布式memcache设置web集群session同步的方法
2018/04/10 PHP
PHP whois查询类定义与用法示例
2019/04/03 PHP
优秀js开源框架-jQuery使用手册(1)
2007/03/10 Javascript
表单验证的完整应用案例探讨
2013/03/29 Javascript
jQuery带进度条全屏图片轮播特效代码分享
2020/06/28 Javascript
js电话号码验证方法
2015/09/28 Javascript
jQuery实现带有动画效果的回到顶部和底部代码
2015/11/04 Javascript
实例讲解javascript注册事件处理函数
2016/01/09 Javascript
基于BootStrap实现局部刷新分页实例代码
2016/08/08 Javascript
微信小程序 开发工具快捷键整理
2016/10/31 Javascript
jQuery、layer实现弹出层的打开、关闭功能
2017/06/28 jQuery
JS中Swiper的使用和轮播图效果
2017/08/11 Javascript
JS简单实现点击跳转登陆邮箱功能的方法
2017/10/31 Javascript
微信小程序上传图片到服务器实例代码
2017/11/07 Javascript
JavaScript实现修改伪类样式
2017/11/27 Javascript
关于Google发布的JavaScript代码规范你要知道哪些
2018/04/04 Javascript
使用vue.js在页面内组件监听scroll事件的方法
2018/09/11 Javascript
JavaScript实现简单音乐播放器
2020/04/17 Javascript
JS/jQuery实现简单的开关灯效果【案例】
2019/02/19 jQuery
node express使用HTML模板的方法示例
2019/08/22 Javascript
[40:10]2015国际邀请赛全明星表演赛
2015/08/07 DOTA
python 实现文件的递归拷贝实现代码
2012/08/02 Python
Python2.7实现多进程下开发多线程示例
2019/05/31 Python
python 读取更新中的log 或其它文本方式
2019/12/24 Python
python 线性回归分析模型检验标准--拟合优度详解
2020/02/24 Python
Python pytesseract验证码识别库用法解析
2020/06/29 Python
米兰网婚纱礼服法国网上商店:Milanoo法国
2016/08/20 全球购物
旧时光糖果:Old Time Candy
2018/02/05 全球购物
日本索尼音乐商店:Sony Music Shop
2018/07/17 全球购物
2015年小学教师培训工作总结
2015/07/21 职场文书
优秀共产党员主要事迹材料
2015/11/05 职场文书
学生会2016感恩节活动小结
2016/04/01 职场文书
如何让vue长列表快速加载
2021/03/29 Vue.js