feat: create v2-prep branch with comprehensive planning
Restructured project for V2 refactor: **Structure Changes:** - Moved all V1 code to orig/ folder (preserved with git mv) - Created docs/planning/ directory - Added orig/README_V1.md explaining V1 preservation **Planning Documents:** - 00_V2_MASTER_PLAN.md: Complete architecture overview - Executive summary of critical V1 issues - High-level component architecture diagrams - 5-phase implementation roadmap - Success metrics and risk mitigation - 07_TASK_BREAKDOWN.md: Atomic task breakdown - 99+ hours of detailed tasks - Every task < 2 hours (atomic) - Clear dependencies and success criteria - Organized by implementation phase **V2 Key Improvements:** - Per-exchange parsers (factory pattern) - Multi-layer strict validation - Multi-index pool cache - Background validation pipeline - Comprehensive observability **Critical Issues Addressed:** - Zero address tokens (strict validation + cache enrichment) - Parsing accuracy (protocol-specific parsers) - No audit trail (background validation channel) - Inefficient lookups (multi-index cache) - Stats disconnection (event-driven metrics) Next Steps: 1. Review planning documents 2. Begin Phase 1: Foundation (P1-001 through P1-010) 3. Implement parsers in Phase 2 4. Build cache system in Phase 3 5. Add validation pipeline in Phase 4 6. Migrate and test in Phase 5 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
276
orig/pkg/errors/structured_error.go
Normal file
276
orig/pkg/errors/structured_error.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrorCategory represents the category of an error
|
||||
type ErrorCategory string
|
||||
|
||||
const (
|
||||
CategoryNetwork ErrorCategory = "NETWORK" // RPC, DNS, connection issues
|
||||
CategoryParsing ErrorCategory = "PARSING" // ABI decoding, transaction parsing
|
||||
CategoryValidation ErrorCategory = "VALIDATION" // Input validation, data validation
|
||||
CategoryExecution ErrorCategory = "EXECUTION" // Transaction execution, contract calls
|
||||
CategoryConfiguration ErrorCategory = "CONFIGURATION" // Config loading, invalid settings
|
||||
CategoryDatabase ErrorCategory = "DATABASE" // Database operations
|
||||
CategorySecurity ErrorCategory = "SECURITY" // Security violations, unauthorized access
|
||||
CategoryMath ErrorCategory = "MATH" // Arithmetic errors, overflow/underflow
|
||||
CategoryInternal ErrorCategory = "INTERNAL" // Internal logic errors, unexpected state
|
||||
CategoryExternal ErrorCategory = "EXTERNAL" // External service failures
|
||||
CategoryUnknown ErrorCategory = "UNKNOWN" // Uncategorized errors
|
||||
)
|
||||
|
||||
// ErrorSeverity represents how critical an error is
|
||||
type ErrorSeverity string
|
||||
|
||||
const (
|
||||
SeverityDebug ErrorSeverity = "DEBUG" // Informational, not an actual error
|
||||
SeverityInfo ErrorSeverity = "INFO" // Notable but not problematic
|
||||
SeverityWarning ErrorSeverity = "WARNING" // Potential issue, should investigate
|
||||
SeverityError ErrorSeverity = "ERROR" // Actual error, functionality impacted
|
||||
SeverityCritical ErrorSeverity = "CRITICAL" // Critical error, immediate attention required
|
||||
SeverityFatal ErrorSeverity = "FATAL" // Fatal error, system cannot continue
|
||||
)
|
||||
|
||||
// StructuredError represents a comprehensive error with full context
|
||||
type StructuredError struct {
|
||||
// Core error information
|
||||
Message string // Human-readable error message
|
||||
Category ErrorCategory // Error category for classification
|
||||
Severity ErrorSeverity // How critical is this error
|
||||
|
||||
// Origin tracking
|
||||
File string // Source file where error occurred
|
||||
Function string // Function where error occurred
|
||||
Line int // Line number where error occurred
|
||||
Package string // Go package where error occurred
|
||||
|
||||
// Context
|
||||
Reason string // Why this error occurred (root cause)
|
||||
Action string // What the code was trying to do when it failed
|
||||
Impact string // Impact of this error on the system
|
||||
Suggestion string // Suggested fix or next steps
|
||||
Details map[string]interface{} // Additional structured context
|
||||
UnderlyingErr error // Original error if wrapping
|
||||
|
||||
// Metadata
|
||||
Timestamp time.Time // When the error occurred
|
||||
ErrorID string // Unique identifier for this error instance
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (e *StructuredError) Error() string {
|
||||
if e.UnderlyingErr != nil {
|
||||
return fmt.Sprintf("[%s/%s] %s: %v (in %s:%d)",
|
||||
e.Category, e.Severity, e.Message, e.UnderlyingErr, e.File, e.Line)
|
||||
}
|
||||
return fmt.Sprintf("[%s/%s] %s (in %s:%d)",
|
||||
e.Category, e.Severity, e.Message, e.File, e.Line)
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying error for error chain support
|
||||
func (e *StructuredError) Unwrap() error {
|
||||
return e.UnderlyingErr
|
||||
}
|
||||
|
||||
// NewStructuredError creates a new structured error with automatic caller tracking
|
||||
func NewStructuredError(category ErrorCategory, severity ErrorSeverity, message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(category, severity, message, 2)
|
||||
}
|
||||
|
||||
// newStructuredErrorWithDepth creates a structured error with custom stack depth
|
||||
func newStructuredErrorWithDepth(category ErrorCategory, severity ErrorSeverity, message string, depth int) *StructuredError {
|
||||
// Get caller information
|
||||
pc, file, line, ok := runtime.Caller(depth)
|
||||
if !ok {
|
||||
file = "unknown"
|
||||
line = 0
|
||||
}
|
||||
|
||||
funcName := "unknown"
|
||||
packageName := "unknown"
|
||||
if fn := runtime.FuncForPC(pc); fn != nil {
|
||||
funcName = fn.Name()
|
||||
// Extract package name from function name (format: "package/path.FunctionName")
|
||||
for i := len(funcName) - 1; i >= 0; i-- {
|
||||
if funcName[i] == '/' {
|
||||
packageName = funcName[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate unique error ID
|
||||
errorID := fmt.Sprintf("ERR-%d-%s", time.Now().UnixNano(), category)
|
||||
|
||||
return &StructuredError{
|
||||
Message: message,
|
||||
Category: category,
|
||||
Severity: severity,
|
||||
File: file,
|
||||
Function: funcName,
|
||||
Line: line,
|
||||
Package: packageName,
|
||||
Details: make(map[string]interface{}),
|
||||
Timestamp: time.Now(),
|
||||
ErrorID: errorID,
|
||||
}
|
||||
}
|
||||
|
||||
// WithReason adds the reason (root cause) for the error
|
||||
func (e *StructuredError) WithReason(reason string) *StructuredError {
|
||||
e.Reason = reason
|
||||
return e
|
||||
}
|
||||
|
||||
// WithAction describes what the code was trying to do
|
||||
func (e *StructuredError) WithAction(action string) *StructuredError {
|
||||
e.Action = action
|
||||
return e
|
||||
}
|
||||
|
||||
// WithImpact describes the impact of this error
|
||||
func (e *StructuredError) WithImpact(impact string) *StructuredError {
|
||||
e.Impact = impact
|
||||
return e
|
||||
}
|
||||
|
||||
// WithSuggestion provides a suggestion for fixing or handling the error
|
||||
func (e *StructuredError) WithSuggestion(suggestion string) *StructuredError {
|
||||
e.Suggestion = suggestion
|
||||
return e
|
||||
}
|
||||
|
||||
// WithDetail adds a key-value detail to the error context
|
||||
func (e *StructuredError) WithDetail(key string, value interface{}) *StructuredError {
|
||||
e.Details[key] = value
|
||||
return e
|
||||
}
|
||||
|
||||
// WithDetails adds multiple details at once
|
||||
func (e *StructuredError) WithDetails(details map[string]interface{}) *StructuredError {
|
||||
for k, v := range details {
|
||||
e.Details[k] = v
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Wrap wraps an underlying error with structured context
|
||||
func (e *StructuredError) Wrap(err error) *StructuredError {
|
||||
e.UnderlyingErr = err
|
||||
return e
|
||||
}
|
||||
|
||||
// FormatForLogging returns a comprehensive string representation for logging
|
||||
func (e *StructuredError) FormatForLogging() string {
|
||||
result := fmt.Sprintf(
|
||||
"[%s] %s/%s: %s\n"+
|
||||
" Origin: %s:%d (%s)\n"+
|
||||
" ErrorID: %s\n"+
|
||||
" Timestamp: %s\n",
|
||||
e.ErrorID,
|
||||
e.Category,
|
||||
e.Severity,
|
||||
e.Message,
|
||||
e.File,
|
||||
e.Line,
|
||||
e.Function,
|
||||
e.ErrorID,
|
||||
e.Timestamp.Format(time.RFC3339),
|
||||
)
|
||||
|
||||
if e.Reason != "" {
|
||||
result += fmt.Sprintf(" Reason: %s\n", e.Reason)
|
||||
}
|
||||
|
||||
if e.Action != "" {
|
||||
result += fmt.Sprintf(" Action: %s\n", e.Action)
|
||||
}
|
||||
|
||||
if e.Impact != "" {
|
||||
result += fmt.Sprintf(" Impact: %s\n", e.Impact)
|
||||
}
|
||||
|
||||
if e.Suggestion != "" {
|
||||
result += fmt.Sprintf(" Suggestion: %s\n", e.Suggestion)
|
||||
}
|
||||
|
||||
if len(e.Details) > 0 {
|
||||
result += " Details:\n"
|
||||
for k, v := range e.Details {
|
||||
result += fmt.Sprintf(" - %s: %v\n", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
if e.UnderlyingErr != nil {
|
||||
result += fmt.Sprintf(" Underlying: %v\n", e.UnderlyingErr)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// FormatCompact returns a single-line representation
|
||||
func (e *StructuredError) FormatCompact() string {
|
||||
compact := fmt.Sprintf("[%s/%s] %s", e.Category, e.Severity, e.Message)
|
||||
|
||||
if e.Reason != "" {
|
||||
compact += fmt.Sprintf(" | Reason: %s", e.Reason)
|
||||
}
|
||||
|
||||
if e.Action != "" {
|
||||
compact += fmt.Sprintf(" | Action: %s", e.Action)
|
||||
}
|
||||
|
||||
compact += fmt.Sprintf(" | Origin: %s:%d", e.File, e.Line)
|
||||
|
||||
if e.UnderlyingErr != nil {
|
||||
compact += fmt.Sprintf(" | Underlying: %v", e.UnderlyingErr)
|
||||
}
|
||||
|
||||
return compact
|
||||
}
|
||||
|
||||
// Helper functions for common error patterns
|
||||
|
||||
// NetworkError creates a network-related error
|
||||
func NetworkError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryNetwork, SeverityError, message, 2)
|
||||
}
|
||||
|
||||
// ParsingError creates a parsing-related error
|
||||
func ParsingError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryParsing, SeverityError, message, 2)
|
||||
}
|
||||
|
||||
// ValidationError creates a validation-related error
|
||||
func ValidationError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryValidation, SeverityWarning, message, 2)
|
||||
}
|
||||
|
||||
// ExecutionError creates an execution-related error
|
||||
func ExecutionError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryExecution, SeverityCritical, message, 2)
|
||||
}
|
||||
|
||||
// ConfigurationError creates a configuration-related error
|
||||
func ConfigurationError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryConfiguration, SeverityCritical, message, 2)
|
||||
}
|
||||
|
||||
// InternalError creates an internal logic error
|
||||
func InternalError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryInternal, SeverityError, message, 2)
|
||||
}
|
||||
|
||||
// MathError creates a mathematical error
|
||||
func MathError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategoryMath, SeverityError, message, 2)
|
||||
}
|
||||
|
||||
// SecurityError creates a security-related error
|
||||
func SecurityError(message string) *StructuredError {
|
||||
return newStructuredErrorWithDepth(CategorySecurity, SeverityCritical, message, 2)
|
||||
}
|
||||
Reference in New Issue
Block a user