精华内容
下载资源
问答
  • 系统操作日志设计

    万次阅读 2015-12-06 15:02:57
    我们在做企业管理系统时,有多多少少都有对数据的完整性有所要求,比如要求系统不能物理删除记录,要求添加每一条数据时都要有系统记录、或者更新某条数据都需要跟踪到变化的内容、或者删除数据时需要记录谁删除了,...

    为什么要做操作日志?

    其实上文也描述了一些,其主要目的就是跟踪到每一个用户在系统的操作行为,如对数据进行查询、新增、编辑或删除甚至是登录等行为。更进一步的理解可以说是对用户使用系统情况的跟踪,对数据的跟踪防止数据意外删除、更改时有所记录,有所依据,以便对数据的还原,从某种程序上可以保护数据的完整性。

     

    系统设计

    场景

    我们现在有一张表叫Employee:

    ID int
    Name nvarchar(50)
    Gender nvarchar(2)
    DateCreated datetime
    CreateUser nvarchar(50)

    在aspx页面中可能会有EmployeeEdit.aspx(用来添加或更新Employee信息等操作),EmployeeList.aspx(用来查询或进行删除Employee信息等操作)

    好了,现在我们要对Empoyee表操作的信息做一个系统日志,那怎么办?

    也许你可以建立多一个表跟Employee表一模一样的,叫做EmployeeLog

    ID int
    Name nvarchar(50)
    Gender nvarchar(2)
    DateCreated datetime
    CreateUser nvarchar(50)
    LogCreated datetime
    OperationType int

    其中加多了一些附属的信息如LogCreated(日志添加日期)和OperationType(查询、新增、删除、更新)

    此时这种情况可能大家在做用户登录日志的时候是一件很常见的事件。

    但……问题来了,假如我需要对表EmployeeIncome(员工的收入情况)做日志那怎么办?

    好建立多一张表叫EmployeeIncomeLog来记录员工收入情况的操作日志。

    假如又需要对表FixedAsset(固定资产)进行日志记录那又怎么办?

     

    好了,大家可能意识到我们这样做不但会造成表数量的增倍,而且大大的增加了工作量和开发时间,对数据库表不易管理等情况。

     

    因此我们需要一个能够通过简单的配置和编写就可以完成以上功能的日志管理

    数据库设计

    系统日志设计

    包括三个表,

    LogSetting(日志设置)——用来存储配置业务表名、业务名称、主键等

    LogSettingDetail(日志设置明细)——用来存储配置业务表需要记录的详细内容,如Employee表中,我们可能需要记录字段Name、Gender等信息。

    LogOperation(操作日志)——用来记录用户对各种业务操作的内容情况。

     

    下篇将讨论用代码如何实现日志管理的功能,下面先来几张图:

    日志列表:

    日志管理列表

    查看日志内容:

    查看日志内容



    管理系统的操作日志:

    管理系统的操作日志如何做成通用的模块一直是个让我头疼的问题,不过看了博客园里的某篇文章后,现在基本解决了。

      相关文章链接:《系统操作日志设计

      在开始做之前,必须把两个日志分清楚,那就是普通操作日志业务操作日志,这两者有何区别?

      在我理解,普通操作日志就是单表的操作记录,而业务操作日志则就是一系列的普通操作日志的集合。

      打个比方,用户需要购买一样宝贝,已经到了下单那步,下单就是个业务,这个业务背后就是一系列的业务,如:

      生成订单 → 生成商品快照 → 发送一条站内信 → 删除购物车里对应宝贝

      这样一个下单操作就包含了4部分,可以把这4部分看成是4张表,分别对这4张表进行对应的操作,就实现了业务。

      但今天我要讲的不是业务操作日志,因为不同项目的业务不尽相同,所以它无法做成通用模块,而我要讲的,就是普通操作日志。

      上面解释了一大段,下面干货就要亮相了,先洗把脸清醒下。

      ……

      首先,哪些地方需要记录操作日志?执行insert、update、delete这3个操作的时候,就需要进行日志,而日志执行的先后顺序如下

    insert 在insert后执行
    update 在update前后都要执行,操作前获取操作前数据,操作后获取操作后数据
    delete 在delete前执行

      顺序清楚后,就来看下我写的一份日志操作类吧,第一版随便写写的,重复代码有点多,还未来得及优化。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    class LOG{
        protected $primaryid;
        protected $tbid;
        protected $tbname;
        protected $keys;
        protected $values;
        /**
         * 参数说明
         * int              $tbid       查询指定表的id
         * string           $tbname     数据库表名
         */
        public function insert($tbid$tbname){
            global $db;
            //查询表注释
            $db->query('show table status where name = "'.$tbname.'"');
            $tb $db->fetch();
            //插入日志主表
            $returnid $db->insert(0, 2, 'tb_log'array(
                'adminid = '.$_SESSION['admin']['id'],
                'type = 1',
                'tableid = '.$tbid,
                'tablename = "'.$tbname.'"',
                'comment = "'.$tb['Comment'].'"',
                'dt = now()'
            ));
            //查询字段注释
            $db->query('show full columns from '.$tbname);
            $tb $db->fetchAll();
            foreach($tb as $v){
                $commentArray[$v['Field']] = $v['Comment'];
            }
            //查询所有字段信息,插入日志从表
            $rs $db->select(0, 1, $tbname'*''and tbid = '.$tbid);
            $keys array_keys($rs);
            $values array_values($rs);
            for($i = 0; $i count($keys); $i++){
                $db->insert(0, 0, 'tb_log_content'array(
                    'logid = '.$returnid,
                    'tbkey = "'.$keys[$i].'"',
                    'tbvalue = "'.$values[$i].'"',
                    'comment = "'.$commentArray[$keys[$i]].'"'
                ));
            }
        }
        public function updateStart($tbid$tbname){
            global $db;
            //查询表注释
            $db->query('show table status where name = "'.$tbname.'"');
            $tb $db->fetch();
            //插入日志主表
            $returnid $db->insert(0, 2, 'tb_log'array(
                'adminid = '.$_SESSION['admin']['id'],
                'type = 2',
                'tableid = '.$tbid,
                'tablename = "'.$tbname.'"',
                'comment = "'.$tb['Comment'].'"',
                'dt = now()'
            ));
            //查询修改前数据信息
            $rs $db->select(0, 1, $tbname'*''and tbid = '.$tbid);
            $keys array_keys($rs);
            $values array_values($rs);
            $this->primaryid = $returnid;
            $this->tbid = $tbid;
            $this->tbname = $tbname;
            $this->keys = $keys;
            $this->values = $values;
        }
        public function updateEnd(){
            global $db;
            //查询字段注释
            $db->query('show full columns from '.$this->tbname);
            $tb $db->fetchAll();
            foreach($tb as $v){
                $commentArray[$v['Field']] = $v['Comment'];
            }
            //查询修改后数据信息
            $rs $db->select(0, 1, $this->tbname, '*''and tbid = '.$this->tbid);
            $currentvalues array_values($rs);
            //前后信息进行比较
            for($i = 0; $i count($currentvalues); $i++){
                if($this->values[$i] !== $currentvalues[$i]){
                    $db->insert(0, 0, 'tb_log_content'array(
                        'logid = '.$this->primaryid,
                        'tbkey = "'.$this->keys[$i].'"',
                        'tbvalue = "'.$this->values[$i].'"',
                        'currenttbvalue = "'.$currentvalues[$i].'"',
                        'comment = "'.$commentArray[$this->keys[$i]].'"'
                    ));
                }
            }
        }
        public function delete($tbid$tbname){
            global $db;
            //查询表注释
            $db->query('show table status where name = "'.$tbname.'"');
            $tb $db->fetch();
            //插入日志主表
            $returnid $db->insert(0, 2, 'tb_log'array(
                'adminid = '.$_SESSION['admin']['id'],
                'type = 3',
                'tableid = '.$tbid,
                'tablename = "'.$tbname.'"',
                'comment = "'.$tb['Comment'].'"',
                'dt = now()'
            ));
            //查询字段注释
            $db->query('show full columns from '.$tbname);
            $tb $db->fetchAll();
            foreach($tb as $v){
                $commentArray[$v['Field']] = $v['Comment'];
            }
            //查询所有字段信息,插入日志从表
            $rs $db->select(0, 1, $tbname'*''and tbid = '.$tbid);
            $keys array_keys($rs);
            $values array_values($rs);
            for($i = 0; $i count($keys); $i++){
                $db->insert(0, 0, 'tb_log_content'array(
                    'logid = '.$returnid,
                    'tbkey = "'.$keys[$i].'"',
                    'tbvalue = "'.$values[$i].'"',
                    'comment = "'.$commentArray[$keys[$i]].'"'
                ));
            }
        }
    }

      使用前,需要引入数据库操作类,这是我之前写的一份,可参考《全新的PDO数据库操作类(仅适用Mysql)》。

      引入之后,就可以开始使用了。

      select

    1
    $log->insert(82, 'tb_member');

      update

    1
    2
    3
    $log->updateStart(82, 'tb_member');
    //中间放更新操作代码
    $log->updateEnd();

      delete

    1
    $log->delete(82, 'tb_member');

      可以看到,一共只需要两个参数即可,分别是表ID(主键)和表名称。

      另外需要强调一点,表注释和字段注释一定要完整,因为记录的信息包含注释,目的就是为了查阅的时候能清楚哪个字段是干什么用的。

      下面就看下成品吧

      最后把表结构分享下,一共2张表,一张主表一张从表,主表记录操作表及操作人等信息,从表记录操作的表字段信息。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    -- ----------------------------
    -- Table structure for `tb_log`
    -- ----------------------------
    CREATE TABLE `tb_log` (
      `tbid` bigint(20) NOT NULL AUTO_INCREMENT,
      `adminid` bigint(20) DEFAULT NULL COMMENT '管理员id',
      `type` tinyint(4) DEFAULT '1' COMMENT '操作类型:1新增2修改3删除',
      `tableid` bigint(20) DEFAULT NULL,
      `tablename` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '表名',
      `comment` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      `dt` datetime DEFAULT NULL,
      PRIMARY KEY (`tbid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
     
    -- ----------------------------
    -- Table structure for `tb_log_content`
    -- ----------------------------
    CREATE TABLE `tb_log_content` (
      `tbid` bigint(20) NOT NULL AUTO_INCREMENT,
      `logid` bigint(20) DEFAULT NULL,
      `tbkey` longtext COLLATE utf8_unicode_ci,
      `tbvalue` longtext COLLATE utf8_unicode_ci,
      `currenttbvalue` longtext COLLATE utf8_unicode_ci,
      `comment` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      PRIMARY KEY (`tbid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


    展开全文
  • 设计单片机日志系统

    千次阅读 2016-09-13 16:19:14
     环境:主机:WIN10开发环境:MDK5.12MCU:STM32F407说明:为单片机设计了一套简单的日志系统,通过日志系统提供的接口可以查看设备状态,并进行一些基本的调试。日志系统通过串口输出,所以单片机需要准备一个串口供...

    设计单片机日志系统


    本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

     

    环境:

    主机:WIN10

    开发环境:MDK5.12

    MCU:STM32F407


    说明:
    为单片机设计了一套简单的日志系统,通过日志系统提供的接口可以查看设备状态,并进行一些基本的调试。
    日志系统通过串口输出,所以单片机需要准备一个串口供日志系统使用。注意串口发送不能用DMA发送(避免在在中断中打印日志造成的中断竞争),接收可以用DMA接收。

    功能:
    • 打开/关闭各个模块的调试输出
    • 输入动作指令,让设备进行一些动作
    • 打印系统运行日志
    指令:
    • H:帮助
    • O:调试输出全开
    • O1:打开1号模块,打开其他模块指令类似
    • F:调试输出全关
    • F1:关闭1号模块
    • I:输出系统日志
    • C:清除系统日志
    • A1:执行1号动作,执行其他动作指令类似

    源代码:

    log.h:

    /**
    * Copyright (c), 2015-2025
    * @file log.h
    * @brief 日志模块主文件
    * @author jdh
    * @date 2015/5/7
    * @update 2015/6/19
    * @update 2015/6/23
    * @update 2015/6/30
    * @update 2015/7/8
    * @update 2015/7/13
    * @update 2015/8/12
    * @update 2015/8/18
    * @update 2016/5/17
    * @update 2016/6/30
    * @update 2016/7/22
    * @update 2016/8/11
    * @update 2016/8/24
    * @update 2016/9/2
    * @update 2016/9/5
    * @update 2016/9/7
    * @update 2016/9/9
    */
    
    #ifndef _LOG_H_
    #define _LOG_H_
    
    /*********************************************************************
    *							头文件
    **********************************************************************/
    
    #include "world.h"
    #include "console.h"
    
    /*********************************************************************
    *							宏定义
    **********************************************************************/
    
    /**
    * @brief 日志模块数量
    */
    #define NUM_LOG					5
    
    /**
    * @brief 模块编号
    */
    
    #define LOG_TEST				0
    #define LOG_CLOCK				1
    #define LOG_DW1000				2
    #define LOG_DW1000_STATUS		3
    #define LOG_DEAL_BUS			4
    
    /*********************************************************************
    *							数据结构
    **********************************************************************/
    
    /**
    * @brief 日志
    */
    
    struct _Log
    {
    	//公有日志
    	//收到移动点数据次数
    	uint32_t num_rf_rx;
    	//发送超时被删除点数
    	uint32_t num_time_out_delete;
    	//RF发送次数
    	uint32_t num_rf_tx;
    	//RF校时或分配事件次数
    	uint32_t num_rf_time;
    	//RF随机信道发送次数
    	uint32_t num_rf_random_tx;
    	//复位次数
    	uint32_t num_reset;
    	//运行时间,分度为0.5s
    	uint32_t time_run;
    	//收到同步脉冲计数
    	uint32_t num_sync_pulse;
    	//收到422轮询/事件帧次数
    	uint32_t num_bus_poll;
    	//收到422事务命令次数
    	uint32_t num_bus_down_cmd;
    	//收到422事务命令中事件个数
    	uint32_t num_bus_down_cmd_dot;
    	//收到有效的422帧次数
    	uint32_t num_valid_bus;
    	//收到无效的422帧次数
    	uint32_t num_invalid_bus;
    	//接收时间错误
    	uint32_t num_time_error;
    	
    	//私有日志
    	//dw1000芯片错误次数
    	uint32_t num_dw1000_error[NUM_DW1000];
    	//接收时间错误
    	uint32_t num_dw1000_time_error[NUM_DW1000];
    	//轮询超时被删除点数
    	uint32_t num_poll_time_out_delete;
    	//接收超时复位
    	uint32_t num_dw1000_time_out_reset[NUM_DW1000];
    	//dw1000芯片状态错误次数
    	uint32_t num_dw1000_status_error[NUM_DW1000];
    };
    
    /*********************************************************************
    *							函数
    **********************************************************************/
    
    /**
    * @brief 模块加载
    */
    
    void log_load(void);
    
    /**
    * @brief 读取日志
    * @retval 日志
    */
    
    struct _Log log_read(void);
    
    /**
    * @brief 清除日志
    */
    
    void log_clear(void);
    
    /**
    * @brief 收到移动点数据次数
    */
    
    void log_write_num_rf_rx(void);
    
    /**
    * @brief 发送超时被删除点数
    */
    
    void log_write_num_time_out_delete(void);
    
    /**
    * @brief RF发送次数
    */
    
    void log_write_num_rf_tx(void);
    
    /**
    * @brief RF校时或分配事件次数
    */
    
    void log_write_num_rf_time(void);
    
    /**
    * @brief RF随机信道发送次数
    */
    
    void log_write_num_rf_random_tx(void);
    
    /**
    * @brief 复位次数
    */
    
    void log_write_num_reset(void);
    
    /**
    * @brief 运行时间
    * @param add_time:增加的时间.单位:0.5s
    */
    
    void log_write_time_run(uint32_t add_time);
    
    /**
    * @brief 收到同步脉冲计数
    */
    
    void log_write_num_sync_pulse(void);
    
    /**
    * @brief 收到422轮询/事件帧次数
    */
    
    void log_write_num_bus_poll(void);
    
    /**
    * @brief 收到422事务命令次数
    */
    
    void log_write_num_bus_down_cmd(void);
    
    /**
    * @brief 收到422事务命令中事件个数
    */
    
    void log_write_num_bus_down_cmd_dot(void);
    
    /**
    * @brief 收到有效的422帧次数
    */
    
    void log_write_num_valid_bus(void);
    
    /**
    * @brief 收到无效的422帧次数
    */
    
    void log_write_num_invalid_bus(void);
    
    /**
    * @brief 收到时间错误
    */
    
    void log_write_num_time_error(void);
    
    /**
    * @brief dw1000芯片错误次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_error(uint8_t index);
    
    /**
    * @brief dw1000芯片接收时间错误次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_time_error(uint8_t index);
    
    /**
    * @brief 轮询超时被删除点数
    */
    
    void log_write_num_poll_time_out_delete(void);
    
    /**
    * @brief dw1000芯片接收超时复位次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_time_out_reset(uint8_t index);
    
    /**
    * @brief dw1000芯片状态错误次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_status_error(uint8_t index);
    
    /**
    * @brief 控制台打印
    * @param index:模块编号
    * @param info:打印的信息
    */
    
    void log_print(uint8_t index,char *info);
    
    /**
    * @brief 控制台强制打印
    * @param info:打印的信息
    */
    
    void log_print_force(char *info);
    
    /**
    * @brief 接收处理
    * @param rx:接收数据
    */
    
    void log_deal_rx(struct _Console_Rx rx);
    
    #endif
    
    

    log.c:

    /**
    * Copyright (c), 2015-2025
    * @file log.c
    * @brief 日志模块主文件
    * @author jdh
    * @email jdh821@163.com
    * @date 2015/5/7
    * @update 2015/6/19
    * @update 2015/6/30
    * @update 2015/7/8
    * @update 2015/7/13
    * @update 2015/7/15
    * @update 2015/8/12
    * @update 2015/8/13
    * @update 2015/11/11
    * @update 2016/5/17
    * @update 2016/6/30
    * @update 2016/7/22
    * @update 2016/8/11
    * @update 2016/8/18
    * @update 2016/8/22
    * @update 2016/8/24
    * @update 2016/9/2
    * @update 2016/9/5
    * @update 2016/9/7
    * @update 2016/9/9
    * @update 2016/9/12
    */
    
    /*********************************************************************
    *							头文件
    **********************************************************************/
    
    #include "log.h"
    #include "protocol_bus.h"
    #include "protocol_uwb.h"
    #include "para_manage.h"
    
    /*********************************************************************
    *							静态变量
    **********************************************************************/
    
    /**
    * @brief 运行日志
    */
    
    static struct _Log Log __attribute__((section("NO_INIT"),zero_init));
    
    /**
    * @brief 日志过滤标志数组,0:未过滤,1:过滤
    */
    
    static uint8_t Filter[NUM_LOG] = {1, 1, 1, 1, 1};
    
    /**
    * @brief 暂停输出标志,0:未暂停输出,1:暂停输出
    */
    
    static uint8_t Flag_Pause = 0;
    
    /*********************************************************************
    *							静态函数
    **********************************************************************/
    
    /**
    * @brief 帮助界面
    */
    
    static void help(void);
    
    /**
    * @brief 输出本地日志
    */
    
    static void print_log(void);
    
    /**
    * @brief 处理动作
    * @param index:动作编号
    */
    
    static void deal_action(uint8_t index);
    
    /*********************************************************************
    *							函数
    **********************************************************************/
    
    /**
    * @brief 模块加载
    */
    
    void log_load(void)
    {
    	//检查是否上电
    	if (RCC_GetFlagStatus(RCC_FLAG_PORRST) == SET)
    	{
    		//清除标志位
    		RCC_ClearFlag();
    		//清除日志
    		memset(&Log, 0, sizeof(Log));
    	}
    	else
    	{
    	 	//日志:复位次数
    		Log.num_reset++;
    	}
    }
    
    /**
    * @brief 清除日志
    */
    
    void log_clear(void)
    {
    	memset(&Log, 0, sizeof(Log));
    }
    
    /**
    * @brief 读取日志
    * @retval 日志
    */
    
    struct _Log log_read(void)
    {	
    	return Log;
    }
    
    /**
    * @brief 收到移动点数据次数
    */
    
    void log_write_num_rf_rx(void)
    {
    	Log.num_rf_rx++;
    }
    
    /**
    * @brief 发送超时被删除点数
    */
    
    void log_write_num_time_out_delete(void)
    {
    	Log.num_time_out_delete++;
    }
    
    /**
    * @brief RF发送次数
    */
    
    void log_write_num_rf_tx(void)
    {
    	Log.num_rf_tx++;
    }
    
    /**
    * @brief RF校时或分配事件次数
    */
    
    void log_write_num_rf_time(void)
    {
    	Log.num_rf_time++;
    }
    
    /**
    * @brief RF随机信道发送次数
    */
    
    void log_write_num_rf_random_tx(void)
    {
    	Log.num_rf_random_tx++;
    }
    
    /**
    * @brief 复位次数
    */
    
    void log_write_num_reset(void)
    {
    	Log.num_reset++;
    }
    
    /**
    * @brief 运行时间
    * @param add_time:增加的时间.单位:0.5s
    */
    
    void log_write_time_run(uint32_t add_time)
    {
    	Log.time_run += add_time;
    }
    
    /**
    * @brief 收到同步脉冲计数
    */
    
    void log_write_num_sync_pulse(void)
    {
    	Log.num_sync_pulse++;
    }
    
    /**
    * @brief 收到422轮询/事件帧次数
    */
    
    void log_write_num_bus_poll(void)
    {
    	Log.num_bus_poll++;
    }
    
    /**
    * @brief 收到422事务命令次数
    */
    
    void log_write_num_bus_down_cmd(void)
    {
    	Log.num_bus_down_cmd++;
    }
    
    /**
    * @brief 收到422事务命令中事件个数
    */
    
    void log_write_num_bus_down_cmd_dot(void)
    {
    	Log.num_bus_down_cmd_dot++;
    }
    
    /**
    * @brief 收到有效的422帧次数
    */
    
    void log_write_num_valid_bus(void)
    {
    	Log.num_valid_bus++;
    }
    
    /**
    * @brief 收到无效的422帧次数
    */
    
    void log_write_num_invalid_bus(void)
    {
    	Log.num_invalid_bus++;
    }
    
    /**
    * @brief 收到时间错误
    */
    
    void log_write_num_time_error(void)
    {
    	Log.num_time_error++;
    }
    
    /**
    * @brief dw1000芯片错误次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_error(uint8_t index)
    {
    	Log.num_dw1000_error[index]++;
    }
    
    /**
    * @brief dw1000芯片接收时间错误次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_time_error(uint8_t index)
    {
    	Log.num_dw1000_time_error[index]++;
    }
    
    /**
    * @brief 轮询超时被删除点数
    */
    
    void log_write_num_poll_time_out_delete(void)
    {
    	Log.num_poll_time_out_delete++;
    }
    
    /**
    * @brief dw1000芯片接收超时复位次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_time_out_reset(uint8_t index)
    {
    	Log.num_dw1000_time_out_reset[index]++;
    }
    
    /**
    * @brief dw1000芯片状态错误次数
    * @param index:模块序号,从0开始
    */
    
    void log_write_num_dw1000_status_error(uint8_t index)
    {
    	Log.num_dw1000_status_error[index]++;
    }
    
    /**
    * @brief 控制台打印
    * @param index:模块编号
    * @param info:打印的信息
    */
    
    void log_print(uint8_t index,char *info)
    {
    	T_Time time;
    	char log_out[256] = {0};
    	
    	//判断是否是暂停输出
    	if (Flag_Pause)
    	{
    		return;
    	}
    	
    	//判断是否被过滤输出
    	if (Filter[index])
    	{
    		return;
    	}
    	
    	time = get_time();
    	sprintf(log_out,"%05d:%03d:%03d %s\r\n",time.s,time.ms,time.us,info);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    }
    
    /**
    * @brief 控制台强制打印
    * @param info:打印的信息
    */
    
    void log_print_force(char *info)
    {
    	T_Time time;
    	char log_out[256] = {0};
    	
    	time = get_time();
    	sprintf(log_out,"%05d:%03d:%03d %s\r\n",time.s,time.ms,time.us,info);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    }
    
    /**
    * @brief 接收处理
    * @param rx:接收数据
    */
    
    void log_deal_rx(struct _Console_Rx rx)
    {
    	uint8_t i = 0;
    	int num = 0;
    	char str_temp[5] = {0};
    	
    	//判断是否是输出本地日志
    	if (rx.len == 1 && rx.buf[0] == 'I')
    	{
    		print_log();
    		return;
    	}
    	
    	//判断是否是输出本地日志
    	if (rx.len == 1 && rx.buf[0] == 'C')
    	{
    		log_clear();
    		return;
    	}
    	
    	//判断是否是暂停输出
    	if (rx.len == 1 && rx.buf[0] == 'P')
    	{
    		Flag_Pause = 1;
    		return;
    	}
    	
    	//判断是否是打开输出
    	if (rx.len == 1 && rx.buf[0] == 'S')
    	{
    		Flag_Pause = 0;
    		return;
    	}
    	
    	//判断是否是帮助
    	if (rx.len == 1 && rx.buf[0] == 'H')
    	{
    		help();
    		return;
    	}
    	
    	//判断是否是过滤规则
    	if (rx.len <= 3 && rx.buf[0] == 'F')
    	{	
    		if (rx.len == 1)
    		{
    			//全部过滤
    			for (i = 0;i < NUM_LOG;i++)
    			{
    				Filter[i] = 1;
    			}
    			return;
    		}
    		
    		memset(str_temp,sizeof(str_temp),0);
    		memcpy(str_temp,rx.buf,rx.len);
    		sscanf(str_temp,"F%d",&num);
    		Filter[num] = 1;
    		return;
    	}
    	
    	//判断是否是打开模块
    	if (rx.len <= 3 && rx.buf[0] == 'O')
    	{	
    		if (rx.len == 1)
    		{
    			//清除过滤规则
    			for (i = 0;i < NUM_LOG;i++)
    			{
    				Filter[i] = 0;
    			}
    			return;
    		}
    		
    		memset(str_temp,sizeof(str_temp),0);
    		memcpy(str_temp,rx.buf,rx.len);
    		sscanf(str_temp,"O%d",&num);
    		Filter[num] = 0;
    		return;
    	}
    	
    	//判断是否是打开模块
    	if (rx.len > 1 && rx.len <= 3 && rx.buf[0] == 'A')
    	{	
    		memset(str_temp,sizeof(str_temp),0);
    		memcpy(str_temp,rx.buf,rx.len);
    		sscanf(str_temp,"A%d",&num);
    		deal_action(num);
    		return;
    	}
    }
    
    /**
    * @brief 帮助界面
    */
    
    static void help(void)
    {
    	char log_out[100] = {0};
    	
    	strcpy(log_out,"*******************************************\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"             UWB基站日志帮助界面            \r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"硬件版本:%d 软件版本:%d\r\n",VERSION_HARD,VERSION_SOFT);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"总线通信协议版本:%s\r\n",VERSION_NAME_BUS);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"空口通信协议版本:%s\r\n",VERSION_NAME_UWB);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"CSSN:0x%06x ID:0x%04x\r\n",para_manage_read_cssn(), para_manage_read_id());
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键I(INFO)输出本地日志\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键C(CLEAR)清除本地日志\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键P(PAUSE)暂停输出\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键S(START)开始输出\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键A(ACTION)动作\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"A1:读取1号dw1000状态寄存器\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"A2:清除1号dw1000状态寄存器\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"A3:打开1号dw1000接收\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键H(HELP)打开帮助\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键F(FILTER)过滤输出\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"例:过滤1号模块:F1\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"例:全部过滤:F\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"快捷键O(OPEN)打开模块\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"例:打开1号模块:O1\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"例:全部打开:O\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"包含的模块:\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"TEST:%d 过滤:%d \r\n",LOG_TEST,Filter[LOG_TEST]);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"CLOCK:%d 过滤:%d \r\n",LOG_CLOCK,Filter[LOG_CLOCK]);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"DW1000:%d 过滤:%d \r\n",LOG_DW1000,Filter[LOG_DW1000]);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"DW1000_STATUS:%d 过滤:%d \r\n",LOG_DW1000_STATUS,Filter[LOG_DW1000_STATUS]);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"DW1000_DEAL_BUS:%d 过滤:%d \r\n",LOG_DEAL_BUS,Filter[LOG_DEAL_BUS]);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	strcpy(log_out,"*******************************************\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    }
    
    /**
    * @brief 输出本地日志
    */
    
    static void print_log(void)
    {
    	char log_out[100] = {0};
    	uint8_t i = 0;
    	
    	strcpy(log_out,"本地日志输出:\r\n");
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到移动点数据次数:%d\r\n", Log.num_rf_rx);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"发送超时被删除点数:%d\r\n", Log.num_time_out_delete);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"RF发送次数:%d\r\n", Log.num_rf_tx);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"RF校时或分配事件次数:%d\r\n", Log.num_rf_time);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"RF随机信道发送次数:%d\r\n", Log.num_rf_random_tx);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"复位次数:%d\r\n", Log.num_reset);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"运行时间:%d\r\n", Log.time_run);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到同步脉冲计数:%d\r\n", Log.num_sync_pulse);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到422轮询/事件帧次数:%d\r\n", Log.num_bus_poll);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到422事务命令次数:%d\r\n", Log.num_bus_down_cmd);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到422事务命令中事件个数:%d\r\n", Log.num_bus_down_cmd_dot);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到有效的422帧次数:%d\r\n", Log.num_valid_bus);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"收到无效的422帧次数:%d\r\n", Log.num_invalid_bus);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	sprintf(log_out,"校时时间错误次数:%d\r\n", Log.num_time_error);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	for (i = 0; i < NUM_DW1000; i++)
    	{
    		sprintf(log_out,"%d号dw1000模块错误次数:%d\r\n", i, Log.num_dw1000_error[i]);
    		console_tx((uint8_t *)log_out,strlen(log_out));
    	}
    	for (i = 0; i < NUM_DW1000; i++)
    	{
    		sprintf(log_out,"%d号dw1000模块时间错误次数:%d\r\n", i, Log.num_dw1000_time_error[i]);
    		console_tx((uint8_t *)log_out,strlen(log_out));
    	}
    	sprintf(log_out,"轮询超时被删除点数:%d\r\n", Log.num_poll_time_out_delete);
    	console_tx((uint8_t *)log_out,strlen(log_out));
    	for (i = 0; i < NUM_DW1000; i++)
    	{
    		sprintf(log_out,"%d号dw1000模块接收时间超时复位次数:%d\r\n", i, Log.num_dw1000_time_out_reset[i]);
    		console_tx((uint8_t *)log_out,strlen(log_out));
    	}
    	for (i = 0; i < NUM_DW1000; i++)
    	{
    		sprintf(log_out,"%d号dw1000模块状态错误次数:%d\r\n", i, Log.num_dw1000_status_error[i]);
    		console_tx((uint8_t *)log_out,strlen(log_out));
    	}
    }
    
    /**
    * @brief 处理动作
    * @param index:动作编号
    */
    
    static void deal_action(uint8_t index)
    {
    	uint32_t status = 0;
    	char log_out[100] = {0};
    	
    	switch (index)
    	{
    		//读取1号dw1000状态寄存器
    		case 1:
    		{
    			status = dwt_read32bitreg(0, SYS_STATUS_ID);
    			sprintf(log_out,"1号dw1000状态:0x%08x\r\n", status);
    			console_tx((uint8_t *)log_out,strlen(log_out));
    			break;
    		}
    		//清除1号dw1000状态寄存器
    		case 2:
    		{
    			status = dwt_read32bitreg(0, SYS_STATUS_ID);
    			dwt_write32bitreg(0, SYS_STATUS_ID, status);
    			break;
    		}
    		//打开1号dw1000接收
    		case 3:
    		{
    			dwt_rxenable(0, 0);
    			break;
    		}
    	}
    }
    
    
    
    


    展开全文
  • 系统设计——操作日志

    千次阅读 2017-07-10 16:41:44
    系统操作日志原型设计: 该设计主要为实现用户操作一些重要功能过程中,系统会自动记载对应操作日志,以及操作过程中涉及的库、表、字段及数据变动,以便后期追责、及功能回退等需要。 名词解释: 业务编码: 指系统...

    系统操作日志原型设计:

    该设计主要为实现用户操作一些重要功能过程中,系统会自动记载对应操作日志,以及操作过程中涉及的库、表、字段及数据变动,以便后期追责、及功能回退等需要。

    名词解释:

    业务编码:

    指系统区分业务操作的系统标识,该编码一般可存于系统字典表当中,也可以单独简历码表。

    业务对象:

    日志在被用于查询过程中,往往需要根据某个资源去查询被操作历史记录。拿网购商城举例:一部手机从进货到占用再被销售,整个过程中产生的日志将被系统归属于这一步手机,库管员可以针对该手机查询它曾经被操作或被使用的历史记录。
     

    日志相关表变动:

    指完成某个业务操作过程中,数据方面曾经发生的变动情况,具体到某些字段的值变动。本设计是先提供表变动及变动顺序情况,再提供各个表的字段变动情况。

    模型如图:

    展开全文
  • 管理系统的操作日志如何做成通用的模块一直是个让我头疼的问题,不过看了博客园里的某篇文章后,现在基本解决了。... 相关文章链接:《系统操作日志设计》  在开始做之前,必须把两个日志分清楚,那就是普
    原文地址为:浅谈管理系统操作日志设计(附操作日志类)

      管理系统的操作日志如何做成通用的模块一直是个让我头疼的问题,不过看了博客园里的某篇文章后,现在基本解决了。

      相关文章链接:《系统操作日志设计

      在开始做之前,必须把两个日志分清楚,那就是普通操作日志业务操作日志,这两者有何区别?

      在我理解,普通操作日志就是单表的操作记录,而业务操作日志则就是一系列的普通操作日志的集合。

      打个比方,用户需要购买一样宝贝,已经到了下单那步,下单就是个业务,这个业务背后就是一系列的业务,如:

      生成订单 → 生成商品快照 → 发送一条站内信 → 删除购物车里对应宝贝

      这样一个下单操作就包含了4部分,可以把这4部分看成是4张表,分别对这4张表进行对应的操作,就实现了业务。

      但今天我要讲的不是业务操作日志,因为不同项目的业务不尽相同,所以它无法做成通用模块,而我要讲的,就是普通操作日志。

      上面解释了一大段,下面干货就要亮相了,先洗把脸清醒下。

      ……

      首先,哪些地方需要记录操作日志?执行insert、update、delete这3个操作的时候,就需要进行日志,而日志执行的先后顺序如下

    insert 在insert后执行
    update 在update前后都要执行,操作前获取操作前数据,操作后获取操作后数据
    delete 在delete前执行

      顺序清楚后,就来看下我写的一份日志操作类吧,第一版随便写写的,重复代码有点多,还未来得及优化。

    class LOG{
    protected $primaryid;
    protected $tbid;
    protected $tbname;
    protected $keys;
    protected $values;
    /**
    * 参数说明
    * int $tbid 查询指定表的id
    * string $tbname 数据库表名
    */
    public function insert($tbid, $tbname){
    global $db;
    //查询表注释
    $db->query('show table status where name = "'.$tbname.'"');
    $tb = $db->fetch();
    //插入日志主表
    $returnid = $db->insert(0, 2, 'tb_log', array(
    'adminid = '.$_SESSION['admin']['id'],
    'type = 1',
    'tableid = '.$tbid,
    'tablename = "'.$tbname.'"',
    'comment = "'.$tb['Comment'].'"',
    'dt = now()'
    ));
    //查询字段注释
    $db->query('show full columns from '.$tbname);
    $tb = $db->fetchAll();
    foreach($tb as $v){
    $commentArray[$v['Field']] = $v['Comment'];
    }
    //查询所有字段信息,插入日志从表
    $rs = $db->select(0, 1, $tbname, '*', 'and tbid = '.$tbid);
    $keys = array_keys($rs);
    $values = array_values($rs);
    for($i = 0; $i < count($keys); $i++){
    $db->insert(0, 0, 'tb_log_content', array(
    'logid = '.$returnid,
    'tbkey = "'.$keys[$i].'"',
    'tbvalue = "'.$values[$i].'"',
    'comment = "'.$commentArray[$keys[$i]].'"'
    ));
    }
    }
    public function updateStart($tbid, $tbname){
    global $db;
    //查询表注释
    $db->query('show table status where name = "'.$tbname.'"');
    $tb = $db->fetch();
    //插入日志主表
    $returnid = $db->insert(0, 2, 'tb_log', array(
    'adminid = '.$_SESSION['admin']['id'],
    'type = 2',
    'tableid = '.$tbid,
    'tablename = "'.$tbname.'"',
    'comment = "'.$tb['Comment'].'"',
    'dt = now()'
    ));
    //查询修改前数据信息
    $rs = $db->select(0, 1, $tbname, '*', 'and tbid = '.$tbid);
    $keys = array_keys($rs);
    $values = array_values($rs);
    $this->primaryid = $returnid;
    $this->tbid = $tbid;
    $this->tbname = $tbname;
    $this->keys = $keys;
    $this->values = $values;
    }
    public function updateEnd(){
    global $db;
    //查询字段注释
    $db->query('show full columns from '.$this->tbname);
    $tb = $db->fetchAll();
    foreach($tb as $v){
    $commentArray[$v['Field']] = $v['Comment'];
    }
    //查询修改后数据信息
    $rs = $db->select(0, 1, $this->tbname, '*', 'and tbid = '.$this->tbid);
    $currentvalues = array_values($rs);
    //前后信息进行比较
    for($i = 0; $i < count($currentvalues); $i++){
    if($this->values[$i] !== $currentvalues[$i]){
    $db->insert(0, 0, 'tb_log_content', array(
    'logid = '.$this->primaryid,
    'tbkey = "'.$this->keys[$i].'"',
    'tbvalue = "'.$this->values[$i].'"',
    'currenttbvalue = "'.$currentvalues[$i].'"',
    'comment = "'.$commentArray[$this->keys[$i]].'"'
    ));
    }
    }
    }
    public function delete($tbid, $tbname){
    global $db;
    //查询表注释
    $db->query('show table status where name = "'.$tbname.'"');
    $tb = $db->fetch();
    //插入日志主表
    $returnid = $db->insert(0, 2, 'tb_log', array(
    'adminid = '.$_SESSION['admin']['id'],
    'type = 3',
    'tableid = '.$tbid,
    'tablename = "'.$tbname.'"',
    'comment = "'.$tb['Comment'].'"',
    'dt = now()'
    ));
    //查询字段注释
    $db->query('show full columns from '.$tbname);
    $tb = $db->fetchAll();
    foreach($tb as $v){
    $commentArray[$v['Field']] = $v['Comment'];
    }
    //查询所有字段信息,插入日志从表
    $rs = $db->select(0, 1, $tbname, '*', 'and tbid = '.$tbid);
    $keys = array_keys($rs);
    $values = array_values($rs);
    for($i = 0; $i < count($keys); $i++){
    $db->insert(0, 0, 'tb_log_content', array(
    'logid = '.$returnid,
    'tbkey = "'.$keys[$i].'"',
    'tbvalue = "'.$values[$i].'"',
    'comment = "'.$commentArray[$keys[$i]].'"'
    ));
    }
    }
    }

      使用前,需要引入数据库操作类,这是我之前写的一份,可参考《全新的数据库操作类(仅适用)》。

      引入之后,就可以开始使用了。

      select

    $log->insert(82, 'tb_member');

      update

    $log->updateStart(82, 'tb_member');
    //中间放更新操作代码
    $log->updateEnd();

      delete

    $log->delete(82, 'tb_member');

      可以看到,一共只需要两个参数即可,分别是表ID(主键)和表名称。

      另外需要强调一点,表注释和字段注释一定要完整,因为记录的信息包含注释,目的就是为了查阅的时候能清楚哪个字段是干什么用的。

      下面就看下成品吧

      最后把表结构分享下,一共2张表,一张主表一张从表,主表记录操作表及操作人等信息,从表记录操作的表字段信息。

    -- ----------------------------
    -- Table structure for `tb_log`
    -- ----------------------------
    CREATE TABLE `tb_log` (
    `tbid` bigint(20) NOT NULL AUTO_INCREMENT,
    `adminid` bigint(20) DEFAULT NULL COMMENT '管理员id',
    `type` tinyint(4) DEFAULT '1' COMMENT '操作类型:1新增2修改3删除',
    `tableid` bigint(20) DEFAULT NULL,
    `tablename` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '表名',
    `comment` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
    `dt` datetime DEFAULT NULL,
    PRIMARY KEY (`tbid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

    -- ----------------------------
    -- Table structure for `tb_log_content`
    -- ----------------------------
    CREATE TABLE `tb_log_content` (
    `tbid` bigint(20) NOT NULL AUTO_INCREMENT,
    `logid` bigint(20) DEFAULT NULL,
    `tbkey` longtext COLLATE utf8_unicode_ci,
    `tbvalue` longtext COLLATE utf8_unicode_ci,
    `currenttbvalue` longtext COLLATE utf8_unicode_ci,
    `comment` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
    PRIMARY KEY (`tbid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

    转载请注明本文地址:浅谈管理系统操作日志设计(附操作日志类)
    展开全文
  • syslog日志系统——日志采集

    万次阅读 2018-11-08 14:00:17
    客户端埋点就是在客户系统植入日志发送的代码,可以是前端页面、app界面、后端服务等,把需要的日志信息发送到指定的日志采集接口。 日志的发送应该采用异步方式,这样不会对客户系统代码的执行造成影响。 日志采集 ...
  • 日志系统之HBase日志存储设计优化

    万次阅读 2015-06-13 15:08:27
    本文探讨了基于HBase的日志存储原先自建索引存在的问题,展开分析了rowKey优化、索引优化等相关的优化策略。
  • 日志监控告警系统设计与实现

    万次阅读 多人点赞 2017-06-13 17:02:23
    日志监控告警系统 基于的日志进行监控,监控需要一定规则,对触发监控规则的日志信息进行告警,告警的方式,是短信和邮件。 log4j---->error,info,debug 应用程序程序的日志 error级别 TimeOutException 角标...
  • 略论并行处理系统日志设计

    千次阅读 2016-02-19 00:15:45
    作者:朱金灿来源:http://blog.csdn.net/clever101 一般来说桌面软件以单机单进程的方式运行,在调试程序时可以方便地...下面谈谈如何设计日志可以方便地定位错误。 首先是日志文件的命名,最初的命名是采用软件名字
  • FLASH日志文件系统设计

    千次阅读 2013-08-26 12:59:05
    大家都知道,目前主要流利的日志文件系统有JFFS,YAFFS等,这些都是目前在Linux中应用较多的日志文件系统。前期在做嵌入式方面的开发工作时,发现原来同事使用FLASH存储数据时使用了非常多的全局变量来保存FLASH的...
  • 日志系统设计

    万次阅读 2007-11-10 09:37:00
    一、重要性 日志系统在整个系统架构中的重要性可以称得上基础的基础,但是这一点,都容易被大多数人所忽视。因为日志在很多人看来只是printf。在系统运行期间,是很难step by step的,所以只能根据系统的运行轨迹来...
  • 系统日志方案设计

    千次阅读 2018-10-02 17:11:32
    前后端交互系统 前端感知异常与不感知异常的区分有多重方法:不同的异常类或者相同的类,不同的错误码区间等等; 有多种交互形式的开放系统
  • 游戏日志系统设计与实现

    千次阅读 2017-12-05 13:15:54
    游戏临近上线,需要做一个日志系统,记录玩家的行为,用途如下: 监控玩家状态变化,如账号登记,角色创建,上线下线,充值等; 分析玩家行为,如金币钻石消耗在什么系统上了,主要参与了哪些活动和玩法; 帮助...
  • 比如说一个教师登录后台对学生成绩的增删改都要记录下来是哪个教师什么时间对哪个学生执行了什么操作,求大神指点一下思路,和数据库表的搭建,谢谢
  • 最近这段时间在设计和实现日志系统,在整个日志系统系统中Zookeeper的作用非常重要——它用于协调各个分布式组件并提供必要的配置信息和元数据。这篇文章主要分享一下Zookeeper的使用场景。这里主要涉及到Zookeeper...
  • 系统操作日志设计(二)

    千次阅读 2010-07-20 18:43:00
    上一篇《系统操作日志设计》,已基本介绍了为什么要系统操作日志设计系统操作日志部分内容,如不清楚系统操作日志的请点这里。 :)  通了解《系统操作日志设计》,已基本明确我们不能通过clone的方式来做...
  • 日志系统设计模式

    万次阅读 2012-01-06 17:49:31
    从事服务器程序开发的工程师们,几乎不可避免地需要使用到日志系统(Logging System)。...这些开源的日志系统,几乎都使用到相同的设计模式,不同之处在于实现语言、实现方法,以及附加的一些额外功能。今天,我想
  • 每个软件都有自己的日志系统,每种语言都有自己的日志框架/模块,随着互联网和大数据的蓬勃发展,分布式的日志系统,以及日志分析系统也应用的越来越广泛,越来越成熟。这里讨论的日志设计,主要关注日志的内容,而...
  • 文章目录目录日志结构的文件系统日志文件系统 日志结构的文件系统 技术的改变会给当前的文件系统带来压力。这种情况下,CPU 会变得越来越快,磁盘会变得越来越大并且越来越便宜(但不会越来越快)。内存容量也是以...
  • QNX 系统日志设计

    千次阅读 2014-05-13 10:43:48
     QNX系统日志进行统一管理。具体包括:约定日志的级别,日志导出方式,日志的保存目录,日志的输出格式。  通过集中管理,有效方便异常定位和故障分析。 1.2适用平台 软件环境:QNX CAR2 1.3 ...
  • APP系统报错日志反馈机制设计

    千次阅读 2016-04-12 15:16:07
    APP日志调取与服务器的交互设计APP日志调取接口设计接口约定接口返回说明 参数 参数类型 说明 code Integer 含义类似http协议返回码,200代表成功 message String 返回消息,如果code为异常,则返回消息是...
  • 中小型WEB系统权限日志数据表设计

    千次阅读 2014-11-20 20:36:49
    中小型WEB系统权限日志数据表设计
  • 用户登录 日志设计

    万次阅读 2016-10-25 16:31:56
    设计: 脚本: USE [master] GO CREATE TABLE [dbo].[LogLoginOn]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [InputLoginName] [varchar](50) NULL, [ClientIP] [varchar](15) NULL, [MemberId] [bigint]
  • 业务应用系统的业务操作日志设计

    千次阅读 2020-02-22 16:03:34
    日志信息应包含如下内容: 1.操作时间 2.系统设备的主机名与IP地址(即被访问的服务器) 3.操作源IP(即访问者IP) 4.访问的业务名称 5.操作方式(增删改查) 6.操作结果(成功,失败) ...
  • 预写日志(WAL,Write-Ahead Log)将每次状态更新抽象为一个命令并追加写入一个日志中,这个日志只追加写入,也就是顺序写入,所以 IO 会很快。相比于更新存储的数据结构并且更新落盘这个随机 IO 操作,写入速度更快...
  • 分布式日志系统

    千次阅读 2016-01-29 10:31:48
    为什么需要分布式日志系统 分布式日志系统架构 我们的分布式日志系统设计--埋点部分
  • 1、系统采用B/S架构,要求能够记录客户端的任何事件,比如单击了某个按钮或者链接; 2、要求能够记录用户每次操作时后台代码使用到的SQL和参数,比如添加数据时的SQL语句和具体的Parameter; 3、将1和2串联或者合并...
  • Windows CE系统日志设计

    千次阅读 2008-10-09 13:29:00
    在这方面,最常见的手段显然就是系统日志了。嵌入式系统由定制的硬件平台、定制的驱动程序、定制的系统组件,以及定制的应用程序构成。这么多定制的组件凑在一起,要在一个比较短的时间内把他们凑在一起,配合良好...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 401,967
精华内容 160,786
关键字:

怎么设计系统的登录日志