mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
139 lines
3.5 KiB
Go
139 lines
3.5 KiB
Go
package errors
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// Error codes for categorizing errors
|
|
type Code string
|
|
|
|
const (
|
|
// Configuration errors
|
|
CodeConfigInvalid Code = "CONFIG_INVALID"
|
|
CodeConfigNotFound Code = "CONFIG_NOT_FOUND"
|
|
CodeConfigParseFailed Code = "CONFIG_PARSE_FAILED"
|
|
|
|
// Server errors
|
|
CodeServerStartFailed Code = "SERVER_START_FAILED"
|
|
CodeServerStopFailed Code = "SERVER_STOP_FAILED"
|
|
CodeServerAlreadyRunning Code = "SERVER_ALREADY_RUNNING"
|
|
CodeServerNotRunning Code = "SERVER_NOT_RUNNING"
|
|
|
|
// Proxy errors
|
|
CodeProxyBackendUnavailable Code = "PROXY_BACKEND_UNAVAILABLE"
|
|
CodeProxyTimeout Code = "PROXY_TIMEOUT"
|
|
CodeProxyInvalidTarget Code = "PROXY_INVALID_TARGET"
|
|
|
|
// Network errors
|
|
CodeNetworkTimeout Code = "NETWORK_TIMEOUT"
|
|
CodeNetworkUnreachable Code = "NETWORK_UNREACHABLE"
|
|
CodeNetworkRefused Code = "NETWORK_REFUSED"
|
|
|
|
// Internal errors
|
|
CodeInternalError Code = "INTERNAL_ERROR"
|
|
CodeUnknownError Code = "UNKNOWN_ERROR"
|
|
)
|
|
|
|
// AppError represents a structured application error
|
|
type AppError struct {
|
|
Code Code // Error code for categorization
|
|
Message string // Human-readable error message
|
|
Cause error // Underlying error (if any)
|
|
}
|
|
|
|
// Error implements the error interface
|
|
func (e *AppError) Error() string {
|
|
if e.Cause != nil {
|
|
return fmt.Sprintf("[%s] %s: %v", e.Code, e.Message, e.Cause)
|
|
}
|
|
return fmt.Sprintf("[%s] %s", e.Code, e.Message)
|
|
}
|
|
|
|
// Unwrap returns the underlying error (for errors.Is and errors.As)
|
|
func (e *AppError) Unwrap() error {
|
|
return e.Cause
|
|
}
|
|
|
|
// Is checks if the error matches the target
|
|
func (e *AppError) Is(target error) bool {
|
|
t, ok := target.(*AppError)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return e.Code == t.Code
|
|
}
|
|
|
|
// New creates a new AppError
|
|
func New(code Code, message string) *AppError {
|
|
return &AppError{
|
|
Code: code,
|
|
Message: message,
|
|
}
|
|
}
|
|
|
|
// Wrap wraps an existing error with additional context
|
|
func Wrap(code Code, message string, cause error) *AppError {
|
|
return &AppError{
|
|
Code: code,
|
|
Message: message,
|
|
Cause: cause,
|
|
}
|
|
}
|
|
|
|
// Wrapf wraps an error with a formatted message
|
|
func Wrapf(code Code, cause error, format string, args ...interface{}) *AppError {
|
|
return &AppError{
|
|
Code: code,
|
|
Message: fmt.Sprintf(format, args...),
|
|
Cause: cause,
|
|
}
|
|
}
|
|
|
|
// GetCode extracts the error code from an error
|
|
func GetCode(err error) Code {
|
|
var appErr *AppError
|
|
if errors.As(err, &appErr) {
|
|
return appErr.Code
|
|
}
|
|
return CodeUnknownError
|
|
}
|
|
|
|
// HasCode checks if an error has a specific code
|
|
func HasCode(err error, code Code) bool {
|
|
return GetCode(err) == code
|
|
}
|
|
|
|
// IsConfigError checks if an error is configuration-related
|
|
func IsConfigError(err error) bool {
|
|
code := GetCode(err)
|
|
return code == CodeConfigInvalid ||
|
|
code == CodeConfigNotFound ||
|
|
code == CodeConfigParseFailed
|
|
}
|
|
|
|
// IsServerError checks if an error is server-related
|
|
func IsServerError(err error) bool {
|
|
code := GetCode(err)
|
|
return code == CodeServerStartFailed ||
|
|
code == CodeServerStopFailed ||
|
|
code == CodeServerAlreadyRunning ||
|
|
code == CodeServerNotRunning
|
|
}
|
|
|
|
// IsProxyError checks if an error is proxy-related
|
|
func IsProxyError(err error) bool {
|
|
code := GetCode(err)
|
|
return code == CodeProxyBackendUnavailable ||
|
|
code == CodeProxyTimeout ||
|
|
code == CodeProxyInvalidTarget
|
|
}
|
|
|
|
// IsNetworkError checks if an error is network-related
|
|
func IsNetworkError(err error) bool {
|
|
code := GetCode(err)
|
|
return code == CodeNetworkTimeout ||
|
|
code == CodeNetworkUnreachable ||
|
|
code == CodeNetworkRefused
|
|
}
|