- Introduced a new error handling system with custom error types for better context and clarity in error reporting. - Implemented URL validation to prevent invalid requests and enhance security. - Updated cache key generation functions to return errors, improving robustness in handling invalid inputs. - Added comprehensive metrics tracking for requests, cache hits, misses, and performance metrics, allowing for better monitoring and analysis of the caching system. - Enhanced logging to include detailed metrics and error information for improved debugging and operational insights.
121 lines
3.4 KiB
Go
121 lines
3.4 KiB
Go
// steamcache/errors/errors.go
|
|
package errors
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
)
|
|
|
|
// Common SteamCache errors
|
|
var (
|
|
ErrInvalidURL = errors.New("steamcache: invalid URL")
|
|
ErrUnsupportedService = errors.New("steamcache: unsupported service")
|
|
ErrUpstreamUnavailable = errors.New("steamcache: upstream server unavailable")
|
|
ErrCacheCorrupted = errors.New("steamcache: cache file corrupted")
|
|
ErrInvalidContentLength = errors.New("steamcache: invalid content length")
|
|
ErrRequestTimeout = errors.New("steamcache: request timeout")
|
|
ErrRateLimitExceeded = errors.New("steamcache: rate limit exceeded")
|
|
ErrInvalidUserAgent = errors.New("steamcache: invalid user agent")
|
|
)
|
|
|
|
// SteamCacheError represents a SteamCache-specific error with context
|
|
type SteamCacheError struct {
|
|
Op string // Operation that failed
|
|
URL string // URL that caused the error
|
|
ClientIP string // Client IP address
|
|
StatusCode int // HTTP status code if applicable
|
|
Err error // Underlying error
|
|
Context interface{} // Additional context
|
|
}
|
|
|
|
// Error implements the error interface
|
|
func (e *SteamCacheError) Error() string {
|
|
if e.URL != "" && e.ClientIP != "" {
|
|
return fmt.Sprintf("steamcache: %s failed for URL %q from client %s: %v", e.Op, e.URL, e.ClientIP, e.Err)
|
|
}
|
|
if e.URL != "" {
|
|
return fmt.Sprintf("steamcache: %s failed for URL %q: %v", e.Op, e.URL, e.Err)
|
|
}
|
|
return fmt.Sprintf("steamcache: %s failed: %v", e.Op, e.Err)
|
|
}
|
|
|
|
// Unwrap returns the underlying error
|
|
func (e *SteamCacheError) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// NewSteamCacheError creates a new SteamCache error with context
|
|
func NewSteamCacheError(op, url, clientIP string, err error) *SteamCacheError {
|
|
return &SteamCacheError{
|
|
Op: op,
|
|
URL: url,
|
|
ClientIP: clientIP,
|
|
Err: err,
|
|
}
|
|
}
|
|
|
|
// NewSteamCacheErrorWithStatus creates a new SteamCache error with HTTP status
|
|
func NewSteamCacheErrorWithStatus(op, url, clientIP string, statusCode int, err error) *SteamCacheError {
|
|
return &SteamCacheError{
|
|
Op: op,
|
|
URL: url,
|
|
ClientIP: clientIP,
|
|
StatusCode: statusCode,
|
|
Err: err,
|
|
}
|
|
}
|
|
|
|
// NewSteamCacheErrorWithContext creates a new SteamCache error with additional context
|
|
func NewSteamCacheErrorWithContext(op, url, clientIP string, context interface{}, err error) *SteamCacheError {
|
|
return &SteamCacheError{
|
|
Op: op,
|
|
URL: url,
|
|
ClientIP: clientIP,
|
|
Context: context,
|
|
Err: err,
|
|
}
|
|
}
|
|
|
|
// IsRetryableError determines if an error is retryable
|
|
func IsRetryableError(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
|
|
// Check for specific retryable errors
|
|
if errors.Is(err, ErrUpstreamUnavailable) ||
|
|
errors.Is(err, ErrRequestTimeout) {
|
|
return true
|
|
}
|
|
|
|
// Check for HTTP status codes that are retryable
|
|
if steamErr, ok := err.(*SteamCacheError); ok {
|
|
switch steamErr.StatusCode {
|
|
case http.StatusServiceUnavailable,
|
|
http.StatusGatewayTimeout,
|
|
http.StatusTooManyRequests,
|
|
http.StatusInternalServerError:
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// IsClientError determines if an error is a client error (4xx)
|
|
func IsClientError(err error) bool {
|
|
if steamErr, ok := err.(*SteamCacheError); ok {
|
|
return steamErr.StatusCode >= 400 && steamErr.StatusCode < 500
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsServerError determines if an error is a server error (5xx)
|
|
func IsServerError(err error) bool {
|
|
if steamErr, ok := err.(*SteamCacheError); ok {
|
|
return steamErr.StatusCode >= 500
|
|
}
|
|
return false
|
|
}
|