package errs import ( "strings" "backend/pkg/library/errors/code" ) /* ========================= 日誌介面(與你現有 Logger 對齊) ========================= */ // Logger 你現有的 logger 介面(與外部一致即可) type Logger interface { WithCallerSkip(n int) Logger WithFields(fields ...LogField) Logger Error(msg string) Warn(msg string) Info(msg string) } // LogField 結構化欄位 type LogField struct { Key string Val any } /* ========================= 共用小工具 ========================= */ // joinMsg:把可變參數字串用空白串接(避免到處判斷 nil / 空 slice) func joinMsg(s []string) string { if len(s) == 0 { return "" } return strings.Join(s, " ") } // logErr:統一打一筆 error log(避免重複記錄) func logErr(l Logger, fields []LogField, e *Error) { if l == nil || e == nil { return } ll := l.WithCallerSkip(1) if len(fields) > 0 { ll = ll.WithFields(fields...) } // 需要更多欄位可在此擴充,例如:e.DisplayCode()、e.Category()、e.Detail() ll.Error(e.Error()) } /* ========================= 共用裝飾器(把任意 ez 建構器包成帶日誌版本) ========================= */ // WithLog 將任一 *Error 建構器(如 SysTimeoutError)轉成帶日誌的版本 func WithLog(l Logger, fields []LogField, ctor func(s ...string) *Error, s ...string) *Error { e := ctor(s...) logErr(l, fields, e) return e } // WithLogWrap 同上,但會同時 Wrap 內部 cause func WithLogWrap(l Logger, fields []LogField, ctor func(s ...string) *Error, cause error, s ...string) *Error { e := ctor(s...).Wrap(cause) logErr(l, fields, e) return e } /* ========================= 泛用建構器(當你懶得記函式名時) ========================= */ // EL 依 Category/Detail 直接建構並記錄日誌 func EL(l Logger, fields []LogField, cat code.Category, det code.Detail, s ...string) *Error { e := New(uint32(Scope), uint32(cat), uint32(det), joinMsg(s)) logErr(l, fields, e) return e } // ELWrap 同上,並 Wrap cause func ELWrap(l Logger, fields []LogField, cat code.Category, det code.Detail, cause error, s ...string) *Error { e := New(uint32(Scope), uint32(cat), uint32(det), joinMsg(s)).Wrap(cause) logErr(l, fields, e) return e } /* ======================================================================= 一、基礎 ez 建構器(純建構 *Error,不帶日誌) 分類順序:Input → DB → Resource → Auth → System → PubSub → Service ======================================================================= */ /* ----- Input (CatInput) ----- */ func InputInvalidFormatError(s ...string) *Error { return New(uint32(Scope), uint32(code.InputInvalidFormat), 0, joinMsg(s)) } func InputNotValidImplementationError(s ...string) *Error { return New(uint32(Scope), uint32(code.InputNotValidImplementation), 0, joinMsg(s)) } func InputInvalidRangeError(s ...string) *Error { return New(uint32(Scope), uint32(code.InputInvalidRange), 0, joinMsg(s)) } /* ----- DB (CatDB) ----- */ func DBErrorError(s ...string) *Error { return New(uint32(Scope), uint32(code.DBError), 0, joinMsg(s)) } func DBDataConvertError(s ...string) *Error { return New(uint32(Scope), uint32(code.DBDataConvert), 0, joinMsg(s)) } func DBDuplicateError(s ...string) *Error { return New(uint32(Scope), uint32(code.DBDuplicate), 0, joinMsg(s)) } /* ----- Resource (CatResource) ----- */ func ResNotFoundError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResNotFound), 0, joinMsg(s)) } func ResInvalidFormatError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResInvalidFormat), 0, joinMsg(s)) } func ResAlreadyExistError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResAlreadyExist), 0, joinMsg(s)) } func ResInsufficientError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResInsufficient), 0, joinMsg(s)) } func ResInsufficientPermError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResInsufficientPerm), 0, joinMsg(s)) } func ResInvalidMeasureIDError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResInvalidMeasureID), 0, joinMsg(s)) } func ResExpiredError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResExpired), 0, joinMsg(s)) } func ResMigratedError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResMigrated), 0, joinMsg(s)) } func ResInvalidStateError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResInvalidState), 0, joinMsg(s)) } func ResInsufficientQuotaError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResInsufficientQuota), 0, joinMsg(s)) } func ResMultiOwnerError(s ...string) *Error { return New(uint32(Scope), uint32(code.ResMultiOwner), 0, joinMsg(s)) } /* ----- Auth (CatAuth) ----- */ func AuthUnauthorizedError(s ...string) *Error { return New(uint32(Scope), uint32(code.AuthUnauthorized), 0, joinMsg(s)) } func AuthExpiredError(s ...string) *Error { return New(uint32(Scope), uint32(code.AuthExpired), 0, joinMsg(s)) } func AuthInvalidPosixTimeError(s ...string) *Error { return New(uint32(Scope), uint32(code.AuthInvalidPosixTime), 0, joinMsg(s)) } func AuthSigPayloadMismatchError(s ...string) *Error { return New(uint32(Scope), uint32(code.AuthSigPayloadMismatch), 0, joinMsg(s)) } func AuthForbiddenError(s ...string) *Error { return New(uint32(Scope), uint32(code.AuthForbidden), 0, joinMsg(s)) } /* ----- System (CatSystem) ----- */ func SysInternalError(s ...string) *Error { return New(uint32(Scope), uint32(code.SysInternal), 0, joinMsg(s)) } func SysMaintainError(s ...string) *Error { return New(uint32(Scope), uint32(code.SysMaintain), 0, joinMsg(s)) } func SysTimeoutError(s ...string) *Error { return New(uint32(Scope), uint32(code.SysTimeout), 0, joinMsg(s)) } func SysTooManyRequestError(s ...string) *Error { return New(uint32(Scope), uint32(code.SysTooManyRequest), 0, joinMsg(s)) } /* ----- PubSub (CatPubSub) ----- */ func PSuPublishError(s ...string) *Error { return New(uint32(Scope), uint32(code.PSuPublish), 0, joinMsg(s)) } func PSuConsumeError(s ...string) *Error { return New(uint32(Scope), uint32(code.PSuConsume), 0, joinMsg(s)) } func PSuTooLargeError(s ...string) *Error { return New(uint32(Scope), uint32(code.PSuTooLarge), 0, joinMsg(s)) } /* ----- Service (CatService) ----- */ func SvcInternalError(s ...string) *Error { return New(uint32(Scope), uint32(code.SvcInternal), 0, joinMsg(s)) } func SvcThirdPartyError(s ...string) *Error { return New(uint32(Scope), uint32(code.SvcThirdParty), 0, joinMsg(s)) } func SvcHTTP400Error(s ...string) *Error { return New(uint32(Scope), uint32(code.SvcHTTP400), 0, joinMsg(s)) } func SvcMaintenanceError(s ...string) *Error { return New(uint32(Scope), uint32(code.SvcMaintenance), 0, joinMsg(s)) } /* ============================================================================= 二、帶日誌版本:L / WrapL(在「基礎 ez 建構器」之上包裝 WithLog / WithLogWrap) 分類順序同上:Input → DB → Resource → Auth → System → PubSub → Service ============================================================================= */ /* ----- Input (CatInput) ----- */ func InputInvalidFormatErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, InputInvalidFormatError, s...) } func InputInvalidFormatErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, InputInvalidFormatError, cause, s...) } func InputNotValidImplementationErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, InputNotValidImplementationError, s...) } func InputNotValidImplementationErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, InputNotValidImplementationError, cause, s...) } func InputInvalidRangeErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, InputInvalidRangeError, s...) } func InputInvalidRangeErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, InputInvalidRangeError, cause, s...) } /* ----- DB (CatDB) ----- */ func DBErrorErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, DBErrorError, s...) } func DBErrorErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, DBErrorError, cause, s...) } func DBDataConvertErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, DBDataConvertError, s...) } func DBDataConvertErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, DBDataConvertError, cause, s...) } func DBDuplicateErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, DBDuplicateError, s...) } func DBDuplicateErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, DBDuplicateError, cause, s...) } /* ----- Resource (CatResource) ----- */ func ResNotFoundErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResNotFoundError, s...) } func ResNotFoundErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResNotFoundError, cause, s...) } func ResInvalidFormatErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResInvalidFormatError, s...) } func ResInvalidFormatErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResInvalidFormatError, cause, s...) } func ResAlreadyExistErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResAlreadyExistError, s...) } func ResAlreadyExistErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResAlreadyExistError, cause, s...) } func ResInsufficientErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResInsufficientError, s...) } func ResInsufficientErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResInsufficientError, cause, s...) } func ResInsufficientPermErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResInsufficientPermError, s...) } func ResInsufficientPermErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResInsufficientPermError, cause, s...) } func ResInvalidMeasureIDErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResInvalidMeasureIDError, s...) } func ResInvalidMeasureIDErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResInvalidMeasureIDError, cause, s...) } func ResExpiredErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResExpiredError, s...) } func ResExpiredErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResExpiredError, cause, s...) } func ResMigratedErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResMigratedError, s...) } func ResMigratedErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResMigratedError, cause, s...) } func ResInvalidStateErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResInvalidStateError, s...) } func ResInvalidStateErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResInvalidStateError, cause, s...) } func ResInsufficientQuotaErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResInsufficientQuotaError, s...) } func ResInsufficientQuotaErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResInsufficientQuotaError, cause, s...) } func ResMultiOwnerErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, ResMultiOwnerError, s...) } func ResMultiOwnerErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, ResMultiOwnerError, cause, s...) } /* ----- Auth (CatAuth) ----- */ func AuthUnauthorizedErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, AuthUnauthorizedError, s...) } func AuthUnauthorizedErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, AuthUnauthorizedError, cause, s...) } func AuthExpiredErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, AuthExpiredError, s...) } func AuthExpiredErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, AuthExpiredError, cause, s...) } func AuthInvalidPosixTimeErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, AuthInvalidPosixTimeError, s...) } func AuthInvalidPosixTimeErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, AuthInvalidPosixTimeError, cause, s...) } func AuthSigPayloadMismatchErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, AuthSigPayloadMismatchError, s...) } func AuthSigPayloadMismatchErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, AuthSigPayloadMismatchError, cause, s...) } func AuthForbiddenErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, AuthForbiddenError, s...) } func AuthForbiddenErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, AuthForbiddenError, cause, s...) } /* ----- System (CatSystem) ----- */ func SysInternalErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SysInternalError, s...) } func SysInternalErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SysInternalError, cause, s...) } func SysMaintainErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SysMaintainError, s...) } func SysMaintainErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SysMaintainError, cause, s...) } func SysTimeoutErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SysTimeoutError, s...) } func SysTimeoutErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SysTimeoutError, cause, s...) } func SysTooManyRequestErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SysTooManyRequestError, s...) } func SysTooManyRequestErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SysTooManyRequestError, cause, s...) } /* ----- PubSub (CatPubSub) ----- */ func PSuPublishErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, PSuPublishError, s...) } func PSuPublishErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, PSuPublishError, cause, s...) } func PSuConsumeErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, PSuConsumeError, s...) } func PSuConsumeErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, PSuConsumeError, cause, s...) } func PSuTooLargeErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, PSuTooLargeError, s...) } func PSuTooLargeErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, PSuTooLargeError, cause, s...) } /* ----- Service (CatService) ----- */ func SvcInternalErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SvcInternalError, s...) } func SvcInternalErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SvcInternalError, cause, s...) } func SvcThirdPartyErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SvcThirdPartyError, s...) } func SvcThirdPartyErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SvcThirdPartyError, cause, s...) } func SvcHTTP400ErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SvcHTTP400Error, s...) } func SvcHTTP400ErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SvcHTTP400Error, cause, s...) } func SvcMaintenanceErrorL(l Logger, fields []LogField, s ...string) *Error { return WithLog(l, fields, SvcMaintenanceError, s...) } func SvcMaintenanceErrorWrapL(l Logger, fields []LogField, cause error, s ...string) *Error { return WithLogWrap(l, fields, SvcMaintenanceError, cause, s...) }