其他分享
首页 > 其他分享> > 用信息抓取实现周报的自动生成

用信息抓取实现周报的自动生成

作者:互联网

用信息抓取实现周报的自动生成

在【信息抓取】一文中我们展示了jxTMS可以自动生成周报,本文讲述一下其实现机制。

在jxTMS中,信息抓取机制总共有四个组成单元:

其中,支持信息抓取的日志记录已经被整合到jxTMS日志记录接口中,用户在自己的处理现场直接调用即可,本文就不复赘述了。

日志中的信息

信息抓取的基础是系统执行过程中在关键点所记录下的用户操作日志。这个操作日志记录的是:什么时间针对什么事情谁干了什么。即,该日志记录了5类重要信息【4W1A】:

定义一个统计分析

根据jxTMS所提供的信息抓取机制,用户可自定义一个接到信息流水中的抓取自己感兴趣的日志进行分析处理的功能,jxTMS的术语叫做一个stat。

一个stat包括两个部分:

我们先看下任务管理中是如何用信息抓取来生成的动态与周报等信息的:

#对任务进行信息抓取与统计
@myModule.stat('任务统计分析'.decode('utf-8'))
def stat():
    '''
    //捕获器定义:所有针对what是task类型的stat型日志
    match 任务.动态 'what.type==task and do.purpose==logStat'
    
    //任务动态实时通知转发给what的创建者和事的管理责任人
    dual 动态 creator,taskOwner

    //按人生成日报、周报、月报,并转发给执行人以及该员的上级
    dual 工作报告 stat per day,week,month to caller,owner

    //按事生成周报,并转发给事的管理责任人
    dual 任务跟踪 stat per week to taskOwner

    '''
    pass

上述代码定义了一个名为【任务统计分析】的stat,带有一个捕获器和三个处理器以及相应的分发器,我们做个简单的讲解。

首先定义了捕获器:

match 任务.动态 'what.type==task and do.purpose==logStat'

即对数据对象的类型是task而执行动作的目的是用于logStat的日志进行捕获。该日志是用户调用stat语句所记录的,如创建一个子任务时:

self.stat(db,ctx,st,pt,'创建子任务'.decode('utf-8'),'吧啦吧啦吧啦')

就此捕获器,所有用stat语句对what是task类型记录的日志都会被捕获到。

捕获后,会将该日志发给所有的处理器进行处理,然后将各处理器加工后的业务信息通过对应的分发器分发给相应的人员。如:

dual 动态 creator,taskOwner

意即定义了一个名为【动态】的处理器,处理结果发给creator和taskOwner的接收者。

jxTMS预定义了如下的接收者:

【动态】这个处理器要求把捕获到的日志传递给本capa中定义的对应的处理函数,但我们并没有定义该函数,所以就按默认处理【是把该日志信息做个简单的信息拼接】,然后分发给事的创建者和事的管理者【如项目经理】。

又如:

dual 工作报告 stat per day,week,month to caller,owner

【工作报告】要求把指定时间段内捕获到的日志传递给对应的处理函数进行加工,然后把加工后的业务信息分发给事的创建者和事所在部门的管理者【如部门经理】。

比较这两者,大家发现工作报告比动态多了一个stat的标记。stat标记指示当捕获到日志信息后,并不会立刻进行处理,而是将其保存到数据库中。然后会启动一个定时器,按分发器中所指示的分发周期定时来执行相应的处理器,再将处理器加工后的业务信息进行分发。

我们再看一下工作报告处理器的实现,由于代码较长,我对代码进行了一定的删减:

@myModule.request('bizData','bizDataStream','工作报告'.decode('utf-8'))
def bizDataStream(self, db, ctx, qo, list):
    #timeStyle是哪个等级的汇总:preDay、preWeek、preMonth等
    #timeStyle = self.getInput('period')
    reportByPeople = getattr(self,'rbp',None)
    if list is None:
        #日志数据发送完毕,清理
        self.rbp = jxJson.getArrayNode()
        #本次stat处理完毕
        return reportByPeople
    if reportByPeople is None:
        #第一次送入数据,进行初始化
        reportByPeople = jxJson.getArrayNode()
        self.rbp = reportByPeople
    for js in list:
        #日志中记载的是:谁在什么时间干了什么,我们要分别进行提取
        #从日志中提取信息,wo是谁
        wo = js.getSubValueString('Who')
        wid = js.getSubValueLong('WhoID')
        ...
        #根据这些信息从汇总结果中查找,这里是按人进行汇总
        rp = reportByPeople.getByKey('WhoID',wid)
        if rp is None:
            #该员工第一次出现,用提取到的信息进行装订
            rp = ...
            reportByPeople.add(rp)
            tip = wo + ' 的工作报告:\n'.decode('utf-8') + '本次的工作说明'
            rp.set('Content',tip)
        else:
            #该员工已经出现过了,将本次他干了什么合并到周报中
            cs = utils.stringAdd(rp.get('Content'),'\n','本次的工作说明')
            rp.set('Content',cs)

该代码就是在本次汇总期内:

由于可能查询出来的数据量太大,所以stat处理器是每次查询100个记录,放到list中送给处理器处理,最后用一个空的list通知处理器没数据了。

注:为避免self.rbp受到干扰,所以处理器使用前会被加锁

这就完成了工作报告的信息加工:日报、周报、月报。

标签:stat,捕获,抓取,信息,生成,处理器,日志,周报
来源: https://blog.csdn.net/jxandrew/article/details/123591722