面向“运营”编程,不考虑运营成本的编码都是耍流氓!

 今天下午,系统运营群里反映问题。我们查看生产日志排查问题时,发现有大文本日志不停在刷屏,严重干扰了我们对问题的定位。

面向“运营”编程,不考虑运营成本的编码都是耍流氓!

 

大日志刷屏现(wèn)象(tí)由来已久,生产环境每天都在打印海量的log,日志文件动辄10G或20G。这些大文本通常是一些api接口签名串、数据加密串、图片文件base64串/hex串、从db或rpc接口拿到的list序列化串。

我们做任何事情,其实是要考虑成本的。生产排障尤其衡量时间成本。长时间定位不到原因,无法及时反馈和修复,小问题也可能会升(yǎn)级(biàn)为生产事故。

因此,我们在日常编码时,不要忽视这些细节。对于记日志,有必要考虑目标对象是否会输出一大段很长很长的文本。如果是,那么,就要做处理。

 

举个例子,下面两段代码,一个是springmvc接口,程序打印获取到的请求参数。一个是程序在调用外部API时,调用前后打印数据报文。这两块的通信报文均涉及到大字段,就要对其做处理。

@RequestMapping(value = "/common.do", method = RequestMethod.POST)
public void doBusiness(@RequestBody String reqJson, HttpServletRequest request, HttpServletResponse response) throws IOException {
    log.info("商户API前置请求,请求参数={}", StringUtil.abbrLongJSONString(reqJson));
    ....
}

 

logger.info("OCR识别请求地址:{},参数:{}", listAuthUrl , StringUtil.abbrLongJSONString(json));

Response response = FastHttpClient.
        post().
        addHeader("Content-Type", "application/json").
        body(json).
        url(listAuthUrl.get(0).getCode()).
        build().
        execute();

String result = response.body().string();
logger.info("OCR识别返回:" + result);

小改动,大受益!

上面reqJson和json都是包含了长文本的json串。那么,对于这种情况,怎么处理呢?

简单粗暴的方式,是直接利用subString截取指定长度的子串。弊端是可能会舍掉必要的信息,反而不利于生产排障。

另一种方式,则是将其中特定的大文本进行截取。如下StringUtil方法可供参考。 

/**
 * 截取json字符串中的大文本
 * @param jsonStr 含有特长value的JSON字符串
 * @return
 */
public static String cutLongJSONString(String jsonStr) {
    String[] split = jsonStr.split("\"");
    System.out.println(split.length);
    for (int i = 0; i < split.length; i++) {
        if (split[i].length() > 100) {
            split[i] = cutLongString(split[i], 128);
        }
    }
    return String.join("\"", split);
}

/**
 * 截取大文本字符串。
 * 本方法会包含原串的长度。如果不关注,则可直接使用{@link org.apache.commons.lang3.StringUtils#abbreviate(String, int)}或其重载方法
 * @param longString
 * @param length
 * @return
 */
public static String cutLongString(String longString, int length) {
    if(StringUtils.isBlank(longString)){
        return "";
    }
    StringBuilder sb=new StringBuilder();

    if (longString.length()>length){
        sb.append(longString, 0, length).append("...(length=").append(longString.length()).append(")");
        return sb.toString();
    }
    return longString;

}
上一篇:C语言利用time进行计时的问题和解决方案


下一篇:实验2-2-9 计算火车运行时间 (15 分)