zoukankan      html  css  js  c++  java
  • 提高日志质量的 5 大技巧

    近期涌现出各种各样能帮助你理解日志的新工具。有相似 Scribe、Logstash 这样的开源项目。也有相似 Splunk 的预付费工具。还有托管服务如 SumoLogic 和 PaperTrail。

    这些工具的共同点是对日志数据进行清洗,在大量日志中提取一些更有价值的文件。

    提高日志质量的五大技巧

    但有一件事这些工具却爱莫能助,由于它们全然依赖你实际投入的日志数据。而怎样保证数据的质量和数量则须要用户自行完毕。因此。在关键时刻,假设你须要基于部分或者遗漏日志做代码调试时,事情可能会变得非常棘手。

    为了降低这样的情况发生。在这里分享五个建议,在你记录日志时最好能铭记于心:

    1. 你好。我的(线程)名字是

    正如 Ringo,线程名称这个属性是 Java 中最被低估的方法之中的一个。其原因是线程名称大部分是描写叙述性的。然而问题相同出如今这里。相似人们自己。起名时一般会被赋予一定的意义。而在多线程日志中。线程名相同挥着关键作用。通常情况下,大多数日志框架会记录当前所调用的线程名称。可悲的是,我们一般会看到 http-nio-8080-exec-3 这样的名字。简单地由线程池或容器进行分配。

    出于某种原因,我们曾不止一次地听过这样的误解——线程名称是不可变的。

    与之相反。在日志中,线程名称占领基本主要地位,你应该确保能正确使用。比方将它与详细情境结合起来。比如 Servlet 的名字、任务相关,或者一些动态语境如用户或消息 ID。

    这样的话,代码接口应该是这样:

    Thread.currentThread().setName(ProcessTask.class.getName() + “: “+ message.getID);

    更先进的版本号将被载入到当前线程的线程局部变量,配置 log appender,并自己主动将其加入到日志条目。

    当多个线程写入server日志,但你须要集中在单一线程上时。这将会非常实用。

    假设你在一个分布式 /SOA 环境下执行,更能看到它得天独厚的优势。

    2. 分布式的标识符

    在 SOA 或消息驱动的架构,任务执行非常可能跨多台机器。

    当处理这样的环境下的故障时。连接相关机器和它们的状态将是了解详细情况的关键。大多数日志分析器会将这些日志信息分组,假设你为它们提供了唯一标识。它们便能够作为实际日志消息的一部分。

    从设计的角度出发。这意味着,从进入系统到操作完毕,每个入站操作应该有其唯一的 ID 相应。请注意。一个持久的标识符,如用户 ID 可能不是一个好容器。

    在记录日志文件的过程中,用户可能有多个操作,这将使得隔离特定流更加困难。

    UUIDs 可能是个不错的选择。它的值能够被载入到实际线程名称或者作为 TLS-thread 的局部储存器。

    3. 不要使用文本+驱动器,不要日志+循环

    非常多时候。你会看到一段代码在紧密的循环中执行。并执行相应的日志操作。基本假设是,该代码执行的次数是有限的。

    非常可能执行情况非常良好。

    可是当代码得到意外输入时,循环可能并不会中断。

    在这样的情况下,你不仅仅是处理一个无限循环「尽管这样已经非常糟糕了」。你正在处理的代码正将无限量的数据写到磁盘或网络。

    在单机场景中它可能会造成一台server崩溃。而在分布式场景中,被影响的则是整个集群。

    因此假设可能,不要在紧密循环中记录日志。

    捕获错误时,这一点尤其如此。

    以下这个样例。记录了一个 while 循环中的异常:

        void read() {
    while (hasNext()) {
    try {
    readData();
    } catch {Exception e) {
    // this isn’t recommend
    logger.error(“error reading data“, e);
    }
    }
    }
    

    假设 readData 抛出异常,而 hasNext 返回值为 true,这里将会写入无限量的日志数据。

    要解决问题的方法是确保不会记录这一切:

    void read() {
    int exceptionsThrown = 0;
    while (hasNext()) {
    try {
    readData();
    } catch {Exception e) {
    if (exceptionsThrown < THRESHOLD) {
    logger.error(“error reading data", e);
    exceptionsThrown++;
    } else {
    // Now the error won’t choke the system.
    }
    }
    }
    }

    还有一种方法是从循环中移除日志记录。并保存第一/最后一个异常对象并在其它地方记录。

    4. 未捕获的处理程序

    Westeros 有最后一道防御墙,而你有 Thread.uncaughtExceptionHandler。因此,尽量使用它们。假设没有安装这些处理程序。在异常抛出时,你仅仅能获得非常少有价值的上下文,同一时候你也无法控制在结束之前你已经将其记录。并确定记录的位置。

    请注意,即使在未捕获的异常处理程序。看起来你没有不论什么办法訪问线程中(已终止)的不论什么变量,你仍然能够获得实际线程对象的引用。

    假设你坚持# 1步,你仍然会得到一个有意义的thread.getName()值可记录。

    5. 捕获外部调用

    每当调用一个外部的 API, JVM 异常的几率将大大添加。

    这包含 Web 服务、 HTTP、 DB、 文件系统、操作系统和不论什么其它 JNI 调用。认真对待每个调用,由于它随时会爆炸 「它非常有可能发生在相同的点」。

    大多数情况下。外部 API 故障的原因是意外输入,日志中对其记录是修复代码的关键。

    在这一点上。你能够选择不记录错误,仅仅是抛出异常也能够。在这样的情况下。仅仅要收集到调用的相关參数。并将其解析为异常错误信息。

    仅仅要确保异常被捕获并记录在更高级别的堆栈调用就可以。

    try {
    return s3client.generatePresignedUrl(request);
    } catch (Exception e) {
    String err = String.format(“Error generating request: %s bucket: %s key: %s. method: %s", request, bucket, path, method);
    log.error(err, e); //you can also throw a nested exception here with err instead.
    }

    原文链接:5 Techniques to Improve Your Server Logging

    本文系 OneAPM project师编译整理。OneAPM 是中国基础软件领域的新兴领军企业。能帮助企业用户和开发人员轻松实现:缓慢的程序代码和 SQL 语句的实时抓取。想阅读很多其它技术文章,请訪问 OneAPM 官方博客

  • 相关阅读:
    PHP语言 -- 数据访问,连接数据库
    PHP语言 -- 面向对象和面向过程的区别
    (转)10条PHP编程习惯助你找工作
    PHP语言 -- 面向对象
    PHP语言 -- 数组常用函数
    jquery 与javascript关系 ①取元素 ②操作内容 ③操作属性 ④操作 样式 ⑤ 事件 点击变色
    PDO:: 数据访问抽象层 ? :
    查询一张表进行添加删除修改
    图片轮播,复制即用,安全快捷!
    会话控制
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5166171.html
Copyright © 2011-2022 走看看