V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
BraveXaiver
V2EX  ›  Java

请问这条 Java 日志有更优雅的写法吗? log.error(String.format("Request to %s failed, uuid is %s.",uri, uuid),exception)

  •  
  •   BraveXaiver · 2023-10-24 23:03:56 +08:00 · 2772 次点击
    这是一个创建于 400 天前的主题,其中的信息可能已经有所发展或是发生改变。
    谢谢
    28 条回复    2023-10-26 10:07:22 +08:00
    stranchong
        1
    stranchong  
       2023-10-25 00:12:27 +08:00   ❤️ 5
    log.error("Request to {} failed, uuid is {}.", uri, uuid, exception)
    ==========
    这样异常堆栈也能打印出来
    iminto
        2
    iminto  
       2023-10-25 07:45:07 +08:00 via Android
    楼主写法给我看笑了。。。log 本来就有格式化功能,再格式化一次。。
    chendy
        3
    chendy  
       2023-10-25 08:10:07 +08:00
    其实如果是 100% 会打印出来的 log ,就不需要 format 了,直接 + 拼接就行
    想优雅点就按照经验先 new 一个长度差不多够用的 StringBuilder 避免扩容
    再优雅点就把这个 StringBuilder 扔 ThreadLocal 里缓存住(不一定有性能提升,可能 ThreadLocal 查找的时间都够把字符串拼出来了

    另外就是格式问题,楼主目前的格式只考虑给人看没考虑给机器解析,可以考虑调整一下,加一些特殊的分隔符,便于统一处理日志做数据分析和预警之类的
    cslive
        4
    cslive  
       2023-10-25 08:35:07 +08:00
    使用 slf4j, log.info("Request to {} failed,uuid is {}",uri,uuid)
    自带占位符
    N9f8Pmek6m8iRWYe
        5
    N9f8Pmek6m8iRWYe  
       2023-10-25 08:54:55 +08:00
    竟无语凝噎
    tramm
        6
    tramm  
       2023-10-25 09:26:08 +08:00
    楼主从 C 那边转过来的?
    ZhanLangCN
        7
    ZhanLangCN  
       2023-10-25 09:36:56 +08:00   ❤️ 1
    uuid 如果是追踪调用链用的话可以存在 MDC, 那日志直接就
    ZhanLangCN
        8
    ZhanLangCN  
       2023-10-25 09:37:11 +08:00
    log.error("Request to {} failed.", uri, exception)
    workingonescape
        9
    workingonescape  
       2023-10-25 09:38:18 +08:00
    绷不住了
    qcbf111
        10
    qcbf111  
       2023-10-25 09:39:52 +08:00   ❤️ 1
    log.error($"Request to {uri} failed, uuid is {uuid}.", exception)
    c#真的是越用越先进!
    tedzhou1221
        11
    tedzhou1221  
       2023-10-25 09:41:00 +08:00   ❤️ 4
    ```java
    public StringFormattedMessage(final Locale locale, final String messagePattern, final Object... arguments) {
    this.locale = locale;
    this.messagePattern = messagePattern;
    this.argArray = arguments;
    if (arguments != null && arguments.length > 0 && arguments[arguments.length - 1] instanceof Throwable) {
    this.throwable = (Throwable) arguments[arguments.length - 1];
    }
    }
    ```
    log4j 的 log.error 的实现中,找到 StringFormattedMessage 类,会判断最后一个是不是 Throwable 。

    所以调用
    这个接口也是可以打印异常堆栈
    public void error(String format, Object... arguments);

    调用这个也行
    public void error(String msg, Throwable t);
    liaopen123
        12
    liaopen123  
       2023-10-25 09:43:17 +08:00   ❤️ 1
    log.error(() -> String.format("Request to %s failed, uuid is %s.", uri, uuid), exception);
    chatgpt 回答的
    zhongjun96
        13
    zhongjun96  
       2023-10-25 09:52:36 +08:00   ❤️ 1
    请求入口设置 uuid 到 MDC ,logback 配置好,该请求所有日志都会带上 uuid 。更方便排查。
    iold
        14
    iold  
       2023-10-25 09:55:44 +08:00
    不怎么写 Java ,但是 idea 会提示你这写法可以优化吧??
    litchinn
        15
    litchinn  
       2023-10-25 10:02:38 +08:00
    /t/984299
    前两天不是就有帖子讨论过了吗,这个帖子还能回答为啥不能像你这样写
    chendy
        16
    chendy  
       2023-10-25 10:03:18 +08:00
    @iold 这种警告基本要 sonar lint 这种才会有,idea 本身没管到这一层
    tedzhou1221
        17
    tedzhou1221  
       2023-10-25 10:03:25 +08:00   ❤️ 1
    @iold #14
    我使用的 idea 2023.2.2 版本,没有这种提示。

    楼主的问题主要是:(个人猜测)
    看到 error 接口,以为只有这个才会打印异常堆栈, public void error(String msg, Throwable t);

    以为这个接口 public void error(String format, Object... arguments);

    没有 Throwable 作为入参,认为不会打印异常堆栈。


    包括我以前也是这样认为。同样很多年前也遇到过 log.error 不打印异常堆栈的情况。
    gongxuanzhang
        18
    gongxuanzhang  
       2023-10-25 10:13:54 +08:00
    是来钓鱼的吗。。。
    kaedei
        19
    kaedei  
       2023-10-25 10:23:13 +08:00
    @qcbf111 c#也不要这么写,每一次调用都会有额外的字符串分配。把前面$去掉,log 框架会帮你格式化的
    log.error(exception, "Request to {uri} failed, uuid is {uuid}.", uri, uuid);
    bk201
        20
    bk201  
       2023-10-25 10:25:29 +08:00
    %s 这个看了就头疼,不知道当初谁设计的这 api 写法
    qcbf111
        21
    qcbf111  
       2023-10-25 12:14:15 +08:00
    @kaedei 你可以看下反编译的代码,事实上 字符串模板不仅写着舒服,性能还算是任何语言最高的字符串拼接做法。在很老的版本做法简单本质就是,string.format("{} aa{}", uri, uuid)这样。
    而较新版本已经做到没有任何一次额外的临时分配了。
    julyclyde
        22
    julyclyde  
       2023-10-25 12:24:53 +08:00
    @stranchong 不明白。俩花括号怎么输出三个变量呢?
    BaseException
        23
    BaseException  
       2023-10-25 12:48:21 +08:00 via iPhone
    @julyclyde #22 第三个是 print 了 stacktrace ,上面有人贴了源码,throwable ,源码里用的 object... 对象数组的
    guoziq09
        24
    guoziq09  
       2023-10-25 14:20:03 +08:00
    @bk201 %s,%d,%l ,这些不是通用的 format 占位符吗?
    nothingistrue
        25
    nothingistrue  
       2023-10-25 14:51:28 +08:00
    @stranchong #1
    @iminto #2
    @cslive #4
    Slf4j 没有这种重载方式。

    @tedzhou1221 #11
    Log4j 的实现,不能代表 Slf4j 的接口定义,除非你明确用得是 Log4j 不是 Slf4j

    事实上来说,没有比楼主原来那个语句更优雅的了。当然,如果再极限追求性能,还是得改成 if(log.isErrorEnable()){ log.error ....}
    Richared
        26
    Richared  
       2023-10-25 15:37:03 +08:00
    代码怎么写不重要,因为你看的是日志,不是打印日志的代码,我习惯是每个链路加一个跟踪号。排查起来简单。
    Richared
        27
    Richared  
       2023-10-25 15:41:26 +08:00
    @Richared 补充一下,Slf4j void error(String var1, Throwable var2); 会自动格式化,输出堆栈信息,log.error("aa:{},bb{},id,data,e" 就可以了。当然你不确定你的日志框架是啥,可以自己写个 utils 。还是上边那句话,怎么写不重要。你就+拼问题也不大。保证日志输出标准,是给人看的就可以了。
    lleiwang
        28
    lleiwang  
       2023-10-26 10:07:22 +08:00
    @liaopen123 这 GTP 还怪好嘞,异步打印。。^_^
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4137 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 05:21 · PVG 13:21 · LAX 21:21 · JFK 00:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.