对于错误码的设计,不同的开发团队有不同的风格习惯。本文分享阿里娱乐技术专家张彤对错误码的看法,希望从错误码使用的不同场景的讨论中得到合理的错误码规范,得到日志的错误码标准和外部的错误码标准传播。1前言在工作中,接触过很多外部接口,包括:支付宝、微信支付、微博开发平台、阿里云等。每个公司都有不同的错误代码样式。有的用纯数字,有的用纯英文,还有的用字母和数字的组合。我也接触过很多内部系统,错误代码设计也各不相同。错误码的输出路径面向日志输出服务,最终输出到日志。域内服务之间,比如大麦电商系统之间同时进行,最终目的是输出到日志。对于外部传输从域内到域外从服务器到前端OpenAPI错误代码不同内部域之间错误代码的使用使用错误代码配置来监控市场。通过日志排查问题,快速定位问题。后端服务之间的错误代码传输。前端显示的错误信息/OpenAPI。本文希望从错误码使用的不同场景的讨论中得到合理的错误码规范,得到面向日志的错误码标准和对外传输的错误码标准。PS:本文所有引用来自阿里巴巴《Java 开发手册》,以下简称?。2.什么是错误代码?错误代码要回答的最基本问题是,谁有错?错误在哪里?那么一个错误可以表明谁有错,错误在哪里是一个好的错误代码?答案显然是否定的,这个标准太基础了。一个好的错误代码必须能够快速知道错误的来源。好的错误代码必须易于记忆和比较。一个好的错误码必须能够在没有文档和系统平台的情况下达到离线轻量级通信的目的(这个要求比较高)。引自《手册》-异常日志-ErrorCode错误码制定原则:快速追溯、易记、规范通信。解释:错误代码过于完善和繁杂,就像康熙字典里的生僻字,字看似精确,但字典不易携带,通俗易懂。正例:错误码回答的问题是谁的错?错在哪里?1)错误码必须能够快速知道错误来源,快速判断是谁的错。2)错误码容易记忆和比较(代码中容易equals)。3)错误代码可以与文档和系统平台分离,达到离线轻量级和自由通信的目的。这个原理写在异常日志-错误码一章,我觉得也适用于面向用户的错误码。3.错误码说明错误码定义必须有字母和数字。纯数字。错误代码。错误码是人之常情,感性认知+口耳相传。用纯数字来排列错误代码不利于感知记忆和分类。说明:数字是一个整体,每个数字的地位和意义都是一样的。计数器示例:一个五位数字12345,第一位是错误级别,第二位是错误来源,345是序列号。人脑不会主动去区分每个数字的不同含义。《手册》说明了纯数字错误代码的问题。纯字母错误码不好吗?有两个问题:对于使用中文的我们来说,有时很难用英文准确描述一个错误。纯英文字母的错误码不利于排序。错误代码应该尽可能有助于具有不同文化背景的开发人员在代码上进行交流和协作。注意:英文单词形式的错误代码不利于非英语国家(如阿拉伯语、希伯来语、俄语等)开发者之间的相互协作。快速追溯|简单好记|通信标准化什么是快速可追溯性?这意味着一眼就知道出了什么问题。李磊负责服务A,韩梅梅负责服务B,韩梅梅发现服务B有错误代码,韩梅梅很快定位到服务A内部业务异常导致的问题.这时候,韩梅梅拿着错误码找到了李雷,说:“hi,LiLei,Howoldareyou.(LiLei,为什么总是你)”。厉雷接过错误码看了看。他的心在狂跳,他立刻知道这是负责上游Polly的应用程序Alpha的错误。怎样才能达到这个效果呢?首先,必须有一套标准,域内的所有业务都使用相同的标准。其次,要求错误代码具有自我解释能力,具有信息内容,是有意义的。最后,错误代码应该在域中传递。错误码标准的意思很明显是借鉴了《手册》的错误码定义原则,作为错误码标准能够给我们带来的好处。我想再次强调并尝试扭转没有错误代码标准的成本。错误代码用于通信:系统之间的通信、人与人之间的通信、人与系统之间的通信。想象一下这样的场景:韩梅梅在异常日志中看到一个纯数字的错误代码。韩梅梅需要弄明白这串数字代表什么,是不是错误码。几秒后,确认是错误码,但她不能确定是不是这个系统的错误码,因为在她负责的系统中,是由韩梅梅、露西和莉莉共同维护的,每个人都根据自己的理解定义了一组错误码。韩梅梅去系统源代码中查找这个错误码,却发现这个错误码并不是这个系统的错误码。然后向前翻两页,向后翻两页,从日志的上下文判断,这是李磊负责的系统的错误码,“李烈,你几岁了?”。韩梅梅把错误代码扔到李雷脸上,李雷一脸疑惑,这是我系统的错误代码吗?李雷不确定,因为李雷负责的系统是由李雷、林涛和吉姆共同维护的,也是三人共同维护的。李雷只好打开源码,果然是!上面的场景经历了七个步骤:发现-初步判断-判断来源-确认来源-沟通-二次判断-二次确认。希望以上场景描述能够说明没有统一标准的错误代价。4.面向日志的错误码输出到日志的错误码有两个目的:用于快速追根溯源,发现问题。用于形成监控市场。错误码设计《手册》错误码建议参考很多:错误码不反映版本号和错误级别信息。解释:错误码兼容连续相加的方式。错误级别由日志和错误代码本身的解释决定。错误码为字符串类型,共5位,分为两部分:错误来源+四位数字。错误码不能直接作为提示信息输出给用户。说明:堆栈(stack_trace)、错误信息(error_message)、错误代码(error_code)、提示信息(user_tip)是一个和谐的整体,有效关联,相互转义,但请不要相互覆盖。在获取第三方服务错误码时,throwup让系统越狱,从C到B,在错误信息中加上原来的第三方错误码。结合错误码的设计原则、错误码的使用、协议推荐,服务端日志的错误码应该是如下形式。错误码分为一级宏错误码、二级宏错误码和三级宏错误码。错码是人之常情,感性认知+口口相传,用纯数字来排列错码,不利于感性记忆和分类。说明:数字是一个整体,每个数字的地位和意义都是一样的。计数器示例:一个五位数字12345,第一位是错误级别,第二位是错误来源,345是序列号。人脑不会主动去区分每个数字的不同含义。根据《手册》的建议,面向日志的错误码定义一共有十三位(十位是有意义的,三位是连接符),应该有如下分类:应用ID,表示错误是哪个应用属于,三位数。功能域标识符,表示错误属于应用程序中的哪个功能模块,三位数字。错误类型,表示错误的类型,一个字母。错误码,错误类型下的具体错误,三位数字。《手册》还有一篇文章规定了如何定义错误码:错误码是字符串类型,一共5位,分为两部分:错误来源+四位数字。说明:错误来源分为A/B/C。A表示错误来自于用户,例如参数错误、用户安装的版本太低、用户支付超时等;B表示错误来自于当前系统,往往是业务逻辑错误。或者程序健壮性等问题;C表示错误来自于第三方服务,如CDN服务错误、消息传递超时等;四位数字从0001到9999,大类之间的步距保留为100。五位错误代码的好处是容易记忆,但使用错误会变难代码创建一个业务监控仪表盘,需要对面向日志的错误码场景进行分类,比如统计应用A的函数B的错误次数。同样在系统间传递此类错误码也极有可能导致错误码冲突。当然,分成四段的错误码也特别不好。应用标识和功能域标识需要专人管理或开发错误码管理工具。否则时间长了容易造成定义混乱、破窗。《手册》对于错误码的定义,我觉得很适合对外传递的错误码。简单易记,熟悉的错误码风格,显示的错误码数量非常有限。在没有枚举的情况下定义错误代码国际化支持是不使用枚举定义错误代码的一个重要原因。我们可以通过i18n支持管理错误代码、错误状态和错误描述。5.外传错误码外传错误码用于传递域内的错误信息。域外系统可以根据错误码执行后续动作或中断运行或记录日志继续执行。可以让前端通过错误码给用户准确的错误提示或者忽略错误重试。错误码设计根据《手册》给出的错误码定义,为对外传输设计的错误码一共5个字符,分类如下:错误类型,表示错误来源,一个字母。错误码,表示具体的错误,四位数字。错误代码的最后三位数字与HTTP状态代码无关。错码是人之常情,感性认知+口口相传,用纯数字来排列错码,不利于感性记忆和分类。说明:数字是一个整体,每个数字的地位和意义都是一样的。计数器示例:一个五位数字12345,第一位是错误级别,第二位是错误来源,345是序列号。人脑不会主动去区分每个数字的不同含义。下图是《手册》给出的错误代码示例:他山之石未必能攻玉。GoogleAPI错误代码定义GoogleAPI的错误代码定义与HTTP状态代码有很强的联系,是一个全数字错误代码定义。没有明显的误分类,快速识别和自我解释能力较弱。TencentOpenAPI(Wenzhi)错误码定义这也是一个全数字的错误码,没有明确的分类字段,纯数字的某个数字没有明显的分类。不利于感性记忆。微博API错误码定义也是全数字的错误码定义:其他建议《手册》有一个建议:一切正常,但是非要填写错误码的时候,返回五个零:00000。这也是可以在其他API错误代码中看到的定义。参考《阿里巴巴java开发手册》《Google API Design Guide 》(https://www.bookstack.cn/books/API-design-guide)《阿里云-文件存储-错误码》(https://help.aliyun.com/document_detail/62603.html)《微博开放平台-API-错误码》(https://open.weibo.com/wiki/Help/error)《腾讯开放平台-错误码》(https://wiki.open.qq.com/wiki/%E9%94%99%E8%AF%AF%E7%A0%81)
