客户端日志打印规范

eMPrint打印监控v7.5部署与自研采集脚本实战 打印监控是Windows打印架构中通过Spooler、打印处理器和端口监视器截获打印作业元数据的技术,核心在于稳定记录用户、文档、页数等审计信息。其原理是挂钩打印链路,从作业流转中提取字段并落库,技术价值在于实现成本核算与行为审计。典型应用于企业内网打印成本分摊、安全合规审计等场景。本文以eMPrint v7.5为例,详解C/S架构部署、数据库配置、客户端验证,并给出基于PowerShell事件订阅的自研采集脚本,涵盖作业ID去重、成本映射表设计及老包避坑清单,帮助运维和开发者快速复现打印监控核心逻辑。 阅读详情

日志的作用

还原故障发生的现场

由于终端设备的碎片化问题,以及用户行为的不可预知性,产品功能上线前的测试阶段通常无法覆盖所有的意外情况。

当线上问题发生时,日志是否能提供足够多的信息来还原用户当时的场景和行为,以快速定位问题的原因,减少无谓的争执和甩锅,就显得尤为重要了。

怎样打印日志

日志级别

  • Verbose: 最详尽的log,任何内容都会输出。

  • DEBUG(调试):仅在开发期间有用的调试信息。

    主要集中在开发/测试阶段使用,输出的日志内容及形式可以根据开发人员的实际调试需要来调整,灵活度较大,一般会包含参数信息/流程信息/返回值信息等内容。

    特别要注意的是,该级别的日志不能被带到生产环境,建议在封装的日志工具类API中加上当前是否是调试模式的判断。

  • INFO(信息):常规使用情况的预期日志信息。

        用于记录具体的业务行为信息,需要有选择地使用,只输出对结果有实际意义的内容,避免          日志输出量过大,造成设备存储空间不足。一般作为默认的输出级别。

  • WARN(警告):尚未引发严重错误的潜在问题信息。

        涉及的通常是可提前预知并且影响范围可控的问题,一般不影响业务流程的正常执行,包括          但不限于参数缺失/参数错误/任务超时等情况。对该级别的日志,要求对于问题发生时的上下          文信息要尽可能详尽地记录下来,以便事后的日志分析。

  • ERROR(错误):已经引发严重错误的问题信息。

        涉及的通常是不可预知的并且影响范围较广的异常或错误,可能会导致应用崩溃,或者严重          阻塞业务流程正常执行,需要人工及时干预。对该级别的日志,除了要记录问题发生时的上          下文信息,还要包括完整的异常堆栈信息,以便快速定位问题发生的地方并及时修复。

日志级别示例——登录流程

  1. 首先假设我们的登录模块包含三种登录方式,分别是验证码登录、密码登录以及第三方平台登录,我们可以为不同的登录方式定义不同的TAG:
    // 父模块-登录
    public static final String TAG_LOGIN = "login";
    // 子模块-验证码登录
    public static final String TAG_LOGIN_IDENTIFYING_CODE = "login_identifying_code";
    // 子模块-密码登录
    public static final String TAG_LOGIN_PASSWORD = "login_password";
    // 子模块-第三方平台登录
    public static final String TAG_LOGIN_THIRD_PARTY = "login_third_party";
  2. 假设用户选择了验证码登录,输入了手机号码之后点击「获取验证码」按钮,此时需要请求获取验证码接口,并将按钮置为不可用,然后开始计时,超过一分钟后才将按钮恢复为可用,允许重新获取验证码。在开始计时之前不允许用户重复点击按钮,以免重复发起请求。

  3. 为了验证防止重复获取验证码和计时按钮恢复可用的代码逻辑是否生效,我们可以使用验证码登录的TAG,分别打印以下DEBUG级别的日志,验证流程是否如预期执行:
     

    LogUtil.d(TAG_LOGIN_IDENTIFYING_CODE, "处于重复点击判断时间区间,返回不处理")
    ...
    LogUtil.d(TAG_LOGIN_IDENTIFYING_CODE, "开始计时,按钮不可用");
    ...
    LogUtil.d(TAG_LOGIN_IDENTIFYING_CODE, "当前剩余秒数:" + second);
    ...
    LogUtil.d(TAG_LOGIN_IDENTIFYING_CODE, "计时结束,按钮恢复可用");
  4. 假设用户正常收到了验证码短信,并且输入了验证码后成功登陆,我们需要将过程中的具体的业务行为用INFO级别打印出来,以便后期日志分析时可以还原用户的行为轨迹以及有故障发生时的现场信息:
    LogUtil.i(TAG_LOGIN_IDENTIFYING_CODE, "请求获取验证码接口, phone:" + phone);
    ...
    LogUtil.i(TAG_LOGIN_IDENTIFYING_CODE, "请求获取验证码接口成功, response: " + response.toString());
    ...
    LogUtil.i(TAG_LOGIN_IDENTIFYING_CODE, "请求验证码登录接口, phone:" + phone + ", identifyingCode: " + identifyingCode);
    ...
    LogUtil.i(TAG_LOGIN_IDENTIFYING_CODE, "请求验证码登录接口成功, response: " + response.toString());
    ...
    LogUtil.i(TAG_LOGIN, "开始同步用户配置...");
    ...
    LogUtil.i(TAG_LOGIN, "开始同步消息通知...");
    ...
  5. 当偶现获取验证码超时的情况,虽然用户可以通过再次点击「获取验证码」按钮来重新获取,但是仍要将该情况记录到WARN级别的日志,并提供当时的上下文信息,以便后期统计出现此情况的频率,从而寻找可以优化的空间。
        String msg = new StringBuilder("获取验证码接口超时:")
                .append("countryCode").append(countryCode)
                .append("phone:").append(phone)
                .append("time:").append(DateUtil.format(System.currentTimeMillis()))
                .append("networkAvailable:").append(NetworkUtil.isNetworkAvailable(getContext()))
                .append("networkType:").append(NetworkUtil.getNetworkType(getContext()));
        LogUtil.w(TAG_LOGIN_IDENTIFYING_CODE, msg);

而当「获取验证码」接口不可用,用户登录流程受阻时,我们则要在接口请求失败回调方法中用ERROR级别打印出接口返回的错误码和错误信息,或者抛出的异常堆栈,以协助快速定位问题的原因并及时修复:

    @Override
    public void onFailure(Response response, IOException e) {
        if(response != null) {
            LogUtil.e(TAG_LOGIN_IDENTIFYING_CODE, "获取验证码接口请求失败,code: " + response.getCode() + ", msg: " + response.getMsg());
        } else {
            LogUtil.e(TAG_LOGIN_IDENTIFYING_CODE, "获取验证码接口请求失败", e);
        }
    }

日志规范

1.把控日志级别,严禁出现日志信息与日志级别不符的情况

不同的日志级别代表不同的日志重要程度,乱用日志级别将对排查的重要日志信息产生严重干扰。

// 反例:仅仅出于红色更显眼的原因,用ERROR级别打印调试信息
LogUtil.e(TAG, "Send a Msg")

2.合理使用TAG,以便分析时能快速过滤出指定日志

这里建议的TAG命名方式是按不同模块粒度划分、根据从属关系从大到小进行排列、模块名间以下划线分隔来命名,这样做的结果是可以更细致地查看不同粒度下的模块功能是否正常执行。

但要注意Android旧版本系统对logcat的TAG长度支持最长只有23个字符长度,建议使用合理且易懂的单词缩写,且尽量不超过三个模块层级。
 

比如以下两个TAG分别代表的是:

  • msgserv_ws_keepalive——消息接入服务/WebSocket模块/心跳保活功能
  • msgserv_ws_msgqueue——消息接入服务/WebSocket模块/消息队列功能

如果我只想关注心跳保活功能,我可以筛选完整的msgserv_ws_keepalive。而如果我想关注整个WebSocket模块的各项功能是否都运行正常,我可以筛选msgserv_ws。

// 正例:合理的TAG命名与使用
public static final String TAG = "msgserv_ws_keepalive";
...
LogUtil.i(TAG, "Received a pong frame, do nothing")

// 反例:以开发者名字为TAG的无意义命名
LogUtil.i("zhangsan", "onResume()")

// 反例:出于方便省略TAG
LogUtil.i("onPause()")

3.确保重要信息的完整,避免打印无效的日志

大量无效的日志不仅占用了设备的存储空间,更为获取真正有效的日志增加了干扰度,不利于快速定位和解决问题。为此,在打印日志之前请先思考:打印该日志的目的是什么?该日志是否真的有助于解决问题?

// 正例:抛出异常时打印异常堆栈信息
LogUtil.e(TAG, "Websocket connection was closed", e)

// 正例:问题发生时输出相关上下文信息
LogUtil.w(TAG, "Request failed with code: " + code);

// 反例:冗余日志——频繁下载进度回调打印干扰正常的日志打印
LogUtil.d(TAG, "Current download progress: " + progress)

// 反例:无效日志——缺少描述失败原因的返回码及描述
LogUtil.w("Download failed")

// 反例:意义不明的日志—为了验证流程而输出无意义的数字
LogUtil.d(TAG, "1")
LogUtil.d(TAG, "2")
LogUtil.d(TAG, "3")

4.力求日志内容描述简洁、清晰,又不影响可读性

// 正例:只取出关心的字段,描述其代表含义
String msg = new StringBuilder()
                .append("Request method:").append(request.method()).append("\n")
                .append("Request url:").append(request.url()).append("\n")
                .append("Request headers:").append(request.headers()).append("\n")
                .append("Request body:").append(request.body()).append("\n")
                .toString();
LogUtil.d(TAG, msg);

// 反例:直接打印请求实体,没有任何描述
LogUtil.i(TAG, request.toString())

5.用StringBuilder替代字符串拼接以处理参数较多的情形

采用Java语言开发时,使用字符串拼接会产生大量的String对象。当参数较多时,建议使用StringBuilder替代字符串拼接。

// 反例:以用字符串拼接输出日志
LogUtil.d(TAG, "Request method:" + request.method() + "\n"
        + "Request url:" + request.url() + "\n"
        + "Request headers:" + request.headers() + "\n"
        + "Request body:" + request.body());

6.包含敏感信息的日志内容需要脱敏,进行加密或不输出

平时打印的日志信息就要注意避免敏感信息的泄漏,如果有持久化到本地的操作要注意对日志内容进行加密。

7.打印Java语言定义的实体类必须重写toString()方法

// 正例:重写toString()方法,将实体类转换为JSON字符串
 @Override
 public String toString() {
    return JSONUtil.toJSON(this);
 }

8.避免因日志系统的引入,为应用增加不稳定性及额外的性能损耗

前面说过,日志本身并不能为功能带来增益,但日志打印毕竟也是编码的一部分,是编码就会有隐藏的稳定性风险和性能损耗,需要开发人员特别注意。最好能支持线上的降级手段,当出现了因日志造成的不良影响时,能停止打印某个级别的日志或直接不再打印日志。

// 反例:调用对象方法没有先进行非空判断,有隐藏的空指针异常风险
LogUtil.d(TAG, "Insert a new message:" + message.getId())

9.为日志文件制定合理的缓存时间,定时清理过期日志

建议以FIFO的清除策略,按日期顺序移除过期的日志文件,日志文件的最长缓存时间可根据产品的业务特性(比如是否有定期的周活动/月活动)来制定,可以选择在每次进行读写操作时才去检查日志文件是否过期,也可以专门建立一个后台任务定期检查过期日志文件并删除。
 

10.禁止直接使用第三方日志框架API,避免产生方案碎片化问题

规范建立之后,具体的日志相关处理可以交由第三方日志框架来实现,但为了保证方案的统一性和可替换性,需要基于外观模式,将打印日志的行为统一封装到作为外观角色的Log工具类,项目中统一使用Log工具类来打印日志。

什么时候该打日志?

1.产品核心业务的执行流程

这个自不必多说,产品核心业务的正常执行与否,决定着产品的最终质量,影响着公司在业界的口碑,并与实际收益挂钩。一方面需要全面的日志系统协助排查隐藏的技术漏洞,另一方面页需要在用户反馈问题时能用日志及时定位并快速给予答复。

2.跨端/跨应用/跨模块等的通信过程

常见的如外部接口请求与响应过程,内容主要包含影响接口请求成功率及数据展示的请求方法/请求头/请求参数/响应码/响应内容等,同理还有不同应用间的数据分享过程以及同一应用不同业务模块间的路由跳转过程等。

3.重要组件的初始启动配置

重要组件的初始启动配置会直接影响到应用的整体表现,我们可以通过打印组件的初始启动配置参数,验证是否存在由参数配置错误导致的异常。

4.长时间运行组件的行为/状态切换

长时间运行的组件受设备内存/电量/网络及用户操作等的影响比较大,需要通过日志实时关注其运行状态,确保其运行正常。

5.多个分支逻辑的判断

典型的情况就是代码中出现了多个条件分支,或者存在多个可供选择的策略类,需要确定是进入了哪个分支或策略,从而验证流程有没有按预期的情况执行。

6.对结果有影响的用户交互

比较有代表意义的就是搜索模块,用户通过输入框搜索/历史搜索词/热门搜索词/热搜榜单/联想词等模块都可以触发搜索行为,为了定位是由哪个模块触发的搜索,就有必要记录具体的用户交互行为。

7.调用大概率可能失败的方法时

当功能的实现依赖于外部条件的成立与否时,调用该功能的实现方法就有大概率可能失败,比如持久化数据需要有足够的存储空间,访问外部接口需要当前网络可用等。调用此类方法时我们通常需要验证外部条件是否成立,并提供条件不成立时的相应处理方式,适当的日志打印可以帮助我们验证流程是否合理且可行。

8.第三方SDK的调用过程

由于对第三方SDK提供方技术的不可把控,我们无法保证引入第三方SDK会不会对应用的稳定性造成影响。

为了避免这种情况,我们需要在对第三方SDK的API调用过程中,打印出第三方SDK提供给我们的信息,以便出现问题时能和第三方SDK提供方及时有效地沟通。

eMPrint v7.5 打印监控软件安装配置与故障排查实战指南 打印监控软件是用于审计打印行为、记录打印日志的应用程序,其核心原理是通过客户端采集打印任务信息并存储到数据库,再通过Web控制台进行查询和报表分析。这类工具的技术价值在于实现打印成本控制、安全审计和合规管理,广泛应用于企业办公网络、财务部门和打印服务商等场景。在部署过程中,环境依赖如.NET Framework版本、SQL Server实例配置和端口占用是常见故障点。本文以eMPrint v7.5为例,详细讲解从环境核对、安装配置到服务验证的完整流程,并针对服务启动失败、数据库连接错误等典型问题提供排查方案 阅读详情

相关推荐

Android客户端项目开发规范正式模板

Android客户端项目规范模板文档,含目录、代码规范、命名规范、日志规范、颜色布局资源规范等等,十分详细,公司正式模板

日志打印规范

日志打印规范

m0_38068812的博客 2244

手把手教你用Gazebo插件实现阿克曼底盘仿真(附Navigation2适配指南)

本文提供了一份完整的ROS2 Navigation2与Gazebo阿克曼底盘仿真全栈指南。从阿克曼运动学原理出发,详细讲解了如何构建URDF/SDF模型、集成gazebo_ros_ackermann_drive插件并进行PID调优,并重点阐述了如何深度适配Navigation2,包括配置Ackermann运动模型、调整规划器与恢复行为,最终实现从建图到自主导航的全流程仿真。

weixin_29310631的博客 398

这里有一份《客户端日志打印规范》呈现给您!

前言 「日志」对于客户端开发人员来讲,可以算是既熟悉又陌生了,它和代码注释、编程风格一样,本身不会为功能带来任何增益,也通常不会与你的KPI挂钩。但当有线上问题产生而你无从排查的时候,多少曾经感叹过“我当时要是在这里打印一条日志就好了”,由此可见打印日志的重要性。 但由于长期缺少一个合理的日志规范,导致滥用、乱用日志打印的现象层出不穷。为了解决这个痛点,今天,我们将以「为什么要打印日志」、「应该怎样打印日志?」以及「什么时候该打日志」三个方面为切入点,来拟定一份适合客户端开发中使用的《日志打印规范》。 WH

椎锋陷陈 1003

C++ 工程实践(9):数据抽象

陈硕 (giantchen_AT_gmail)http://blog.youkuaiyun.com/Solstice  http://weibo.com/giantchen陈硕关于 C++ 工程实践的系列文章: http://blog.youkuaiyun.com/Solstice/category/8

陈硕的Blog 1万+

CAD制图

CAD制图可以提高设计效率和准确性,并方便文档的存档和交流,是现代工程设计中不可或缺的一部分。·CAD三维开发是指使用计算机程序和工具来创建、编辑和操作三维模型、图形和设计的过程。它在工程、建筑、制造和游戏等领域广泛应用。CAD三维开发可能涉及到复杂的图形算法、性能优化、并行计算等方面的内容,因此需要深入学习和实践,以提高开发的效率和质量。

RZer的博客 1652

别再乱打日志了,这份日志规范,应有尽有,建议收藏!!

在程序中写日志是一件非常重要,但是很容易被开发人员忽视的地方。写好程序的日志可以帮助我们大大减轻后期维护压力。在实际的工作中,开发人员往往迫于巨大时间压力,而写日志又是一个非常繁琐的事情,往往没有引起足够的重视。开发人员应在一开始就养成良好的日志撰写习惯,并且应在实际的开发工作中为写日志预留足够的时间。

民工哥的博客 642

Multisim14.0仿真实战:从零搭建RS/JK触发器电路(附真值表+波形图)

本文通过Multisim 14.0软件,提供了从零搭建RS触发器和JK触发器电路的详细仿真实战教程。内容涵盖核心概念解析、电路搭建步骤、动态波形观测及真值表分析,重点探讨了RS触发器的非法状态问题以及JK触发器的四种工作模式,帮助读者直观理解时序逻辑电路的“记忆”功能与设计要点。

weixin_29175469的博客 275

日志:日志打印的15个好建议

日志打印的15个好建议

wimpykids的博客 1230

图像特征(一)——颜色特征(颜色直方图,颜色矩,颜色集,颜色聚合向量和颜色相关图)

本文主要是为了更好地理解图像特征,理解各方法的原理。转载请注明出处https://mp.youkuaiyun.com/console/editor/html/105090183 图像模式识别的一般步骤为:输入图像--图像预处理--特征提取--特征选择--图像分类--输出结果。 图像特征主要有:颜色特征、形状特征、纹理特征和空间关系特征。 本文主要介绍颜色特征,并给出matlab上实现的demo。 颜...

gloria_iris的博客 3万+

37、免驱动USB双目同步测距3D活体深度检测和RV1126结合V4L开发USB摄像头使用

基本思想:需要使用双目摄像头在rv1126上进行活体检测,然后将画面实时返回到桌面上,记录一下。第二步:刷机rv1126开发板系统和ssh远程连接,见参考目录。第一步:购买可见光的红外摄像头,见参考连接,在PC端测试可用。

sxj731533730 2621

日志 - 客户端及服务端写法

一、客户端 先来看一个日志类的实现方法,这个日志类也是代表着大多数客户端日志的主流写法: log.h: 1 #ifndef __LOG_H__ 2 #define __LOG_H__ 3 4 #include <stdio.h> 5 6 //#ifdef _ZYL_LOG_ 7 #define LogInfo(...) Log::GetI...

u014694510的博客 1641

Python中的join函数的用法

从语法、实例、应用三方面详尽地介绍join函数

阿黎逸阳的博客 2万+

如何通过日志在本地调试LangChain编写的程序?

LangSmith可以记录LangChain程序对LLM的调用,但它需要登陆LangSmith网站才能看到。有什么办法在本地就能看到详细的信息,以方便调试LangChain编写的程序吗?

cmoaciopm的专栏 884

SAP Fiori Launchpad 概述

SAP Fiori launchpad 是托管 SAP Fiori 应用程序的 shell,并为应用程序提供导航、个性化、嵌入式支持和应用程序配置等服务。SAP Fiori Launchpad 是移动和桌面设备上 SAP Fiori 应用程序的入口点。启动板显示带有图块的主页,其中可以显示实时状态指示器,例如打开的任务数量。每个图块代表用户可以启动的业务应用程序。这包括 SAP Business Suite 事务应用程序和 SAP Smart Business 分析应用程序。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 932

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

这份Java日志格式规范,拿走不谢!

点击上方关注 “终端研发部”设为“星标”,和你一起掌握更多数据库知识作者: 思影影思 来源: blog.youkuaiyun.com/lk142500/article/details/80424945Part1简介在程序中写日志是一件非常重要,但是很容易被开发人员忽视的地方。写好程序的日志可以帮助我们大大减轻后期维护压力。在实际的工作中,开发人员往往迫于巨大时间压力,而写日志又是一个...

这个时代,作为程序员可能要学习小程序 653

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

java日志规范

日志规范

dzl84394的专栏 2207

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

规范的打印日志

一、使用 slf4j 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一 实现方式统一使用:Logback 框架。 二、什么时候应该打日志 1️⃣当遇到问题的时候,只能通过 debug 功能来确定问题,应该考虑打日志,良好的系统,是可以通过日志进行问题定位的。 2️⃣当碰到 if…else 或者 switch 这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支。 3️⃣经常以功能为核心进行开发,应该在提交代码前,可以确定通过日志可以看到整个流程。 三、基本格式 1️⃣必须使用参数化信息的

ChineseSoftware的博客 1649

nodejs 日志规范

nodejs 日志规范 一般前端开发同学,对日志其实不太敏感,毕竟前端大多数情况下,不太关心日志。即使有,也可能调用一些第三方的统计,比如百度统计或者别的等。在 Node.js(下文中简称node) 推进过程中,也发现我们平常打日志太随意,该打的日志没有打,打的一些关键日志缺少必要上下文信息,导致在线上定位问题的时候很困难。 本文主要梳理了目前我们团队在nodejs开发中日志方面存在的问题,以及通...

weixin_34087301的博客 1373

Java日志系列——规范化日志

特别详细的系统运行完成信息,业务代码中,不要使用.(除非有特殊用意,否则请使用DEBUG级别替代)当我们打印日志时我们一定要使用参数化信息的方式进行打印而不要使用字符串拼接的方式,以避免内存占用。可以填写所有的想知道的相关信息(但不代表可以随便写,debug信息要有意义,最好有相关参数)影响到程序正常运行、当前请求正常运行的异常情况。这样更加有利于问题排查。

qq_51553982的博客 1042

Node.js + ELK 日志规范

nodejs 日志规范 一般前端开发同学,对日志其实不太敏感,毕竟前端大多数情况下,不太关心日志。即使有,也可能调用一些第三方的统计,比如百度统计或者别的等。在 Node.js(下文中简称node) 推进过程中,也发现我们平常打日志太随意,该打的日志没有打,打的一些关键日志缺少必要上下文信息,导致在线上定位问题的时候很困难。 本文主要梳理了目前我们团队在nodejs开发中日志方面存在的问题,以及通...

weixin_33772645的博客 582

日志规范与常用日志技巧

日志规范(使用slf4j日志框架) 1.什么时候应该打印日志 a.需要定位问题,使用日志替代debug b.遇到if else或者switch分支,首行打印,确定进入哪个分支 c.核心功能,需要通过日志看到整个流程 2.基本格式,参数化信息的方式 logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol)...

xxx_zha的博客 321

node 统一操作日志_nodejs 日志规范

nodejs 日志规范一般前端开发同学,对日志其实不太敏感,毕竟前端大多数情况下,不太关心日志。即使有,也可能调用一些第三方的统计,比如百度统计或者别的等。在 Node.js(下文中简称node) 推进过程中,也发现我们平常打日志太随意,该打的日志没有打,打的一些关键日志缺少必要上下文信息,导致在线上定位问题的时候很困难。本文主要梳理了目前我们团队在nodejs开发中日志方面存在的问题,以及通过统...

weixin_42546508的博客 1643

业务系统日志记录规范总结

业务系统日志记录规范 注意 应用中应该充满了日志记录信息,日志甚至比逻辑代码还要多; 集成 seluth ,开启消息链路;不开启日志上传,不集成 zipkin; 应该避免日志记录过程中出现异常,比如 log.debug(requst.getid) ,这条日志记录之前一定要判断 request 是否为空;日志记录中使用的信息一定时稳定的,提前准备好的,最好不是专门为此次日志记录专门准备的; 日志应...

来啊 快活啊 7796
上一篇: iOS播放/渲染/解析MIDI
下一篇: Android Unit Test
hunter800421
博客等级 码龄22年 60粉丝 97原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值