在Go的世界里面, 如果error没接好, 服务就会直接panic了。panic发生在k8s环境中, k8s会帮忙重启, 但如果是在机房的环境底下, 又没有重启的机制..., 你准备好接电话了吗?
每个服务都要处理error, 包含套件会发生的Scylla error, Redis error, 程序内的资料与逻辑验证error, 以及其他统称为Server error 的错误....等, 这些都需要被收集起来回覆给Client端或是留下纪录debug。
如果把error的处理各自散落在程序码各处一样会有维护性差的状况, 所以可以把Error收在一起, 既能统一输出格式也方便api 接收端排除问题和处理显示格式, 对照错误查找也快。
这边粗略写一下我们平常使用的error内容, 结构里的Code
跟Msg
用来快速判断错误属於哪一类, ExtraInfo
则是用来说明错误发生当下使用的相关资讯, Time
负责记录当下时间, Service
用来区分是哪一个服务送出来的错误, OriginError
是纪录原始的错误讯息。
lib/error
├── error.go
└── error_test.go
package coconutError
import (
"fmt"
"time"
coconutLog "github.com/evelynocean/coconut/lib/log"
)
type Error struct {
Msg string `json:"msg"`
Code int `json:"code"`
ExtraInfo map[string]interface{} `json:"extrainfo"`
Time int64 `json:"time"`
Service string `json:"service"`
OriginError string `json:"origin_error"`
}
var (
Logger *coconutLog.Logger
// ErrServer 系统错误
ErrServer = &Error{Code: 9999, Msg: "ERROR_SERVER", ExtraInfo: make(map[string]interface{})}
// ErrRedis redis 相关
ErrRedis = &Error{Code: 9998, Msg: "ERROR_REDIS", ExtraInfo: make(map[string]interface{})}
)
func init() {
Logger = coconutLog.New()
}
// ParseError error 输出前加工
func ParseError(e *Error, err error) *Error {
e.Service = "Coconut"
e.Time = time.Now().Unix()
e.OriginError = err.Error()
logMsg := map[string]interface{}{
"service": "Coconut",
"time": time.Now().Unix(),
"origin_error": err.Error(),
"code": e.Code,
"msg": e.Msg,
"extra_info": e.ExtraInfo,
}
Logger.WithFields(logMsg).Errorf(e.Msg)
return e
}
func (t Error) Error() string {
return fmt.Sprintf("[Error %d] %s", t.Code, t.Msg)
}
针对error 的部分写 go test验证是否符合预期
package coconutError
import (
"encoding/json"
"errors"
"fmt"
"testing"
)
func TestError(t *testing.T) {
e := ErrServer
e.ExtraInfo = map[string]interface{}{
"aa": 1,
}
testError := ParseError(e, errors.New("测试错误格式"))
str, err := json.Marshal(testError)
if err != nil {
t.Errorf("json.Marshal error: %s", err)
}
fmt.Println(string(str))
}
go test 执行状况, error log输出时有转成JSON
的格式, 方便之後的Log资料搜集
-> % go test
{"code":9999,"extra_info":{"aa":1},"fields.msg":"ERROR_SERVER","fields.time":1631846776,"level":"error","msg":"ERROR_SERVER","origin_error":"测试错误格式","service":"Coconut","time":"2021-09-17T10:46:16+08:00"}
{"msg":"ERROR_SERVER","code":9999,"extrainfo":{"aa":1},"time":1631846776,"service":"Coconut","origin_error":"测试错误格式"}
PASS
ok github.com/evelynocean/coconut/lib/error 0.576s
<<: 自动化测试,让你上班拥有一杯咖啡的时间 | Day 4 - 利用工具录制脚本
>>: Day18 - 轻前端 Vue - 复杂型别 object
tags: 2021铁人赛 React 在Day9说明了useEffect的用法,不过其实当Card...
魔法设定参考 游戏的设定会将主角设定成初阶的魔法师,故使用魔法是很基本的攻击方式。但这样的考量下其实...
前言 前一天我们建立好了 Kubernetes 的环境,今天就来实际使用看看,将应用程序透过 Pod...
大家好,我是毛毛。ヾ(´∀ ˋ)ノ 废话不多说开始今天的解题Day~ 58. Length of L...
架构图 前言 Java程序是一系列对象的集合,而对象之间透过彼此之间调用方法来达到开发目的,因此在认...