美文网首页
java日志规范及模板

java日志规范及模板

作者: 伊丽莎白菜 | 来源:发表于2023-01-30 16:29 被阅读0次

    日志规约

    1. 【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架(如SLF4J)中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理 方式统一。

    2. 【强制】日志文件至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。对于当天日志,以 “应用名.log”来保存,保存在/{统一目录}/logs/{应用名}目录下,过往日志文件名带有yyyy-MM-dd格式日期。

    3. 【强制】在日志输出时,字符串变量之间的拼接使用占位符的方式。 说明:因为 String 字符串的拼接会使用 StringBuilder 的 append() 方式,有一定的性能损耗。使用占位符仅是替换动 作,可以有效提升性能。
      正例logger.debug("Processing trade with id : {} and symbol : {}", id, symbol);

    4. 【强制】生产环境禁止使用 System.out 或 System.err 输出或使用 e.printStackTrace() 打印异常堆栈。

    5. 【强制】异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字 throws 往上抛出。

      注意:一定要携带最后一个参数e(java.lang.Throwable),禁止仅打印 e.getMessage()

      正例logger.error("inputParams: {}", 各类参数或者对象 toString(), e);

    6. 【推荐】谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时 删除这些观察日志。

    日志格式

    统一的日志格式不仅对用户友好,也有利于日志收集等运维平台做进一步处理。因此,日志格式必须在系统内达成共识。

    一条完整的日志由系统自动捕获的公共信息(由日志模板定义),和开发者手动记录的日志信息拼接组成,即一条日志=公共信息+日志体

    格式定义

    以下日志格式配置适用于log4j2与logback,对应xml中的pattern配置:

    |%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%X{traceId}|%X{spanId}|${appName}|%t|%C|%M|%L|%m%n
    

    分段释义:

    |日期时间|日志级别|链路ID|链路跨度ID|应用名词|线程名称|类名|方法名|行号|日志体
    

    其中traceId与spanId是链路追踪参数,需要基于链路追踪框架生成,可以结合链路追踪系统使用;appName由应用系统定义。

    日志样例

    • INFO(DEBUG,WARN等)日志

      |2023-01-30 14:15:26.220|INFO |trace0|span1|iot.spaceFence|http-nio-8080-exec-1|com.iot.spaceFence.controller.IotAlarmFenceController|findOne|31|正常日志:0e178fbb5907676c38959eb7bf1c5f2b
      
    • ERROR日志

      |2023-01-30 14:15:26.221|ERROR|trace1|span1|iot.spaceFence|http-nio-8080-exec-1|com.iot.spaceFence.controller.IotAlarmFenceController|findOne|35|异常日志: 0e178fbb5907676c38959eb7bf1c5f2b
      java.lang.RuntimeException: 测试异常
        at com.iot.spaceFence.controller.IotAlarmFenceController.findOne(IotAlarmFenceController.java:33) [classes/:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_351]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_351]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_351]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_351]
      

    ELK配置

    filebeat

    每台服务器运行一个filebeat即可,负责采集日志并发送到logstash:

    注意tags表示所属项目,最终会对应到elasticsearch的不同索引。

    #=========================== Agent name =============================
    name: 100.127.6.231
    #=========================== Filebeat inputs =============================
    
    filebeat.inputs:
    
    - type: log
    
      # Change to true to enable this input configuration.
      enabled: true
    
      # Paths that should be crawled and fetched. Glob based paths.
      paths:
        - /apps/logs/iot/*/app.log
    
      # The regexp Pattern that has to be matched. The example pattern matches all lines starting with [
      multiline.pattern: ^\|
    
      # Defines if the pattern set under pattern should be negated or not. Default is false.
      multiline.negate: true
    
      # Match can be set to "after" or "before". It is used to define if lines should be append to a pattern
      # that was (not) matched before or after or as long as a pattern is not matched based on negate.
      # Note: After is the equivalent to previous and before is the equivalent to to next in Logstash
      multiline.match: after
      tags: ['iot']
    - type: log
      enabled: true
      paths:
        - /apps/logs/lms/lms-*.log
      multiline.pattern: ^\|
      multiline.negate: true
      multiline.match: after
      tags: ['lms']
    
    #============================= Filebeat modules ===============================
    
    filebeat.config.modules:
      # Glob pattern for configuration loading
      path: ${path.config}/modules.d/*.yml
    
      # Set to true to enable config reloading
      reload.enabled: false
    
    #==================== Elasticsearch template setting ==========================
    
    setup.template.settings:
      index.number_of_shards: 1
    
    #============================== Dashboards =====================================
    setup.kibana:
    
    #----------------------------- Logstash output --------------------------------
    output.logstash:
      # The Logstash hosts
      hosts: ["192.168.3.39:5044","192.168.3.214:5044"]
    
    #================================ Processors =====================================
    
    # Configure processors to enhance or manipulate events generated by the beat.
    
    processors:
      - add_host_metadata: ~
      - add_cloud_metadata: ~
      - add_docker_metadata: ~
      - add_kubernetes_metadata: ~
    

    logstash

    # Sample Logstash configuration for creating a simple
    # Beats -> Logstash -> Elasticsearch pipeline.
    
    input {
      beats {
        port => 5044
      }
    }
    
    filter {
        if "iot" in [tags] {
            mutate { add_field => { "[@metadata][target_index]" => "iot-%{+YYYY.MM.dd}" } }
        } else if "lms" in [tags] {
            mutate { add_field => { "[@metadata][target_index]" => "lms-%{+YYYY.MM.dd}" } }
        } else {
            mutate { add_field => { "[@metadata][target_index]" => "default-%{+YYYY.MM.dd}" } }
        }
        
        grok {
            match => { "message" => "\|%{DATA:datetime}\|%{NOTSPACE:level}\s?\|%{DATA:traceId}\|%{DATA:spanId}\|%{DATA:app}\|%{NOTSPACE:thread}\|%{NOTSPACE:class}\|%{NOTSPACE:method}\|%{INT:line}\|(?<content>(.|\n)*)" }
            # 移除一些不太有用的默认字段
            remove_field => ["[agent][ephemeral_id]","[agent][id]","[agent][id]","[agent][type]","[agent][version]","[host][mac]","[host][ip]","[host][id]","[host][architecture]","[host][containerized]","[host][os][codename]","[host][os][family]","[host][os][name]","[host][os][kernel]","[ecs][version]"]
        }
    }
    
    output {
      elasticsearch {
        hosts => ["http://192.168.0.184:9200","http://192.168.0.182:9200","http://192.168.0.59:9200"]
        index => "%{[@metadata][target_index]}"
        user => "elastic"
        password => "*********"
      }
    }
    
    

    参考文献

    相关文章

      网友评论

          本文标题:java日志规范及模板

          本文链接:https://www.haomeiwen.com/subject/oqgmhdtx.html