请问这条 Java 日志有更优雅的写法吗? log.error(String.format("Request to %s failed, uuid is %s.",uri, uuid),exception) - V2EX
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 3410 次点击
    这是一个创建于 789 天前的主题,其中的信息可能已经有所发展或是发生改变。
    谢谢
    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 回答的
    qjbcnrs
        13
    qjbcnrs  
       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 ....}
    Cruzz
        26
    Cruzz  
       2023-10-25 15:37:03 +08:00
    代码怎么写不重要,因为你看的是日志,不是打印日志的代码,我习惯是每个链路加一个跟踪号。排查起来简单。
    Cruzz
        27
    Cruzz  
       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     Solana     2633 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 00:30 PVG 08:30 LAX 16:30 JFK 19:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86