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 相关文章推荐
把MySQL表结构映射为Python中的对象的教程
Apr 07 Python
Python的Django框架中消息通知的计数器实现教程
Jun 13 Python
Python实现中文数字转换为阿拉伯数字的方法示例
May 26 Python
python对视频画框标记后保存的方法
Dec 07 Python
Python matplotlib的使用并自定义colormap的方法
Dec 13 Python
Python3实现的旋转矩阵图像算法示例
Apr 03 Python
Python中一些深不见底的“坑”
Jun 12 Python
numpy数组广播的机制
Jul 12 Python
python实现超市管理系统(后台管理)
Oct 25 Python
python 解决flask uwsgi 获取不到全局变量的问题
Dec 22 Python
安装python依赖包psycopg2来调用postgresql的操作
Jan 01 Python
OpenCV绘制圆端矩形的示例代码
Aug 30 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 MsSql server时遇到的中文编码问题
2009/06/11 PHP
laravel框架与其他框架的详细对比
2019/10/23 PHP
基于jQuery的淡入淡出可自动切换的幻灯插件打包下载
2010/09/15 Javascript
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
2010/11/11 Javascript
jQuery中使用data()方法读取HTML5自定义属性data-*实例
2014/04/11 Javascript
使用原生js实现页面蒙灰(mask)效果示例代码
2014/06/20 Javascript
JavaScript中的anchor()方法使用详解
2015/06/08 Javascript
JavaScript检测上传文件大小的方法
2015/07/22 Javascript
jQuery侧边栏实现代码
2016/05/06 Javascript
JS简单实现点击复制链接的方法
2016/08/03 Javascript
JS实现的表头列头固定页面功能示例
2017/01/10 Javascript
AngularJS实现的2048小游戏功能【附源码下载】
2018/01/03 Javascript
基于JavaScript实现抽奖系统
2018/01/16 Javascript
jQuery zTree树插件的使用教程
2019/08/16 jQuery
微信小程序 简易计算器实现代码实例
2019/09/02 Javascript
解决webpack多页面内存溢出的方法示例
2019/10/08 Javascript
你可能从未使用过的11+个JavaScript特性(小结)
2020/01/08 Javascript
[03:18]DOTA2亚洲邀请赛小组赛第一日 RECAP赛事回顾
2015/01/30 DOTA
python脚本实现查找webshell的方法
2014/07/31 Python
python通过加号运算符操作列表的方法
2015/07/28 Python
Python的时间模块datetime详解
2017/04/17 Python
对Python强大的可变参数传递机制详解
2019/06/13 Python
python从list列表中选出一个数和其对应的坐标方法
2019/07/20 Python
python获取指定日期范围内的每一天,每个月,每季度的方法
2019/08/08 Python
结合OpenCV与TensorFlow进行人脸识别的实现
2019/10/10 Python
Python动态导入模块和反射机制详解
2020/02/18 Python
皇马官方商城:Real Madrid Store
2016/09/02 全球购物
碧欧泉Biotherm加拿大官方网站:法国高端护肤品牌
2019/10/18 全球购物
Araks官网:纽约内衣品牌
2020/10/15 全球购物
西安启天科技有限公司网络工程师面试题笔试题
2016/06/12 面试题
拖鞋店创业计划书
2014/01/15 职场文书
运动会跳远加油稿
2014/02/20 职场文书
初中学校军训方案
2014/05/09 职场文书
销售求职信范文
2014/05/26 职场文书
总经理岗位职责
2015/02/04 职场文书
公司周年庆典致辞
2015/07/30 职场文书