架构设计 - 日志管理接口设计

在后端代码中,日志无处不在,自己设计自己的一套日志管理代码,提供一套好用的日志接口将大大方便代码的开发。

其中在日志管理代码的编写中,主要有以下难点:

1.数目不确定的入参函数编写

2.日志权限控制

3.日志输出形式。

接口设计:

1.提供三类日志打印形式:1)控制台打印信息,类似printf的接口封装

            2)函数追踪接口,打印当前代码的文件名,函数名及行,以及一些设定的输出参数

            3)日志打印函数,提供打印级别控制,且打印内容输出到日志文件中

2.提供日志级别控制:1)在打印日志时提供当前日志级别,代码依据级别进行控制打印

          2)日志打印级别控制暂时使用配置文件,后续可以通过通信接口进行实时修改

下面附上代码实现:DMLogManager.h

 1 //=============================================================================
 2 /*
 3 *  File: DMLogManager.h
 4 *
 5 *  Author: bing
 6 *
 7 *  Date: 2016-09-07
 8 *
 9 *  Version: v2.0
10 *
11 *  Github/Mail: https://github.com/binchen-china    <[email protected]>
12 *
13 *  Note:
14 */
15 //=============================================================================
16
17 #pragma once
18 #include "DMaker.h"
19
20 enum LOG_LEVEL
21 {
22     DM_ERROR = 0x0001,
23     DM_WARNING  = 0x0010,
24     DM_INFO = 0x0100,
25     DM_DEBUG = 0x1000
26 };
27
28 class DMLogManager
29 {
30 public:
31     DMLogManager();
32
33     ~DMLogManager();
34
35     void print_log(const DM_CHAR* fmt, ...);
36
37     void trace_log(string file, string func, DM_INT line, const DM_CHAR* fmt, ...);
38
39     void write_log(DM_INT log_level, string file, string func, DM_INT line, const DM_CHAR* fmt, ...);
40
41 private:
42     void init();
43
44     void get_log_config();
45
46     inline void open_log_file();
47
48     inline void close_log_file();
49
50     void set_log_level();
51
52 private:
53     FILE* _log_file;
54     string _log_name;
55     string _log_level;
56     DM_INT _log_mask;
57 };
58
59 typedef ACE_Singleton<DMLogManager, ACE_Thread_Mutex> DMLogMgr;
60
61 //console output without code info
62 #define DM_PRINT(LOG_FMT,args...) DMLogMgr::instance()->print_log(LOG_FMT,##args)
63 //console output with code info
64 #define DM_TRACE(LOG_FMT,args...) DMLogMgr::instance()->trace_log(__FILE__,__FUNCTION__,__LINE__,LOG_FMT,##args)
65 //write logs into log file
66 #define DM_LOG(LOG_LEVEL,LOG_FMT,args...) DMLogMgr::instance()->write_log(LOG_LEVEL,__FILE__,__FUNCTION__,__LINE__,LOG_FMT,##args)

DMLogManager.cpp

#include "DMLogManager.h"

DMLogManager::DMLogManager():_log_mask(0)
{
    init();
}

DMLogManager::~DMLogManager()
{

}

void DMLogManager::init()
{
    get_log_config();
    set_log_level();
}

void DMLogManager::get_log_config()
{
    _log_name = DMJsonCfg::instance()->GetItemString("service_info", "service_name");
    _log_level = DMJsonCfg::instance()->GetItemString("service_info", "log_level");
    _log_name.append(".log");
}

inline  void DMLogManager::open_log_file()
{
    _log_file = fopen(_log_name.c_str(), "a");
    if (nullptr == _log_file)
    {
        return;
    }
}

inline  void DMLogManager::close_log_file()
{
    fclose(_log_file);
}

void DMLogManager::set_log_level()
{
    if ("DEBUG" == _log_level)
    {
        _log_mask = 0x1111;
    }
    else if ("INFO" == _log_level)
    {
        _log_mask = 0x0111;
    }
    else if ("WARNING" == _log_level)
    {
        _log_mask = 0x0011;
    }
    else if ("ERROR" == _log_level)
    {
        _log_mask = 0x0001;
    }
}

void DMLogManager::print_log(const DM_CHAR* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);

    string log_info = fmt;
    ACE_OS::vfprintf(stdout, fmt, ap);  

    va_end (ap);
}

void DMLogManager::trace_log(string file, string func, DM_INT line, const DM_CHAR* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);

    ACE_OS::printf("[DM_TRACE][%s][%s][%d]:",file.c_str(), func.c_str(), line);
    string log_info = fmt;
    ACE_OS::vfprintf(stdout, fmt, ap);  

    va_end (ap);
}

void DMLogManager::write_log(DM_INT log_level, string file, string func, DM_INT line, const DM_CHAR* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);

    open_log_file();

    switch (log_level)
    {
        case DM_DEBUG:
        {
            if (DM_DEBUG & _log_mask)
            {
                ACE_OS::fprintf(_log_file, "[DM_DEBUG][%s][%s][%d]:",file.c_str(), func.c_str(), line);
                ACE_OS::vfprintf(_log_file, fmt, ap);
            }
            break;
        }
        case DM_INFO:
        {
            if (DM_INFO & _log_mask)
            {
                ACE_OS::fprintf(_log_file, "[DM_INFO][%s][%s][%d]:",file.c_str(), func.c_str(), line);
                ACE_OS::vfprintf(_log_file, fmt, ap);
            }
            break;
        }
        case DM_WARNING:
        {
            if (DM_WARNING & _log_mask)
            {
                ACE_OS::fprintf(_log_file, "[DM_WARNING][%s][%s][%d]:",file.c_str(), func.c_str(), line);
                ACE_OS::vfprintf(_log_file, fmt, ap);
            }
            break;
        }
        case DM_ERROR:
        {
            if (DM_ERROR & _log_mask)
            {
                ACE_OS::fprintf(_log_file, "[DM_ERROR][%s][%s][%d]:",file.c_str(), func.c_str(), line);
                ACE_OS::vfprintf(_log_file, fmt, ap);
            }
            break;
        }
    }

    close_log_file();
    va_end (ap);
}

更多技术信息请关注github:https://github.com/binchen-china

时间: 2024-10-03 15:33:33

架构设计 - 日志管理接口设计的相关文章

设备资源管理系统-日志管理

设备资源管理系统-日志管理 数据库设计 日志管理在项目中的作用 * 记录系统的错误日志,便于管理员去维护和管理系统的安全.性能. * 在登录系统的操作中,也要添加日志,便于管理员查看当前系统的使用情况. * 使用日志可以记录当前数据的新增.修改.删除由哪些用户操作. * 使用者:admin/admin 超级管理员和公司领导 实现日志管理的方法: * 1.使用log4j,维护系统日志 * 2.数据库表的形式,维护系统日志 添加日志 操作 1.在系统XXXXXAction层中调用,传递2个参数 *

Spring AOP日志管理

AOP的介绍 AOP(Aspect-OrientedProgramming,面向方面编程) AOP的几个概念 1.切面(Aspect):切面就是一个关注点的模块化,如事务管理.日志管理.权限管理等: 2.连接点(Joinpoint):程序执行时的某个特定的点,在Spring中就是一个方法的执行: 3.通知(Advice):通知就是在切面的某个连接点上执行的操作,也就是事务管理.日志管理等: 4.切入点(Pointcut):切入点就是描述某一类选定的连接点,也就是指定某一类要织入通知的方法: 5.

[转]App架构设计经验谈:接口的设计

原文地址:http://developer.51cto.com/art/201601/503767.htm App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉. 安全机制的设计 现在,大部分App的接口都采用RESTful架构,RESTFul最重要的一个设计原则就是,客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验证信息.实现上,大部分都采用token的认证方式,一般流程是: 用户用密码登录成

HTTP接口设计及日志打印

任何一个稍大的项目中,web接口的使用是少不了的,不管C2S还是S2S都会依赖于http的接口.下面对这一两年来写过各种Http接口做一个总结. 大致可以分为以下五点: 1.使用requestId来记录追踪请求 2.只在body中接收json字符串的请求,避免产生编码问题 3.返回适当的数据结构 4.打印有用的日志 5.提供可阅读的文档 第一点,使用requestId来记录追踪请求.如果你这么做了,当你查找定位问题的时候就会知道这是一个多么有用的规则.这里可以强制请求中用UUID作为reques

架构中的设计原则之接口分离原则(ISP) - 《java开发技术-在架构中体验设计模式和算法之美》

接口分离原则 接口分离原则的核心思想是:不应该强迫客户程序依赖它们不需要使用的方法.英文缩写ISP,即Interface Segregation Principle.其实接口分离原则的意思就是:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该 把所有的操作都封装到一个接口中. 这里的"接口"指的不仅仅是通过interface关键字定义的接口,接口分为如下两种. 对象接口.java中声明的一个类,通过new关键字产生的一个实例,它是对一个类型的事物的描述,这也是一种

图书管理销售系统概要分析,接口设计部分

 负责人:皮皮周(20160401085)               国字号(20160401105)   接口设计 1.用户接口 网站部分:本图书销售系统不包含与网络的交互联通功能. 客户端部分:简洁大方的图形用户界面,包含登陆窗口,以及登陆成功后显示的用户主界面窗口.主界面由各个系统功能子模块构成,要求清晰.美观.登陆界面包含不同角色的切换登陆功能,适用于管理员以及用户等不同身份权限的角色进行登陆,要求简洁.有序.  2.外部接口 数据存储:本系统设计数据的存储和处理,通过ADO.NET与

微服务架构设计基础之领域驱动设计

DDD早于微服务「出道」十年,这两个「忘年交」的软件设计哲学是如何相爱相杀的? 背景 微服务现在可以说是软件研发领域无人不提的话题,然而业界流行的对比多数都是所谓的Monolithic(单体应用),而大量的系统在十几年前都已经是以SOA(面向服务架构)为基础的分布式系统了,那么微服务作为新的架构标准与SOA有什么差异点呢?其本质区别在于设计原理,微服务是去中心化设计,SOA是「集成」形成中心设计: 另外,笔者认为以下几点并不是微服务和SOA的区别点: CI/CD:持续集成.持续部署本身与敏捷.D

微服务设计关键的难点:微服务架构的数据库是如何设计的?

单独的数据库: 微服务设计的一个关键是数据库设计,基本原则是每个服务都有自己单独的数据库,而且只有微服务本身可以访问这个数据库.它是基于下面三个原因. 优化服务接口:微服务之间的接口越小越好,最好只有服务调用接口(RPC或消息),没有其他接口.如果微服务不能独享自己的数据库,那么数据库也变成了接口的一部分,这大大拓展了接口范围. 错误诊断:生产环境中的错误大部分都是和数据库有关的,要么是数据出了问题,要么是数据库的使用方式出了问题.当你不能完全控制数据库的访问时,会有各种各样的错误发生.它可能是

微信小程序的Web API接口设计及常见接口实现

微信小程序给我们提供了一个很好的开发平台,可以用于展现各种数据和实现丰富的功能,通过小程序的请求Web API 平台获取JSON数据后,可以在小程序界面上进行数据的动态展示.在数据的关键 一环中,我们设计和编写Web API平台是非常重要的,通过这个我们可以实现数据的集中控制和管理,本篇随笔介绍基于Asp.NET MVC的Web API接口层的设计和常见接口代码的展示,以便展示我们常规Web API接口层的接口代码设计.参数的处理等内容. 1.Web API整体性的架构设计 我们整体性的架构设计