package errs import ( "errors" "fmt" "strings" "code.30cm.net/digimon/library-go/errs/code" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/status" ) const ( defaultDetailCode = 00 ) func newBuiltinGRPCErr(scope, detail uint32, msg string) *LibError { return &LibError{ category: code.CatGRPC, code: detail, scope: scope, msg: msg, } } // FromError tries to let error as Err // it supports to unwrap error that has Error // return nil if failed to transfer func FromError(err error) *LibError { if err == nil { return nil } var e *LibError if errors.As(err, &e) { return e } return nil } // FromCode parses code as following 7 碼 // Decimal: 1200314 // 12 represents Scope // 003 represents Category // 14 represents Detail error code func FromCode(code uint32) *LibError { // 獲取 scope,前兩位數 scope := code / 100000 // 獲取 detail,最後兩位數 detail := code % 100 // 獲取 category,中間三位數 category := (code / 100) % 1000 return &LibError{ category: category * 100, // category 放大為三位數的整百數 code: category*100 + detail, // 重構完整的 code scope: scope, msg: "", } } // FromGRPCError transfer error to Err // useful for gRPC client func FromGRPCError(err error) *LibError { s, _ := status.FromError(err) e := FromCode(uint32(s.Code())) e.msg = s.Message() // For GRPC built-in code if e.Scope() == code.Unset && e.Category() == 0 && e.Code() != code.OK { e = newBuiltinGRPCErr(Scope, e.Code(), s.Message()) } return e } /*** System ***/ // SystemTimeoutError xxx6300 returns Error 系統超時 func SystemTimeoutError(s ...string) *LibError { return NewError(Scope, code.SystemTimeoutError, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // SystemTimeoutErrorL logs error message and returns Err func SystemTimeoutErrorL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := SystemTimeoutError(s...) if filed != nil { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // SystemInternalError xxx6100 returns Err struct func SystemInternalError(s ...string) *LibError { return NewError(Scope, code.SystemInternalError, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // SystemInternalErrorL logs error message and returns Err func SystemInternalErrorL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := SystemInternalError(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatInput ***/ // InvalidFormat returns Err struct func InvalidFormat(s ...string) *LibError { return NewError(Scope, code.InvalidFormat, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InvalidFormatL logs error message and returns Err func InvalidFormatL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InvalidFormat(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidRange returns Err struct func InvalidRange(s ...string) *LibError { return NewError(Scope, code.InvalidRange, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InvalidRangeL logs error message and returns Err func InvalidRangeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InvalidRange(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // NotValidImplementation returns Err struct func NotValidImplementation(s ...string) *LibError { return NewError(Scope, code.NotValidImplementation, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // NotValidImplementationL logs error message and returns Err func NotValidImplementationL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := NotValidImplementation(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatDB ***/ // DBError returns Err func DBError(s ...string) *LibError { return NewError(Scope, code.DBError, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // DBErrorL logs error message and returns Err func DBErrorL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := DBError(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // DBDataConvert returns Err func DBDataConvert(s ...string) *LibError { return NewError(Scope, code.DBDataConvert, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // DBDataConvertL logs error message and returns Err func DBDataConvertL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := DBDataConvert(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // DBDuplicate returns Err func DBDuplicate(s ...string) *LibError { return NewError(Scope, code.DBDuplicate, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // DBDuplicateL logs error message and returns Err func DBDuplicateL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := DBDuplicate(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatResource ***/ // ResourceNotFound returns Err and logging func ResourceNotFound(s ...string) *LibError { return NewError(Scope, code.ResourceNotFound, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // ResourceNotFoundL logs error message and returns Err func ResourceNotFoundL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := ResourceNotFound(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidResourceFormat returns Err func InvalidResourceFormat(s ...string) *LibError { return NewError(Scope, code.InvalidResourceFormat, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InvalidResourceFormatL logs error message and returns Err func InvalidResourceFormatL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InvalidResourceFormat(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidResourceState returns status not correct. // for example: company should be destroy, agent should be no-sensor/fail-install ... func InvalidResourceState(s ...string) *LibError { return NewError(Scope, code.InvalidResourceState, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InvalidResourceStateL logs error message and returns status not correct. func InvalidResourceStateL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InvalidResourceState(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } func ResourceInsufficient(s ...string) *LibError { return NewError(Scope, code.ResourceInsufficient, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } func ResourceInsufficientL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := ResourceInsufficient(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InsufficientPermission returns Err func InsufficientPermission(s ...string) *LibError { return NewError(Scope, code.InsufficientPermission, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InsufficientPermissionL returns Err and log func InsufficientPermissionL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InsufficientPermission(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // ResourceAlreadyExist returns Err func ResourceAlreadyExist(s ...string) *LibError { return NewError(Scope, code.ResourceAlreadyExist, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // ResourceAlreadyExistL logs error message and returns Err func ResourceAlreadyExistL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := ResourceAlreadyExist(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidMeasurementID returns Err func InvalidMeasurementID(s ...string) *LibError { return NewError(Scope, code.InvalidMeasurementID, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InvalidMeasurementIDL logs error message and returns Err func InvalidMeasurementIDL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InvalidMeasurementID(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // ResourceExpired returns Err func ResourceExpired(s ...string) *LibError { return NewError(Scope, code.ResourceExpired, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // ResourceExpiredL logs error message and returns Err func ResourceExpiredL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := ResourceExpired(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // ResourceMigrated returns Err func ResourceMigrated(s ...string) *LibError { return NewError(Scope, code.ResourceMigrated, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // ResourceMigratedL logs error message and returns Err func ResourceMigratedL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := ResourceMigrated(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InsufficientQuota returns Err func InsufficientQuota(s ...string) *LibError { return NewError(Scope, code.InsufficientQuota, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // InsufficientQuotaL logs error message and returns Err func InsufficientQuotaL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InsufficientQuota(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatAuth ***/ // Unauthorized returns Err func Unauthorized(s ...string) *LibError { return NewError(Scope, code.Unauthorized, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // UnauthorizedL logs error message and returns Err func UnauthorizedL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := Unauthorized(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // AuthExpired returns Err func AuthExpired(s ...string) *LibError { return NewError(Scope, code.AuthExpired, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // AuthExpiredL logs error message and returns Err func AuthExpiredL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := AuthExpired(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidPosixTime returns Err func InvalidPosixTime(s ...string) *LibError { return NewError(Scope, code.InvalidPosixTime, defaultDetailCode, fmt.Sprintf("i%s", strings.Join(s, " "))) } // InvalidPosixTimeL logs error message and returns Err func InvalidPosixTimeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := InvalidPosixTime(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // SigAndPayloadNotMatched returns Err func SigAndPayloadNotMatched(s ...string) *LibError { return NewError(Scope, code.SigAndPayloadNotMatched, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // SigAndPayloadNotMatchedL logs error message and returns Err func SigAndPayloadNotMatchedL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := SigAndPayloadNotMatched(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // Forbidden returns Err func Forbidden(s ...string) *LibError { return NewError(Scope, code.Forbidden, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // ForbiddenL logs error message and returns Err func ForbiddenL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := Forbidden(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // IsAuthUnauthorizedError check the err is unauthorized error func IsAuthUnauthorizedError(err *LibError) bool { switch err.Code() / 100 { case code.Unauthorized, code.AuthExpired, code.InvalidPosixTime, code.SigAndPayloadNotMatched, code.Forbidden, code.InvalidFormat, code.ResourceNotFound: return true default: return false } } /*** CatPubSub ***/ // Publish returns Err func Publish(s ...string) *LibError { return NewError(Scope, code.Publish, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // PublishL logs error message and returns Err func PublishL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := Publish(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // Consume returns Err func Consume(s ...string) *LibError { return NewError(Scope, code.Consume, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } func ConsumeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := Consume(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e } // MsgSizeTooLarge returns Err func MsgSizeTooLarge(s ...string) *LibError { return NewError(Scope, code.MsgSizeTooLarge, defaultDetailCode, fmt.Sprintf("%s", strings.Join(s, " "))) } // MsgSizeTooLargeL logs error message and returns Err func MsgSizeTooLargeL(l logx.Logger, filed []logx.LogField, s ...string) *LibError { e := MsgSizeTooLarge(s...) if filed != nil || len(filed) >= 0 { l.WithCallerSkip(1).WithFields(filed...).Error(e.Error()) } l.WithCallerSkip(1).Error(e.Error()) return e }