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编写网页爬虫脚本并实现APScheduler调度
Jul 28 Python
在Python的Django框架中生成CSV文件的方法
Jul 22 Python
在Windows系统上搭建Nginx+Python+MySQL环境的教程
Dec 25 Python
Python批量查询域名是否被注册过
Jun 21 Python
python中itertools模块zip_longest函数详解
Jun 12 Python
python操作excel的方法
Aug 16 Python
Python学习笔记之变量、自定义函数用法示例
May 28 Python
python中的subprocess.Popen()使用详解
Dec 25 Python
Python实现Wordcloud生成词云图的示例
Mar 30 Python
python抢购软件/插件/脚本附完整源码
Mar 04 Python
如何使用Tkinter进行窗口的管理与设置
Jun 30 Python
python+opencv实现目标跟踪过程
Jun 21 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
使用ThinkPHP自带的Http类下载远程图片到本地的实现代码
2011/08/02 PHP
安装apache2.2.22配置php5.4(具体操作步骤)
2013/06/26 PHP
PHP编程开发怎么提高编程效率 提高PHP编程技术
2015/11/09 PHP
Zend Studio使用技巧两则
2016/04/01 PHP
获取任意Html元素与body之间的偏移距离 offsetTop、offsetLeft (For:IE5+ FF1 )[
2006/12/22 Javascript
javaScript 读取和设置文档元素的样式属性
2009/04/14 Javascript
CSS和Javascript简单复习资料
2010/06/29 Javascript
使用jquery动态加载javascript以减少服务器压力
2012/10/29 Javascript
jquery实现鼠标拖拽滑动效果来选择数字的方法
2015/05/04 Javascript
详解JavaScript逻辑And运算符
2015/12/04 Javascript
关于JavaScript 原型链的一点个人理解
2016/07/31 Javascript
Node.js + Redis Sorted Set实现任务队列
2016/09/19 Javascript
JavaScript中this的用法实例分析
2016/12/19 Javascript
微信小程序实现人脸检测功能
2018/05/25 Javascript
Vue动态控制input的disabled属性的方法
2018/06/26 Javascript
Javascript 实现 Excel 导入生成图表功能
2018/10/22 Javascript
Vue2.0 实现页面缓存和不缓存的方式
2019/11/12 Javascript
vue-cli3.X快速创建项目的方法步骤
2019/11/14 Javascript
vant-ui框架的一个bug(解决切换后onload不触发)
2020/11/11 Javascript
Python将阿拉伯数字转换为罗马数字的方法
2015/07/10 Python
shelve  用来持久化任意的Python对象实例代码
2016/10/12 Python
解决Python的str强转int时遇到的问题
2018/04/09 Python
用python处理图片实现图像中的像素访问
2018/05/04 Python
Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例
2019/01/23 Python
python实现电子产品商店
2019/02/26 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
2020/01/04 Python
Python 防止死锁的方法
2020/07/29 Python
css 元素选择器的简单实例
2016/05/23 HTML / CSS
世界上最受欢迎的钓鱼诱饵:Rapala
2019/05/02 全球购物
澳大利亚Rockwear官网:女子瑜伽、健身和运动服
2021/01/26 全球购物
环境科学专业个人求职的自我评价
2013/11/28 职场文书
产品发布会策划方案
2014/05/12 职场文书
离婚协议书怎么写
2014/09/12 职场文书
宿舍卫生管理制度
2015/08/05 职场文书
教师教育教学随笔
2015/08/15 职场文书
解决thinkphp6(tp6)在状态码500下不报错,或者显示错误“Malformed UTF-8 characters”的问题
2021/04/01 PHP