智能软件平台 XMagital 日志标准化规范

1. 引言

1.2 目的

本规范对运行在平台上的应用产生的运行日志和使用的日志框架提出了规范性要求。其输入是XMagital V1.0的需求规格要求及相关子系统架构设计。

1.3 预期读者

本文档的预期读者包括: XMagital 平台软件的管理人员、设计人员、开发人员、测试人员,在 XMagital 平台基础上进行应用软件产品开发的设计人员、开发人员、测试人员、工程实施人员和维护人员。

2 术语与缩略语

2.1 术语

本文使用的专业术语、自定义的词语、容易产生理解偏差的词语以及缩略语。

术语解释
平台一个公共的基础,在此基础上可以开发不同产品。平台是产品线开发的基础,它为衍生一个产品提供可共用和可重用的特性、设计元素(组件、代码功能)以及相关流程和工具。本文中所提及的平台即XMagital平台。 [GB/T37413-2019 数字化车间术语和定义]
应用Application,为应用软件(application software)的简称,指专为特定工程或特定生产场景编写的程序包,或本身也具有一定的通用性,但是通过XMagital应用开发框架编写的、并可以随时从系统摘除的软件包或模块(如签名软件,称量软件,或WMS接口程序等等)。
日志用来追踪和记录程序运行中的信息,用户可以用它来检查错误发生的原因。
日志框架一套能实现日志输出的工具包,提供了输出日志的API,日志框架具备以下能力:定制输出目标、定制输出格式、携带上下文信息、运行时选择性输出。
日志级别日志基于其重要性和严重程度分配到的一个级别。

3 设计约束

3.1 假设和依赖

  1. 平台支持的Linux系统:64位的 Linux5.X及以上,例如:Ubuntu 22.04 LTS Server;银河麒麟Kylin Server V10。

4. 概述

日志用来记录用户操作、系统运行状态等信息,是一个系统的重要组成部分。然而,由于日志通常不属于系统的核心功能,所以常常不被团队成员所重视。对于一些简单的小程序,可能并不需要在如何记录日志的问题上花费太多精力。但是对于作为基础平台为很多产品提供服务的后端程序,就必须要考虑如何依靠良好的日志来保证系统的可靠运行。

4.1 日志的作用

良好的日志可以帮助系统的开发和运维人员快速掌握以下信息:

  • 了解线上系统的运行状态。
  • 快速准确定位线上问题。
  • 发现系统瓶颈。
  • 预警系统潜在风险。
  • 挖掘产品最大价值。

4.2 日志的可读性

日志必须简明扼要,无冗余,摒弃掉无用信息,防止无用日志淹没重要信息。但能够从日志中得到所有需要的信息,努力做到仅凭日志就可以定位问题。要有明确的日志级别和不同级别日志的用途。日志格式要有统一的规范,包括记录的信息点以及各个信息点之间的分割符要统一。每一条日志应记录为一行,对于日志内容中有换行操作的,应计划处理为一行,否则日志收集之后将出现不易查看和不可解析的问题。

4.3 日志的磁盘占用

日志文件不宜过大,过大的日志文件对于日志监控,问题定位等都会带来不便。因此需要进行日志文件的切分,切割方式应该根据日志量来决定,原则就是方便开发或运维人员能快速查找日志,比如单个日志文件大小不超过一个设定值,或者按照天来分割。

为了防止日志文件将整个磁盘空间占满,需要定期对日志文件进行删除。例如,在日志文件达到一个设定个数时,需要将多余的日志文件删除。

5. 日志规范

本规范对应用的日志文件记录提出了规范性要求,明确各应用日志文件保存位置、日志打印格式、单个日志文件大小、日志文件最多留存个数、日志文件保留天数、日志文件是否压缩和磁盘IO约束。日志文件保留个数、日志文件保留天数至少需要满足其中一个。涉及到的可配置参数,均需要在相应的配置文件中存在。

5.1 日志文件规范

5.1.1 存储位置

日志文件在本地目录中的存储位置示意图,如下图 1:

图片 1

图 1 日志文件存储位置示意图

日志文件保存在hsm-os/logs下,每个安装后的应用,均会在hsm-os/logs下生成一个以应用ID(应用配置文件里配置的应用ID)命名的子目录,其服务产生的运行日志文件均生成在该子目录下,支持多层级日志收集,其自定义文件夹下的日志也需不收集。

5.1.2 命名

日志文件命名按照应用ID、模块泛模块、时间和序号生成,各信息之间按照“-”分割,其中模块信息可选,格式为:泛模块-时间-序号.log,序号从1生成。

泛模块包括如下格式:

泛模块规则说明
应用ID[-模块]
模块
链路名HSM-IO链路调试日志
链路名-COMMHSM-IO链路通讯日志

例如:standard-app1-20230406-1.log、standard-app1-20230406-2.log

5.1.3 大小限制

单个日志文件大小推荐值为10M,需要将其设置为可配置参数,在写入日志信息时,若判断写入后日志文件大小超过限定值,则需要新建一个日志文件,将日志信息写入到新的文件中。

5.1.4 个数限制

各应用可配置留存日志文件个数,推荐个数为10,需要将其设置为可配置参数,每次只保留最新的10个日志文件,当产生第11个文件时,将第一个文件删除。

5.1.5 保存时间

各应用以自然天为单位,将超过设定时间的日志文件删除,文件保留天数推荐值为7天,将保留天数设置为可配置参数。

文件个数规范和文件保存时间规范最少选择一个规范来满足。

5.1.6 文件压缩规范

各应用可选择是否对日志文件进行压缩,默认不压缩。若选择是,则压缩时机设定为超过单个日志文件最大容量,只保留最新的1个文件不压缩,压缩采用tar.gz格式,如 ACS02-20230414-1.log文件,压缩后文件名为:ACS02-20230414-1.log.tar.gz,可将是否压缩设置为可配置参数。

5.2 日志级别规范

5.2.1 类型

日志级别设定为如下8种,严重程度依次降低:

FATAL类型:严重的错误,系统无法正常运行,如磁盘空间满等,常暗含系统或系统的组件崩溃。

ERROR类型:运行时出现的错误,系统可以继续运行,但是要尽快修改错误。错误的环境不一定会造成系统的崩溃,系统可以继续服务接下来的请求。

WARN类型:运行时出现的非错误性的异常信息、潜在异常信息、需要关注并且需要修复,此类异常不影响系统的正常运行,但产生的错误原因需要引起重视,这个级别预示了较小的问题。

IMPORT_INFO 类型: 运行时打印的重要信息(周期调用的勿用)(C++特有)。

INFO类型:运行时打印的关键点的操作信息,一般用于记录业务。这个级别的日志记录了系统日常运转中有意义的事件,若发生缺陷时,可根据记录的信息再现缺陷的路径进而分析产生缺陷的原因。

INTERFACE:运行时打印的接口信息,用于记录接口输入输出信息(C++特有)。
CTORDTOR:构造析构信息,导出类的构造析构函数中需要的输出信息(C++特有)。

DEBUG类型:运行时打印的调试信息,便于开发人员进行错误分析和修正,一般用于程序日志,关于程序操作(细粒度),不太关心业务操作(粗粒度)。

5.2.2 输出级别

图片 1

应用需要设定日志输出级别,以此设置运行后,控制台按照设定的日志级别输出日志信息。平台应用输出的日志级别默认设定为INFO类型,即要求INFO及以上级别的日志均会打印。将日志的输出级别设置为可配置参数,只有在调试阶段可将其设置为DEBUG级别。

5.3 日志格式规范

5.3.1 内容

日志打印的内容包括:日志级别、打印时间、上下文信息、日志详情。日志信息的输出支持可扩展,比如有些应用需要输出线程号、模块、方法名等信息,可在必输出信息后面进行追加。

日志级别打印时间上下文信息日志详情extend1extend2extend3
  • 日志级别:必输出项,可选值有FATAL、ERROR、WARN、IMPORT_INFO 、INFO、DEBUG、INTERFACE、CTORDTOR。
  • 打印时间:必输出项,精度精确到ms级,如:2023-02-01 09:21:28.101。
  • 上下文信息:必输出项,打印日志文件的代码行位置,包括所在文件路径和行数信息。
  • 日志详情:必输出项,打印日志的详情信息,详情信息一般是开发人员在开发过程中用以记录该条日志产生的原因。
  • 扩展信息:可选,各应用根据需要,可添加扩展信息。暂支持3个扩展信息项。

5.3.2 格式

格式的主要设定是各个信息之间的分隔符,分隔符的作用是对数据行中每个属性的数据进行定界,方便人员查看和解析。一个好的分隔符需要具备两点,其一是满足单符号性,单个的字符作为分隔符,使得各个信息之间界限分明,方便人员查看;其二是具备独特性,分隔符不会在各个日志内容中出现,使得日志解析时不会发生错误。

平台规定各个日志内容之间以“|”符号分隔,并规定日志详情中不允许出现“|”符号(强制要求)。

例如:INFO | 2023-02-01 09:21:28.101 | ../zerologtest/main.go:21 |日志详情 。

5.4 磁盘IO约束

在日志输出时,存在对磁盘IO频繁写入的操作,若不对其写入频率进行限制,会影响系统的整体性能,特对磁盘IO操作提出以下规范性要求:

  1. 按照日志级别分配日志输出,日志级别越高的日志输出应该越少。
  2. 原则上INFO及以上级别的日志每秒内输出条数不超过100条。
  3. 在毫秒级的周期性线程里避免周期性的打印重复的日志,例如:对于一个持续的异常条件,不要每周期都产生相同的错误或警告日志。

6 日志框架

6.1 Java日志框架

6.1.1 框架和版本号确立

日志框架采用Log4j2 2.5.9及以上版本

6.1.2 框架配置

6.1.2.1 新增log4j2日志依赖

在pom.xml中添加log4j2的依赖配置,配置信息如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>2.5.9</version>
</dependency>
6.1.2.2 排除默认依赖

在pom.xml中增加排除springboot的默认依赖,配置信息如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
        </exclusion>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>
6.1.2.3 配置信息
  • 日志相关的配置文件命名为:log4j2.properties,内容如下:
# 日志输入格式: 打印时间|日志级别|上下文信息|日志详情
appender.rolling.layout.pattern\=%-5level|%d{yyyy-MM-dd HH:mm:ss.SSS}|%thread %c{1.}(%line--%method)|%msg%n

# 日志自动打包以及命名
appender.rolling.filePattern\=./../logs/hsm-eng-flow-%d{yyyyMMdd}-%i.log

# 日志保存目录以及初始日志命名
appender.rolling.fileName\=../../logs/hsm-eng.log
# 日志自动打包文件限值
appender.rolling.policies.size.size\=10M

# 日志等级
rootLogger.level\=INFO

# 文件个数
appender.rolling.strategy.max\=10
  • 配置文件存放在resources目录下,相对位置如图所示:

图片 8

  • 配置文件示例:

6.1.3 使用介绍

根据前文引入的相关依赖,将log4j2.properties复制到resources目录下,springboot工程会自动识别配置并应用。

6.2 Go日志框架

使用go语言开发的项目需要遵守4.1日志文件规范、4.2日志级别规范、4.3日志格式规范,其中有关删除过期文件的规范遵守4.1.4个数限制规范,且日志文件不压缩。

6.2.1 框架和版本号确立

6.2.1.1 日志框架

日志框架采用第三方包:github.com/rs/zerolog v1.29.0。

6.2.1.2 文件操作依赖包

日志文件的生成、过期日志文件的删除等操作引入使用public中的logger包:包地址为:http://gitlab.hollysys.net/hsm-os/hsm-env/hsm-env-pub/hsm-env-pub-back-end.git  ,每个应用需添加此子模块到 ./public/下。*注:该地址位于开发环境中,外网不可访问。

6.2.2 框架配置

6.2.2.1 配置文件

配置文件中需要包含有关日志规范的相关属性,设计如下:

logger:

  #输出的日志级别

  level: 'INFO'

  #单个日志的文件大小(M)

  max\_size: 10

  #日志文件删除规则

  max\_number: 10

  filename: 'applint/applint.log'
6.2.2.2 结构体设置

设置配置文件对应的结构体类型,用于配置文件解析使用。

    // Log -.

    Log struct {

        Level   string \`env-required:"true" yaml:"level"  env:"LEVEL"\`

        MaxSize int    \`env-required:"true" yaml:"max\_size"  env:"MAX\_SIZE"\`

        MaxNumber int    \`env-required:"true" yaml:"max\_number"  env:"MAX\_NUMBER"\`

        Filename string    \`env-required:"true" yaml:"filename "  env:"FILENAME"\`

    }
6.2.2.3 初始化设置

设置了一个zerolog.Logger类型的日志变量,并进行输出级别和日期精度的初始化,输出级别为配置设置中的值,日期精度到毫秒,并设置日志输出位置为两个地方:os.Stdout和日志文件。

// 定义变量

var l zerolog.Logger

// New -.

func Init(logConf config.Log) {
    var ll zerolog.Level
    switch strings.ToLower(logConf.Level) {
    case "error":
        ll = zerolog.ErrorLevel
    case "warn":
        ll = zerolog.WarnLevel
    case "info":
        ll = zerolog.InfoLevel
    case "debug":
        ll = zerolog.DebugLevel
    default:
        ll = zerolog.InfoLevel
    }

    //全局变量设置:输出级别,时间精度(毫秒)

    zerolog.SetGlobalLevel(ll)
    zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
    skipFrameCount := 3
    logPath := filepath.Join("/usr/local/hsm-os", logConf.Filename)
    lumberjackLog := &lumberjack.Logger{
        Filename:   logPath, //日志文件名
        MaxSize:    logConf.MaxSize,       //单个日志文件的文件大小(MB)
        MaxBackups: logConf.MaxNumber,      //旧日志文件的数量,默认保留所有
        LocalTime:  true,    //是否启用本地时间,否则使用UTC时间
    }

    l = zerolog.
        New(zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "2006-01-02 15:04:05.000",Nocolor:true,PartsOrder:\[\]string{"level","time","caller","message"} },
            zerolog.ConsoleWriter{Out: &Jacklog{JackLog: lumberjackLog}, TimeFormat: "2006-01-02 15:04:05.000",Nocolor:true,PartsOrder:\[\]string{"level","time","caller","message"}})).
        With().
        Timestamp().
        CallerWithSkipFrameCount(zerolog.CallerSkipFrameCount + skipFrameCount).
        Logger()
}

设计五个日志打印方法,分别为打印Debug、Info、Warn、Error、Fatal级别的日志,Error方法接收的第一个参数为interface类型,可用于接收任何类型的参数,这样设计的目的是当程序中发生Error类型的错误时,可直接将此错误传入到Error方法中。

// Debug -.

func Debug(message string, args ...interface{}) {
    l.Debug().Msgf(message, args...)
}

// Info -.

func Info(message string, args ...interface{}) {
    l.Info().Msgf(message, args...)
}

// Warn -.

func Warn(message string, args ...interface{}) {
    l.Warn().Msgf(message, args...)
}

// Error -.

func Error(message interface{}, args ...interface{}) {
    switch msg := message.(type) {
    case error:
        l.Error().Msgf(msg.Error(), args...)
    case string:
        l.Error().Msgf(msg, args...)
    default:
        l.Error().Msgf(fmt.Sprintf("message %v has unknown type %v", message, msg), args...)
    }

}

// Fatal -.

func Fatal(message string, args ...interface{}) {
    l.Error().Msgf(message, args...)
    os.Exit(1)
}

6.2.3 使用介绍

  • 在需要打印的文件中,导入logger包:
Import "applint/pkg/logger"
  • 在启动时进行初始化
func Run(cfg \*config.Config) {
    // 初始化日志组件
logger.Init(cfg.Log)
}
  • 日志记录示例:
    err := httpServer.Shutdown()
    if err != nil {
        logger.Error("app - Run - httpServer.Shutdown: %s",err.Error())
        //logger.Error(err)
    }

    logger.Info("示范怎么打印日志")

6.3 C++日志框架

6.3.1 框架和版本号确立

日志框架采用ACE version 6.3.2 release版本

6.3.2 框架配置

6.3.2.1 配置文件
  • 日志配置文件内容如下:
\[LogServer\]

; 日志等级 0-FAIL 1-ERROR 2-WARNING 3-IMPORTINFORMATION  4-INFORMATION  5-INTERFACE  6-CTORDTOR  7-DEBUG

LogLevel = 4

; 每个日志文件/表格的最大容量(单位:MB,默认1M)

LogMaxSize = 10

;

; 日志压缩方式(1, 压缩 0,不压缩, 压缩时机为超过单个日志文件最大容量,只保留一个最新文件不压缩)

LogComPressType = 0

; 日志文件的最大存储时长(单位:天,默认7天,最小1天)

LogMaxRestoreDuration = 7

*   日志配置文件存放目录:./bin/ LogServerConfig/日志配置文件名.ini

6.3.3 使用介绍

  • 引用ace.lib或libACE.so;DBCommon.lib或libDBCommon.so动态库,并添加如下附加包含目录:

图片 6

图片 12

  • 使用时添加日志框架头文件#include “Common/DebugMsg/Debug_Msg.h”,采用如下方式输出日志。

图片 11

图片 13

6.4 Node.js日志框架

使用nodejs语言开发的项目需要遵守4.1日志文件规范、4.2日志级别规范、4.3日志格式规范,其中有关删除过期文件的规范遵守4.1.4个数限制规范,且日志文件不压缩。

6.4.1 框架和版本号确立

日志框架采用winston 3.8.2。使用nodejs版本v 16.19.1。

6.4.2 框架配置

  • 安装 Winston:在命令行中输入以下命令进行安装。
$ npm install winston winston-daily-rotate-file
  • 创建 Logger 配置文件logConfig.json
{
  "logLevel": "INFO",
  "logPath": "/hsm-os/logs/appname",
  "logFilename": "appname-%DATE%.log",
  "logDatePattern": "YYYYMMDD",
  "logMaxSize": "10m",
  "logMaxFiles": "10",
  "logZippedArchive": false
}
  • 创建 Logger 实例。

    示例如下

    import winston from "winston";
    import DailyRotateFile from "winston-daily-rotate-file";
    import { format } from "winston";
    const { combine, timestamp, printf } = format;
    const config = require("./logConfig.json");
    
    // 获取配置信息
    
    const {
      logLevel,
      logPath,
      logFilename,
      logDatePattern,
      logMaxSize,
      logMaxFiles,
      logZippedArchive,
      level
    } = config;
    
    const levels = {
      FATAL: 0,
      ERROR: 1,
      WARN: 2,
      IMPORT\_INFO: 3,
      INFO: 4,
      INTERFACE: 5,
      CTORDTOR: 6,
      DEBUG: 7
    
    }
    
    // 自定义日志格式
    
    const myFormat = printf(({ level, message, timestamp, filename, line }) \=> {
      return \`${level}|${timestamp}|${filename}:${line}|${message}\`;
    
    });
    
    // 创建 Logger 实例
    
    const winstonLogger = winston.createLogger({
      levels:levels, //定义日志级别
      level: logLevel, // 设置日志级别为 默认INFO
      format: combine(
        timestamp(), // 添加时间戳
        myFormat // 应用自定义格式
      ),
    
      transports: \[
    
        // 输出到文件的传输器
    
        new DailyRotateFile({
          level: logLevel,
          dirname: logPath, // 日志文件路径
          filename: logFilename, // 日志文件名格式
          datePattern: logDatePattern, // 日志文件名中的日期格式
          maxSize: logMaxSize, // 日志文件最大大小
          maxFiles: logMaxFiles, // 日志文件最多保留天数
          zippedArchive: logZippedArchive, // 是否对日志文件进行压缩
          auditFile:"audit.json"
        }),
    
        // 输出到控制台的传输器
    
        new winston.transports.Console({
          level: logLevel, // 日志级别为 debug
        }),
      \],
    });
    
    const logger: any = {};
    logger.log = (level: string, msg: string) \=> {
      const stack = new Error().stack?.split("\n");
      const \[, caller\] = stack?.\[2\]?.match(/at (.\*)/) || \[undefined\];
      const match = caller?.match(/\((.\*?):(\d+):(\d+)\)$/);
      const \[\_, filename, line, column\] = match || \["", "", "", ""\];
      winstonLogger.log(level, msg, { filename, line, column });
    
    };
    
    logger.info = (msg: string) \=> {
      const stack = new Error().stack?.split("\n");
      const \[, caller\] = stack?.\[2\]?.match(/at (.\*)/) || \[undefined\];
      const match = caller?.match(/\((.\*?):(\d+):(\d+)\)$/);
      const \[\_, filename, line, column\] = match || \["", "", "", ""\];
      winstonLogger.log("INFO", msg, { filename, line, column });
    };
    
    logger.warn = (msg: string) \=> {
      const stack = new Error().stack?.split("\n");
      const \[, caller\] = stack?.\[2\]?.match(/at (.\*)/) || \[undefined\];
      const match = caller?.match(/\((.\*?):(\d+):(\d+)\)$/);
      const \[\_, filename, line, column\] = match || \["", "", "", ""\];
      winstonLogger.log("WARN", msg, { filename, line, column });
    
    };
    
    logger.error = (msg: string) \=> {
      const stack = new Error().stack?.split("\n");
      const \[, caller\] = stack?.\[2\]?.match(/at (.\*)/) || \[undefined\];
      const match = caller?.match(/\((.\*?):(\d+):(\d+)\)$/);
      const \[\_, filename, line, column\] = match || \["", "", "", ""\];
      winstonLogger.log("ERROR", msg, { filename, line, column });
    };
    
    logger.debug = (msg: string) \=> {
      const stack = new Error().stack?.split("\n");
      const \[, caller\] = stack?.\[2\]?.match(/at (.\*)/) || \[undefined\];
      const match = caller?.match(/\((.\*?):(\d+):(\d+)\)$/);
      const \[\_, filename, line, column\] = match || \["", "", "", ""\];
      winstonLogger.log("DEBUG", msg, { filename, line, column });
    };
    
    // 导出日志模块
    
    export default logger;

6.4.3 使用介绍

  • 在需要打印的文件中,通过require方法导入logger模块
const logger = require('./path/to/logger'); // 导入 Logger 模块
  • 日志记录示例
// 记录日志

logger.log('info', 'Hello, Winston!');

logger.error('Oops, something went wrong!');

6.5 容器应用

若应用打成镜像进行容器化部署,需要将日志信息输出到控制台,打印格式需符合4.2日志级别规范和4.3日志格式格式,无需关注文件生成规范(基础运行环境会抓取打印在控制台的日志数据并按照日志文件规范进行文件写入)。

7 附:C++日志扩展功能

C++日志扩展功能采用日志服务来打印日志,日志文件的生成符合不符合第4章的日志规范的自定义文件夹,每天产生的日志存放在一个以当天日期命名的文件夹里,按照各个模块以及其不同的功能对日志文件进行更详细的划分存储,这些以天划分的文件存放在/usr/local/hsm-os/logs/应用ID目录下,这部分的日志不会被收集解析,若有相同的需求可参考以下配置和使用说明。

7.1 框架和版本号确立

日志框架沿用SCADA V4的日志服务,涉及到的三方库为:zeromq Version:4.1.14、OPC UA Stack Version: 1.4.2、OpenSSL Version: 1.0.1g

7.2 框架配置

7.2.1 日志配置文件

  • 日志配置文件内容如下:
\[LogServer\]

; 日志等级 0-FAIL 1-ERROR 2-WARNING 3-IMPORTINFORMATION  4-INFORMATION  5-INTERFACE  6-CTORDTOR  7-DEBUG

LogLevel = 4

; 每个日志文件/表格的最大容量(单位:MB,默认1M)

LogMaxSize = 10

;

; 日志压缩方式(1, 压缩 0,不压缩, 压缩时机为超过单个日志文件最大容量,只保留一个最新文件不压缩)

LogComPressType = 0

; 日志文件的最大存储时长(单位:天,默认7天,最小1天)

LogMaxRestoreDuration = 7
  • 日志配置文件存放目录:./bin/ LogServerConfig/日志配置文件名.ini

7.2.2 日志服务配置文件

  • 日志服务配置文件示例:

  • 日志服务配置文件存放目录:./bin/ LogServerConfig/日志服务配置文件名.ini

7.2.3 日志结构说明

  1. 日志目录结构:
  • 在../logs/应用ID目录下按照日期建立第一级子目录(如20171226 ),示例图如下:

图片 2

  • 示例说明:

ScadaServer:进程名目录

20171226:日期目录

FEP:固定为IO模块的链路通信日志目录

ScadaServer:ScadaServer模块的日志目录

PA:  组态的链路名称文件夹

PA或者PA_COMM:  驱动链路日志ACS02-20230414-0.log,驱动报文日志ACS02-COMM-20230414-0.log

  • 如有其它模块则会创建相应的目录(与ScadaServer/FEP目录平级)
  1. 日志文件说明

模块日志说明:DebugLog/进程名称/日期/ 模块名称/ 模块名称-日期-序号.log

链路调试日志说明:DebugLog/进程名称/日期/FEP / 链路名称/链路名-日期-序号.log

链路通信日志说明:DebugLog/进程名称/日期/FEP / 链路名称/链路名-COMM-日期-序号.log

7.3 使用介绍

7.3.1 日志宏接口

应用中有关日志的接口主要包括各个级别的日志打印接口和日志配置接口。

  1. 日志打印接口

首先介绍日志打印接口,其中相关的参数说明如下:M为模块名称或当前类名称,其中模块名称推荐为类名;X 为日志内容,日志内容最大为4096字节。Y为This指针,即当前类的指针 ,不使用时请设置为0;Z为LogNam,是Log文件名称的组成部分,也可省略,如果为中文的话,请使用GBK的编码格式,如果使用其他编码格式化,可能产生乱码。相关接口的具体详情如下:

  • 接口1:LOG_FATAL(M,X,Y)
  • 接口2:LOG_FATAL_EX(M,X,Y,Z)

用途:严重错误日志接口:影响系统正常运行的,配置加载失败,动态库加载失败,空指针等需要人工干预才能解决的错误。

  • 接口3:LOG_ERROR(M,X,Y)
  • 接口4:LOG_ERROR_EX (M,X,Y,Z)

用途:一般错误日志接口:网络切换、服务切换、接口调用失败、参数校验错误等逻辑错误。

  • 接口6:LOG_WARN(M,X,Y)
  • 接口7:LOG_WARN_EX (M,X,Y,Z)

用途:警告信息日志接口:不影响系统运行,部分数据无效,配置错误。

  • 接口8:LOG_ IMPORT_INFO(M,X,Y)
  • 接口9:LOG_ IMPORT_INFO_EX (M,X,Y,Z)

用途:重要信息日志接口:重要必须输出信息。

  • 接口10:LOG_INFO(M,X,Y)
  • 接口11:LOG_INFO_EX (M,X,Y,Z)

用途:一般信息日志接口:重要流程信息。

  • 接口12:LOG_INTERFACE(M,X,Y)
  • 接口13:LOG_INTERFACE_EX (M,X,Y,Z)

用途:接口信息日志接口:导出接口输入输出信息。

  • 接口14:LOG_CTORDTOR(M,X,Y)
  • 接口15:LOG_CTORDTOR_EX (M,X,Y,Z)

用途:构造析构信息日志接口:导出类的构造析构函数中需要输出。

  • 接口16:LOG_DEBUG(M,X,Y)
  • 接口17:LOG_DEBUG_EX (M,X,Y,Z)

用途:其他需要输出的调试用信息。

  1. 日志配置接口

日志文件相关的配置,可以通过接口来灵活设置,其中参数说明如下:X为日志文件个数,设置为0,代表不限制;Y:为日志文件大小,单位为 M;D为日志文件保存天数;C为日志压缩的方式,0代表不压缩,1按照文件压缩;Z:为日志文件名,即日志模块名路径名。

  • 接口18:LOG_FILESET_EX(X,Y,D,C,Z)

用途:使用接口来灵活配置日志参数。

7.3.2 使用示例

  • 引用DBCommon.lib或libDBCommon.so动态库。

图片 19

  • 使用时添加接口函数头文件src\00.Pub\00.include\Common\LogProxy\LogProxy.h

图片 10