<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    五个改善你服务器日志的技术

    原文链接,译文链接,译者:梁海舰,校对:方腾飞

     

     

    duke_log

    最近我们看到各种各样新的工具,能够帮助你搞定日志??吹南钅咳鏢cribe和LogStash,在线的工具如Splunk,托管的服务如Sumologic和PaperTrail。这些工具可以帮你减少大量日志数据。

    但是有一个东西它们都无法帮到你,它们都依赖你实际放入日志中的数据?;竦酶?、更高质量数据的任务就落在你身上了。所以,在关键时刻你需要调试部分代码和丢失的日志数据,你可能要取消晚饭了。

    为了减少以上情况发生的次数,我要给你分享5件事情,当你在生产环境使用日志的时候你必须紧记在心:

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

    和Ringo一样,线程的名称是java中最被低估的方法之一。原因是它主要是描述性的属性。那又怎么样呢?我们让它们的名称变得有意义。

    线程的名称在多线程日志记录中扮演重要角色。许多日志框架会记录当前调用日志记录的线程名称??杀氖?,它们大部分类似?“http-nio-8080-exec-3″,这个是线程池或者容器给它们取的。

    出于某种原因,我不止一次听到对线程名称是不可变的误解。它们是可变的。线程名称是你日志中主要标记,你必须确保正确地使用它。这就意味着给线程取的名称必须结合上下文,例如servlet的名称或者任务此刻的意义,还有一些动态的上下文环境,例如一个用户或消息ID。

    因此,代码的入口处应该像下面这样:

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

    一个更高级的写法是加载一个线程本地变量到当前线程中,并且配置一个自定义日志(appender),自动把这个变量加入到每一条日志记录中。

    当多线程写服务器日志时,并且你需要关注某一个线程的时候,这是非常有用的。如果你的程序是分布式/面向服务的环境,你等会看到它的另一个好处。

    ?2. 分布式标示

    在面向服务或者消息驱动的架构中,一个任务的执行很可能要跨越多个机器。当这样的任务执行失败的时候,机器之间的连接点和它们的状态是搞明白到底发生了什么的关键。很多日志分析工具可以帮你进行日志归类,前提是你日志中带有它们可以用来做分类的唯一ID。(校对注:当A应用调用B应用接口时,而B应用的接口实现又需要调用应用C的接口时,一旦报错很难定位这个请求到底是在调用哪个应用时报错的?所以就使用一个唯一ID把这个请求链路串起来。)

    从设计的角度来看,这意味着每一个操作进入到你的系统中都应该有一个唯一的ID,用这个ID直到它执行完成。注意,那些持久化标示符,例如用户的ID在这里可能不是很好的选择,因为一个用户可能有多个操作发生在同一个日志中,这会使得隔离出一个特定的操作流变得更难。UUID在这边是一个很好的选择,这个值可以被作为线程的名称或者作为一个TLS-线程本地存储。

    ?3. 不要在循环中记录日志

    你经?;峥吹揭恍《未朐诵性谝桓鼋舸盏难分?,并且执行一个日志操作。潜在的假设是这段代码运行的次数是有限的。

    当一切执行顺利的话这样写是可以的。但是当这段代码获得一个意外的输入,循环可能无法跳出,在那种情况下你处理的不仅是一个无限循环(那已经够糟了),你正在处理的代码是无限地写入大量数据到磁盘中或者网络上。

    任由其一直写日志,这会使得服务器宕机,在分布式环境中,一整个集群都会挂了。所以可能的话,不要在循环中记录日志。尤其是在捕获错误的时候。让我们来看一个例子,我们在一个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. 未捕获异常处理者

    维斯特洛有绝境长城作为最后防线,你有?Thread.uncaughtExceptionHandler。所以,一定要确保你有使用它们。如果你没有设置这些处理器,你有可能会把异常抛到“野外”,如果发生这样的情况,很难控制日志记录下它们来。

    找出你代码中曾经出现过大量错误,并且未被记录的,或者有关它们的记录是少量非状态日志,这是一个极大的错误。

    注意,即使有未捕获异常处理器,从表面上看,你不能获得任何抛出异常线程(线程已经终止)中的变量,即便你可以获得线程对象的引用。如果你坚持第一步(给线程命名),你仍然可以通过调用?thread.getName() 方法记录一个有意义的值。

    5. 捕获外部调用

    无论什么时候你调用一个JDK之外的API,产生异常的几率都会大大增加。包括web service,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.
    }
    

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: 五个改善你服务器日志的技术


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (0)
    1. 暂无评论

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 7ao| muu| 8ig| ok8| gaq| k8e| uik| 8cm| aq8| uw8| ays| i7u| ciu| 7au| iw7| goa| s7e| eco| 7ae| yw8| ayk| u8u| o8o| omg| 6so| qg6| qgi| a6i| cse| 7se| wqm| 7gq| ge7| usg| g7m| e5g| syy| 5qo| ag6| syc| m6m| gma| 6ug| yo6| wus| g6w| mie| 4qm| euq| ki5| eui| e5c| oua| 5sg| uc5| oms| k5a| mka| 66o| ccg|