### Best Practices for Error Handling Patterns Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Common patterns for dynamic configuration, conditional capture, and wrapping errors with stack trace skipping. ```go // Environment-specific configuration var stackConfig *erro.StackTraceConfig switch os.Getenv("ENVIRONMENT") { case "development": stackConfig = erro.DevelopmentStackTraceConfig() case "production": stackConfig = erro.ProductionStackTraceConfig() case "strict": stackConfig = erro.StrictStackTraceConfig() } // Wrapper function pattern func wrapDatabaseError(err error, operation string) error { return erro.Wrap(err, "database operation failed", "operation", operation, erro.StackTraceWithSkip(1), ) } ``` -------------------------------- ### Test Error Templates and Wrapping Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Provides unit testing examples for validating error template metadata, field injection, and error wrapping capabilities using the standard testing package. ```go func TestTemplateWrapping(t *testing.T) { originalErr := errors.New("connection refused") err := DatabaseError.Wrap(originalErr, "SELECT", "users") assert.True(t, errors.Is(err, originalErr)) } ``` -------------------------------- ### Configure Environment-Specific Stack Traces Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Demonstrates how to initialize error objects with varying levels of detail based on the deployment environment, ranging from full debugging info to strict security-focused output. ```go // Development err := erro.New("development error", "debug_info", "detailed context", erro.StackTrace(erro.DevelopmentStackTraceConfig()), ) // Production err := erro.New("production error", "request_id", "req_123", erro.StackTrace(erro.ProductionStackTraceConfig()), ) // Strict Security err := erro.New("security error", "event_type", "auth_failure", erro.StackTrace(erro.StrictStackTraceConfig()), ) ``` -------------------------------- ### Perform Stack Analysis and Filtering in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Demonstrates advanced stack manipulation, including filtering frames by package, checking for specific functions, and retrieving the call chain. ```go stack := err.Stack() userFrames := stack.UserFrames() topFrame := stack.TopUserFrame() callChain := stack.GetCallChain() packages := stack.ExtractPackages() if stack.ContainsFunction("processPayment") { fmt.Println("Error occurred in payment processing") } paymentFrames := stack.FilterByPackage("payment") ``` -------------------------------- ### Capture Stack Traces in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Demonstrates how to attach stack traces to errors using the erro package. Includes basic capture, custom configuration application, and frame skipping for wrapper functions. ```go err := erro.New("database connection failed", "host", "localhost", erro.StackTrace(), ) err := erro.New("payment failed", "amount", 100.50, erro.StackTrace(erro.ProductionStackTraceConfig()), ) err := erro.New("validation failed", erro.StackTraceWithSkip(2), ) ``` -------------------------------- ### Instantiate and Wrap Errors from Templates Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Shows how to generate new error instances from templates using .New() and how to wrap existing errors with additional context using .Wrap(). ```go err := ValidationError.New("invalid email format", "email", "not-an-email", "field", "user.email", ) originalErr := sql.ErrNoRows err := DatabaseError.Wrap(originalErr, "SELECT", "products", "query_id", "q123", "user_id", 456, ) ``` -------------------------------- ### Define Stack Trace Configurations in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Shows how to utilize predefined configurations like Development, Production, and Strict, as well as how to instantiate a custom StackTraceConfig struct for specific requirements. ```go config := erro.DevelopmentStackTraceConfig() config := erro.ProductionStackTraceConfig() config := erro.StrictStackTraceConfig() customConfig := &erro.StackTraceConfig{ ShowFileNames: true, ShowFullPaths: true, ShowFunctionNames: true, ShowPackageNames: true, ShowLineNumbers: true, ShowAllCodeFrames: true, PathElements: 2, FunctionRedacted: "[FUNC]", FileNameRedacted: "[FILE]", MaxFrames: 5, } err := erro.New("custom error", erro.StackTrace(customConfig)) ``` -------------------------------- ### Error Templates with Multiple Options in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Illustrates the power of combining multiple options within a single error template. The 'ComprehensiveTemplate' example includes classification, behavior (retryable), observability (stack trace, metrics), and custom formatting. ```go var ComprehensiveTemplate = erro.NewTemplate("operation %s failed for %s", // Classification erro.ClassInternal, erro.CategoryAPI, erro.SeverityHigh, // Behavior erro.Retryable(), erro.ID("API_OPERATION_FAILED"), // Observability erro.StackTrace(erro.ProductionStackTraceConfig()), erro.RecordMetrics(operationMetrics), // Formatting erro.Formatter(erro.FormatErrorWithFields), ) ``` -------------------------------- ### Advanced Frame Filtering and Monitoring Integration Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Techniques for manually filtering stack frames and extracting error context for external monitoring services. ```go // Custom Frame Filtering stack := err.Stack() filteredFrames := make(erro.Stack, 0) for _, frame := range stack { if strings.Contains(frame.Package, "myapp") { filteredFrames = append(filteredFrames, frame) } } // Integration with Monitoring if origin := stack.GetOriginContext(); origin != nil { monitoring.RecordError(map[string]interface{}{ "error_function": origin.Function, "error_file": origin.File, "error_line": origin.Line, "call_chain": strings.Join(stack.GetCallChain(), "->"), }) } ``` -------------------------------- ### Error Templates with Observability in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Demonstrates how to integrate observability features into error templates, such as recording metrics and sending events. The 'TracedTemplate' example includes configurations for metrics collection and event dispatching. ```go var TracedTemplate = erro.NewTemplate("traced operation failed: %s", erro.CategoryAPI, erro.SeverityMedium, erro.RecordMetrics(metricsCollector), erro.SendEvent(ctx, eventDispatcher), ) err := TracedTemplate.New("API request failed", "endpoint", "/api/users", "method", "POST", "user_id", userID, ) ``` -------------------------------- ### Utilize Predefined Error Templates Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Examples of using the built-in error templates provided by the erro package for common scenarios such as validation, authentication, database, and system errors. ```go erro.ValidationError.New("invalid user data", "field", "email", "value", userEmail, ) erro.AuthenticationError.New("login failed", "username", username, "ip_address", clientIP, ) erro.DatabaseError.New("query timeout", "table", "users", "timeout_ms", 10000, ) ``` -------------------------------- ### Error Templates with Stack Traces in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Shows how to configure error templates to include stack traces for better debugging. This example defines a 'CriticalTemplate' with critical severity and production stack trace configuration. ```go var CriticalTemplate = erro.NewTemplate("critical system error: %s", erro.ClassCritical, erro.SeverityCritical, erro.StackTrace(erro.ProductionStackTraceConfig()), ) err := CriticalTemplate.New("memory leak detected", "component", "payment_processor", "memory_mb", 2048, ) ``` -------------------------------- ### Access and Analyze Stack Traces in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Provides methods for printing stack traces, accessing frame data programmatically, and extracting context like origin functions or log fields. ```go fmt.Printf("Error with stack: %+v\n", err) stack := err.Stack() userFrames := stack.UserFrames() topFrame := stack.TopUserFrame() origin := stack.GetOriginContext() if origin != nil { fmt.Printf("Error originated in %s at line %d\n", origin.Function, origin.Line) } logFields := stack.ToLogFields() ``` -------------------------------- ### Install erro library Source: https://github.com/maxbolgarin/erro/blob/main/README.md Command to install the erro package via Go modules. ```bash go get -u github.com/maxbolgarin/erro ``` -------------------------------- ### Logging Errors with Zerolog Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Illustrates how to use the erro library with Zerolog, a high-performance Go logging library. This example shows converting erro fields to a map suitable for Zerolog's event-based logging. ```go logger := zerolog.New(os.Stdout) err := erro.New("service unavailable", "service", "payment-gateway", "timeout_ms", 5000, erro.CategoryExternal, erro.SeverityMedium, ) // Convert to map for zerolog fields := erro.LogFieldsMap(err) event := logger.Error() for k, v := range fields { event = event.Interface(k, v) } event.Msg("Service call failed") ``` -------------------------------- ### Capture and Configure Stack Traces in Go Source: https://context7.com/maxbolgarin/erro/llms.txt Illustrates how to capture stack traces during error creation and configure them for different environments like development, production, or strict security settings. Includes examples of accessing stack information programmatically. ```go package main import ( "fmt" "github.com/maxbolgarin/erro" ) func innerFunction() error { return erro.New("critical failure occurred", erro.StackTrace()) } func main() { err := innerFunction() fmt.Printf("Error with stack: %+v\n", err) // Environment-specific configs devErr := erro.New("debug error", erro.StackTrace(erro.DevelopmentStackTraceConfig())) prodErr := erro.New("production error", erro.StackTrace(erro.ProductionStackTraceConfig())) } ``` -------------------------------- ### Consistent Metadata for Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Emphasizes the importance of consistent metadata across related error templates. This example shows how to group database-related error templates with shared metadata like category and severity. ```go // Group related templates with consistent metadata var DatabaseTemplates = struct { Connection *erro.ErrorTemplate Query *erro.ErrorTemplate Migration *erro.ErrorTemplate }{ Connection: erro.NewTemplate("database connection failed: %s", erro.CategoryDatabase, erro.SeverityHigh, erro.Retryable()), Query: erro.NewTemplate("database query failed: %s", erro.CategoryDatabase, erro.SeverityMedium), Migration: erro.NewTemplate("database migration failed: %s", erro.CategoryDatabase, erro.SeverityCritical), } ``` -------------------------------- ### Error Templates with Custom Formatting in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Explains how to create custom error formatting for detailed context. The 'FormattedTemplate' example uses a formatter that includes severity, category, and function information in the error output. ```go var FormattedTemplate = erro.NewTemplate("custom formatted error: %s", erro.Formatter(erro.GetFormatErrorWithFullContext( erro.WithSeverity(true), erro.WithCategory(true), erro.WithFunction(true), )), ) err := FormattedTemplate.New("detailed context", "request_id", requestID, ) ``` -------------------------------- ### Custom Stack Trace Configuration Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Shows how to define a custom StackTraceConfig to control exactly which metadata is included in error reports, such as redaction strings and frame limits. ```go apiStackConfig := &erro.StackTraceConfig{ ShowFileNames: true, ShowFullPaths: false, ShowFunctionNames: true, ShowPackageNames: false, ShowLineNumbers: true, ShowAllCodeFrames: false, PathElements: 1, MaxFrames: 8, FunctionRedacted: "[API_FUNC]", FileNameRedacted: "[API_FILE]", } err := erro.New("API error", "endpoint", "/api/users", "method", "POST", erro.StackTrace(apiStackConfig), ) ``` -------------------------------- ### Monitoring/Alerting Environment Logging Configuration Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Configures log options for monitoring and alerting systems. This setup focuses on providing concise and actionable information by excluding user-specific fields and emphasizing severity, category, and function details. ```go alertLogOpts := []erro.LogOption{ erro.WithUserFields(false), // Exclude potentially noisy user fields erro.WithSeverity(true), erro.WithCategory(true), erro.WithFunction(true), erro.WithFieldNamePrefix("alert_"), } // Clean, focused alerts alertLogger.Error("Alert condition", erro.LogFields(err, alertLogOpts...)...) ``` -------------------------------- ### Business Logic Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Demonstrates the creation and usage of predefined business logic error templates such as insufficient balance, card declined, and rate limit exceeded. It also shows how to include additional context with these errors. ```go // Business logic error erro.BusinessLogicError.New("insufficient account balance") // Payment error erro.PaymentError.New("card declined") // Rate limit error erro.RateLimitError.New("API quota exceeded") // Example usage: bizErr := erro.BusinessLogicError.New("order validation failed", "order_id", orderID, "customer_id", customerID, "total_amount", total, "available_credit", credit, ) ``` -------------------------------- ### Organize Error Templates in a Single File Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Demonstrates defining global error templates within a single package file. This approach is suitable for small to medium projects where centralized error management is preferred. ```go package errors import "github.com/maxbolgarin/erro" var ( UserNotFound = erro.NewTemplate("user %s not found", erro.ClassNotFound) UserExists = erro.NewTemplate("user %s already exists", erro.ClassConflict) DBConnection = erro.NewTemplate("database connection failed: %s", erro.CategoryDatabase, erro.SeverityHigh) APITimeout = erro.NewTemplate("API timeout: %s", erro.ClassTimeout, erro.CategoryExternal, erro.Retryable()) ) ``` -------------------------------- ### Serialize Stack Traces to JSON in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/stack-trace-configuration.md Converts stack trace information into JSON format for logging or API responses, supporting both full stack and user-frame-only serialization. ```go stackJSON := stack.ToJSON() userStackJSON := stack.ToJSONUserFrames() ``` -------------------------------- ### Organize Error Templates by Package Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Demonstrates grouping error templates into domain-specific packages. This pattern improves maintainability for larger applications by scoping errors to their respective modules. ```go package user var Templates = struct { NotFound *erro.ErrorTemplate Validation *erro.ErrorTemplate }{ NotFound: erro.NewTemplate("user %s not found", erro.ClassNotFound), Validation: erro.NewTemplate("user validation failed: %s", erro.ClassValidation), } ``` -------------------------------- ### Define and Use Domain-Specific Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Demonstrates organizing business-logic errors into a structured collection for e-commerce domains. It shows how to define templates for inventory, order, and payment statuses and apply them within service layer methods. ```go var EcommerceTemplates = struct { OrderNotFound *erro.ErrorTemplate OrderCancelled *erro.ErrorTemplate OrderAlreadyPaid *erro.ErrorTemplate OutOfStock *erro.ErrorTemplate InsufficientStock *erro.ErrorTemplate PaymentDeclined *erro.ErrorTemplate PaymentTimeout *erro.ErrorTemplate }{ /* ... template initialization ... */ } func (s *OrderService) ProcessOrder(orderID string) error { order, err := s.getOrder(orderID) if err != nil { return EcommerceTemplates.OrderNotFound.Wrap(err, orderID, "order_id", orderID, ) } if order.Status == "cancelled" { return EcommerceTemplates.OrderCancelled.New(orderID, "order_id", orderID, "cancelled_at", order.CancelledAt, ) } // ... logic for stock and payment checks using EcommerceTemplates ... return nil } ``` -------------------------------- ### Resource & State Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Illustrates the use of various error templates for resource and state-related issues, including critical errors, temporary unavailability, data loss, resource exhaustion, cancellations, and unimplemented features. ```go // Critical error erro.CriticalError.New("memory leak detected") // Temporary error erro.TemporaryError.New("service temporarily unavailable") // Data loss error erro.DataLossError.New("backup corruption detected") // Resource exhausted erro.ResourceExhaustedError.New("memory limit exceeded") // Service unavailable erro.UnavailableError.New("maintenance mode") // Operation cancelled erro.CancelledError.New("user cancelled operation") // Not implemented erro.NotImplementedError.New("feature not available") // Already exists erro.AlreadyExistsError.New("user account exists") ``` -------------------------------- ### Define Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Demonstrates how to create reusable error templates using erro.NewTemplate, including support for message formatting verbs and metadata options like severity, category, and retryability. ```go var ValidationError = erro.NewTemplate("validation failed: %s", erro.ClassValidation, erro.CategoryUserInput, erro.SeverityLow, ) var DatabaseError = erro.NewTemplate("database %s failed on table %s", erro.CategoryDatabase, erro.SeverityHigh, erro.Retryable(), ) var PaymentError = erro.NewTemplate("payment processing failed: %s", erro.CategoryPayment, erro.ClassExternal, erro.SeverityCritical, erro.Retryable(), erro.ID("PAYMENT_ERROR"), ) ``` -------------------------------- ### Implement Service Layer Error Handling in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md This Go code illustrates how to define and use error templates within a service layer, specifically for user-related operations. It includes templates for 'Not Found', 'Validation', and 'Database' errors. The `UserService` struct holds these templates, and methods like `GetUser` and `CreateUser` demonstrate how to wrap underlying errors or create new ones using these templates, providing context and classification. ```go package main import ( "database/sql" "errors" "github.com/maxbolgarin/erro" ) type User struct { // User fields } type CreateUserRequest struct { // Request fields } type UserService struct { NotFoundError *erro.ErrorTemplate ValidationError *erro.ErrorTemplate DatabaseError *erro.ErrorTemplate db interface{} // Placeholder for database connection } func NewUserService() *UserService { return &UserService{ NotFoundError: erro.NewTemplate("user %s not found", erro.ClassNotFound, erro.CategoryBusinessLogic), ValidationError: erro.NewTemplate("user validation failed: %s", erro.ClassValidation, erro.CategoryUserInput), DatabaseError: erro.NewTemplate("user database operation failed: %s", erro.CategoryDatabase, erro.SeverityHigh), } } func (s *UserService) GetUser(id string) (*User, error) { // Placeholder for database call var user *User err := errors.New("simulated db error") // Replace with actual DB call if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, s.NotFoundError.New(id, "user_id", id) } return nil, s.DatabaseError.Wrap(err, "SELECT", "user_id", id, "table", "users", ) } return user, nil } func (s *UserService) CreateUser(req *CreateUserRequest) (*User, error) { // Placeholder for validation and database call if err := s.validateUser(req); err != nil { return nil, s.ValidationError.Wrap(err, "create user validation", "email", req.Email, "username", req.Username, ) } // Placeholder for database call var user *User err := errors.New("simulated db error") // Replace with actual DB call if err != nil { return nil, s.DatabaseError.Wrap(err, "INSERT", "email", req.Email, "table", "users", ) } return user, nil } // Placeholder for validation method func (s *UserService) validateUser(req *CreateUserRequest) error { return nil } ``` -------------------------------- ### Implement rich error handling in Go services Source: https://github.com/maxbolgarin/erro/blob/main/README.md A practical example showing how to create errors with context in a database function and handle them in an HTTP handler using automatic status code mapping and structured logging. ```go func GetUser(id int) (*User, error) { user, err := db.FindUser(id) if err != nil { return nil, erro.Wrap(err, "failed to retrieve user", "user_id", id, "table", "users", erro.ClassNotFound, erro.CategoryDatabase, ) } return user, nil } func UserHandler(w http.ResponseWriter, r *http.Request) { user, err := GetUser(123) if err != nil { statusCode := erro.HTTPCode(err) slog.Error("user retrieval failed", erro.LogFields(err)...) http.Error(w, err.Error(), statusCode) return } json.NewEncoder(w).Encode(user) } ``` -------------------------------- ### Implement Repository Layer Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Defines a repository struct that encapsulates error templates for database operations. It demonstrates how to initialize templates with categories and severity, and how to use them to wrap or create errors during database queries. ```go type UserRepository struct { ConnectionError *erro.ErrorTemplate QueryError *erro.ErrorTemplate NotFoundError *erro.ErrorTemplate } func NewUserRepository() *UserRepository { return &UserRepository{ ConnectionError: erro.NewTemplate("database connection failed: %s", erro.CategoryDatabase, erro.SeverityHigh, erro.Retryable()), QueryError: erro.NewTemplate("query failed: %s", erro.CategoryDatabase, erro.SeverityMedium), NotFoundError: erro.NewTemplate("user %s not found", erro.ClassNotFound, erro.CategoryDatabase), } } func (r *UserRepository) FindUser(id string) (*User, error) { query := "SELECT * FROM users WHERE id = ?" var user User err := r.db.QueryRow(query, id).Scan(&user.ID, &user.Email, &user.Name) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, r.NotFoundError.New(id, "user_id", id, "table", "users", ) } return nil, r.QueryError.Wrap(err, "user lookup", "user_id", id, "query", query, "table", "users", ) } return &user, nil } ``` -------------------------------- ### Naming Conventions for Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Provides guidelines for naming error templates and groups of related templates. It suggests using descriptive names ending in 'Error' or 'Template' and organizing related errors within a struct. ```go // Use descriptive names ending in Error or Template var UserNotFoundError = erro.NewTemplate("user %d not found", erro.ClassNotFound) var PaymentTemplate = erro.NewTemplate("payment %s failed", erro.CategoryPayment) // Group related templates var AuthErrors = struct { InvalidCredentials *erro.ErrorTemplate SessionExpired *erro.ErrorTemplate PermissionDenied *erro.ErrorTemplate }{ InvalidCredentials: erro.NewTemplate("authentication failed: %s", erro.ClassUnauthenticated, erro.CategoryAuth), SessionExpired: erro.NewTemplate("session expired: %s", erro.ClassUnauthenticated, erro.CategoryAuth), PermissionDenied: erro.NewTemplate("permission denied: %s", erro.ClassPermissionDenied, erro.CategoryAuth), } ``` -------------------------------- ### Handle HTTP Errors with Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md This Go code demonstrates how to use error templates within an HTTP handler to generate appropriate responses. It defines templates for common HTTP error conditions like 'Bad Request', 'Unauthorized', 'Not Found', and 'Server Error'. The `handleUserRequest` function shows how to check for missing parameters, convert service layer errors into HTTP-specific errors using the defined templates, and send the correct HTTP status code and error message to the client. ```go package main import ( "encoding/json" "errors" "net/http" "github.com/maxbolgarin/erro" ) // Assume userService and User, CreateUserRequest are defined elsewhere var userService *UserService // Placeholder var HTTPTemplates = struct { BadRequest *erro.ErrorTemplate Unauthorized *erro.ErrorTemplate NotFound *erro.ErrorTemplate ServerError *erro.ErrorTemplate }{ BadRequest: erro.NewTemplate("bad request: %s", erro.ClassValidation, erro.CategoryAPI), Unauthorized: erro.NewTemplate("unauthorized: %s", erro.ClassUnauthenticated, erro.CategoryAuth), NotFound: erro.NewTemplate("not found: %s", erro.ClassNotFound, erro.CategoryAPI), ServerError: erro.NewTemplate("server error: %s", erro.ClassInternal, erro.CategoryAPI, erro.SeverityHigh), } func handleUserRequest(w http.ResponseWriter, r *http.Request) { userID := r.URL.Query().Get("id") if userID == "" { err := HTTPTemplates.BadRequest.New("missing user ID", "parameter", "id", "method", r.Method, "path", r.URL.Path, ) http.Error(w, err.Error(), erro.HTTPCode(err)) return } user, err := userService.GetUser(userID) // Assume GetUser is from UserService if err != nil { var httpErr erro.Error // Convert service errors to HTTP errors if errors.Is(err, userService.NotFoundError) { httpErr = HTTPTemplates.NotFound.Wrap(err, "user lookup failed", "user_id", userID, ) } else { httpErr = HTTPTemplates.ServerError.Wrap(err, "user service error", "user_id", userID, ) } http.Error(w, httpErr.Error(), erro.HTTPCode(httpErr)) return } json.NewEncoder(w).Encode(user) } ``` -------------------------------- ### Stack Format Options (Go) Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Demonstrates different options for formatting stack traces in logs: String, List, Full, and JSON. Each format provides a different level of detail and structure. ```go // String Format (Default) erro.WithStackFormat(erro.StackFormatString) // Output: "main.processPayment -> payment.validateCard -> payment.checkBalance" // List Format erro.WithStackFormat(erro.StackFormatList) // Output: ["main.processPayment", "payment.validateCard", "payment.checkBalance"] // Full Format erro.WithStackFormat(erro.StackFormatFull) // Output: Multi-line detailed stack trace with file paths // main.processPayment // /app/main.go:42 // payment.validateCard // /app/payment/card.go:15 // JSON Format erro.WithStackFormat(erro.StackFormatJSON) // Output: [ // {"function": "main.processPayment", "file": "main.go", "line": "42", "type": "user"}, // {"function": "payment.validateCard", "file": "card.go", "line": "15", "type": "user"} // ] ``` -------------------------------- ### Apply Logging Best Practices Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Covers environment-specific configuration, consistent naming conventions, structured error context building, and security-conscious data redaction. ```go // Security-conscious logging with redaction err := erro.New("authentication failed", "username", username, "password", erro.Redact(password), "session_id", erro.Redact(sessionID), "user_agent", erro.Redact(userAgent), ) ``` -------------------------------- ### Predefined Log Configurations (Go) Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Shows how to use predefined log option sets like Default, Verbose, and Minimal to control the level of detail included in error logs. These options simplify common logging scenarios. ```go // Default Configuration opts := erro.DefaultLogOptions // Includes: user fields, category, severity, tracing, retryable, function // Excludes: ID, created time, package, file, line, stack fields := erro.LogFields(err) // Uses DefaultLogOptions // Verbose Configuration fields := erro.LogFields(err, erro.VerboseLogOpts...) // Includes everything for debugging: All user fields, Error ID, category, severity, Tracing information, Creation timestamp, Function, package, file, line, Full stack trace // Minimal Configuration fields := erro.LogFields(err, erro.MinimalLogOpts...) // Includes only: User fields, Severity level ``` -------------------------------- ### Implement Interface-Based Error Templates Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md Uses Go interfaces to define and implement error templates. This approach allows for dependency injection and easier mocking during unit testing. ```go type ErrorTemplates interface { NotFound(resource string, fields ...any) erro.Error } type userErrorTemplates struct { notFound *erro.ErrorTemplate } func (e *userErrorTemplates) NotFound(resource string, fields ...any) erro.Error { return e.notFound.New(resource, fields...) } ``` -------------------------------- ### Standard Library Compatibility with Erro Source: https://context7.com/maxbolgarin/erro/llms.txt Demonstrates Erro's compatibility with Go's standard library error handling functions like errors.Is, errors.As, errors.Unwrap, and errors.Join. It shows how Erro can be used as a drop-in replacement, ensuring seamless integration with existing Go codebases. The output confirms the correct behavior of these functions with Erro-wrapped errors. ```go package main import ( "database/sql" "errors" "fmt" "github.com/maxbolgarin/erro" ) var ErrNotFound = erro.New("resource not found", erro.ClassNotFound) func getResource(id int) error { if id == 0 { return ErrNotFound } if id < 0 { return erro.Wrap(sql.ErrNoRows, "invalid resource", "id", id) } return nil } func main() { err := getResource(0) // erro.Is - drop-in replacement for errors.Is if erro.Is(err, ErrNotFound) { fmt.Println("Resource not found!") } // erro.As - drop-in replacement for errors.As var erroErr erro.Error if erro.As(err, &erroErr) { fmt.Printf("Class: %s\n", erroErr.Class()) } // erro.Unwrap - drop-in replacement for errors.Unwrap wrapped := erro.Wrap(errors.New("base error"), "wrapper") unwrapped := erro.Unwrap(wrapped) fmt.Printf("Unwrapped: %v\n", unwrapped) // erro.Join - drop-in replacement for errors.Join err1 := erro.New("error 1") err2 := erro.New("error 2") err3 := erro.New("error 3") combined := erro.Join(err1, nil, err2, err3) // nil values are filtered fmt.Printf("Combined: %v\n", combined) // Works with standard errors.Is/As dbErr := erro.Wrap(sql.ErrNoRows, "query failed") if errors.Is(dbErr, sql.ErrNoRows) { fmt.Println("Standard errors.Is works!") } } ``` -------------------------------- ### Configuration Options (Go) Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Allows customization of logging behavior through functions that set the field name prefix and the stack trace format. ```go erro.WithFieldNamePrefix("svc_error_") // Custom prefix erro.WithStackFormat(erro.StackFormatJSON) // Stack format ``` -------------------------------- ### Benchmark Environment Information Source: https://github.com/maxbolgarin/erro/blob/main/README.md Details about the environment in which the benchmarks were run, including operating system, architecture, and CPU. ```text goos: darwin goarch: arm64 pkg: github.com/maxbolgarin/erro cpu: Apple M1 Pro ``` -------------------------------- ### Structured Logging with LogFields Source: https://context7.com/maxbolgarin/erro/llms.txt The `LogFields` and `LogFieldsMap` functions extract structured fields from errors for integration with logging frameworks like slog and logrus. This example shows how to log errors with varying levels of detail. ```APIDOC ## Structured Logging with LogFields ### Description The `LogFields` and `LogFieldsMap` functions extract structured fields from errors for integration with logging frameworks like slog and logrus. ### Method N/A (Function Usage) ### Endpoint N/A (Illustrative Example) ### Parameters N/A ### Request Example ```go // Create structured handler handler := slog.NewJSONHandler(os.Stdout, nil) logger := slog.New(handler) // Create error with metadata err := erro.New("payment processing failed", "order_id", 456, "customer_id", 789, "amount", 99.99, erro.CategoryPayment, erro.SeverityCritical, erro.StackTrace(), ) // Wrap with additional context err = erro.Wrap(err, "checkout failed", "cart_items", 3, "payment_method", "credit_card", ) // Log with slog using LogFields (returns []any for slog.Error) logger.Error("transaction error", erro.LogFields(err)...) // Log with minimal fields logger.Error("minimal log", erro.LogFields(err, erro.MinimalLogOpts...)...) // Log with verbose fields (includes stack trace, timing, etc.) logger.Error("verbose log", erro.LogFields(err, erro.VerboseLogOpts...)...) // For logrus-style logging using LogFieldsMap (returns map[string]any) fieldsMap := erro.LogFieldsMap(err) // Use with: logrus.WithFields(fieldsMap).Error("transaction error") // Custom log callback erro.LogError(err, func(message string, fields ...any) { logger.Error(message, fields...) }) ``` ### Response #### Success Response (200) N/A (Illustrative Example) #### Response Example N/A ``` -------------------------------- ### Running Benchmarks with Go Test Source: https://github.com/maxbolgarin/erro/blob/main/README.md Command to execute benchmarks for the Go project, including memory profiling, to assess performance characteristics. ```bash go test -bench . -benchmem ``` -------------------------------- ### Stack Information Options (Go) Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Offers functions to control the inclusion of stack trace information in logs, such as function name, package, file, line number, and the full stack trace. ```go erro.WithFunction(true) // Include function name erro.WithPackage(false) // Exclude package name erro.WithFile(false) // Exclude file name erro.WithLine(true) // Include line number erro.WithStack(true) // Include full stack trace ``` -------------------------------- ### HTTP Status Code Mapping with HTTPCode Source: https://context7.com/maxbolgarin/erro/llms.txt The `HTTPCode` function automatically maps error classes and categories to appropriate HTTP status codes for REST API integration. This example demonstrates its usage within an HTTP handler. ```APIDOC ## HTTP Status Code Mapping with HTTPCode ### Description The `HTTPCode` function automatically maps error classes and categories to appropriate HTTP status codes for REST API integration. ### Method N/A (Function Usage) ### Endpoint N/A (Illustrative Example) ### Parameters N/A ### Request Example ```go // Example within an HTTP handler if userID == "" { err := erro.New("user_id parameter is required", erro.ClassValidation, erro.CategoryUserInput, ) http.Error(w, err.Error(), erro.HTTPCode(err)) // Returns 400 return } ``` ### Response #### Success Response (200) N/A (Illustrative Example) #### Response Example N/A ### Error Class to HTTP Status Code Mappings - `ClassValidation` -> 400 Bad Request - `ClassNotFound` -> 404 Not Found - `ClassAlreadyExists` -> 409 Conflict - `ClassPermissionDenied` -> 403 Forbidden - `ClassUnauthenticated` -> 401 Unauthorized - `ClassTimeout` -> 504 Gateway Timeout - `ClassRateLimited` -> 429 Too Many Requests - `ClassTemporary` -> 503 Service Unavailable - `ClassExternal` -> 502 Bad Gateway - `ClassInternal` -> 500 Internal Server Error ``` -------------------------------- ### Define and Use Error Templates in Go Source: https://context7.com/maxbolgarin/erro/llms.txt Demonstrates how to define custom error templates with specific classes, categories, and severity levels using the erro package. Shows how to instantiate these templates and wrap existing errors with additional context. ```go package main import ( "errors" "fmt" "github.com/maxbolgarin/erro" ) var ( ErrUserNotFound = erro.NewTemplate("user with id %d not found", erro.ClassNotFound, erro.CategoryDatabase, erro.SeverityMedium, ) ) func findUser(id int) error { return ErrUserNotFound.New(id, "table", "users") } func processPayment(amount float64) error { dbErr := errors.New("connection timeout") return ErrPaymentFailed.Wrap(dbErr, "bank declined transaction", "amount", amount) } ``` -------------------------------- ### Define Payment Error Templates in Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/template-creation.md This snippet demonstrates how to define a set of error templates specific to payment-related operations. It uses the `erro.NewTemplate` function to create templates for common payment errors like gateway timeouts, insufficient funds, card declines, and fraud detection. These templates can be instantiated with specific details when an error occurs. ```go package main import ( "github.com/maxbolgarin/erro" ) // Create templates for specific domains var PaymentTemplates = struct { GatewayTimeout *erro.ErrorTemplate InsufficientFunds *erro.ErrorTemplate CardDeclined *erro.ErrorTemplate FraudDetected *erro.ErrorTemplate }{ GatewayTimeout: erro.NewTemplate("payment gateway timeout: %s", erro.ClassTimeout, erro.CategoryPayment, erro.Retryable()), InsufficientFunds: erro.NewTemplate("insufficient funds: %s", erro.ClassValidation, erro.CategoryPayment), CardDeclined: erro.NewTemplate("card declined: %s", erro.ClassValidation, erro.CategoryPayment), FraudDetected: erro.NewTemplate("fraud detected: %s", erro.ClassSecurity, erro.CategoryPayment, erro.SeverityCritical), } // Usage example (assuming orderID is defined) // err := PaymentTemplates.CardDeclined.New("expired card", // "card_last_four", "1234", // "expiry_date", "01/20", // "order_id", orderID, // ) ``` -------------------------------- ### Implement Service-Specific Logging with Go Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Demonstrates how to create a custom logger wrapper that injects service-specific metadata and environment-aware logging options. It utilizes the erro library to standardize log fields across different services. ```go type ServiceLogger struct { logger *slog.Logger logOpts []erro.LogOption service string } func NewServiceLogger(service string, isDev bool) *ServiceLogger { opts := []erro.LogOption{ erro.WithUserFields(true), erro.WithSeverity(true), erro.WithCategory(true), erro.WithFieldNamePrefix(service + "_"), } if isDev { opts = append(opts, erro.WithFunction(true), erro.WithStack(true), ) } return &ServiceLogger{ logger: slog.Default(), logOpts: opts, service: service, } } func (sl *ServiceLogger) Error(msg string, err erro.Error) { fields := erro.LogFields(err, sl.logOpts...) fields = append(fields, "service", sl.service) sl.logger.Error(msg, fields...) } ``` -------------------------------- ### Basic Log Field Usage with Different Loggers (Go) Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Demonstrates how to create a new error with context and log it using standard Go logging libraries like slog and logrus, as well as a custom logger integration. It shows how to extract log fields from the error object. ```go err := erro.New("database query failed", "table", "users", "query_time_ms", 150, "rows_affected", 0, ) // With slog slog.Error("Database operation failed", err.LogFields()...) // With logrus (using LogFieldsMap) logrus.WithFields(err.LogFieldsMap()).Error("Database operation failed") // Custom logger integration erro.LogError(err, func(message string, fields ...any) { myLogger.Error(message, fields...) }) ``` -------------------------------- ### Production Environment Logging Configuration Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Presents log options tailored for a production environment. This configuration prioritizes privacy and performance by excluding sensitive details like file paths, line numbers, and stack traces, while retaining essential information. ```go prodLogOpts := []erro.LogOption{ erro.WithUserFields(true), erro.WithSeverity(true), erro.WithCategory(true), erro.WithTracing(true), erro.WithFunction(true), erro.WithFile(false), // Hide file paths erro.WithLine(false), // Hide line numbers erro.WithStack(false), // No stack traces erro.WithFieldNamePrefix("prod_"), } // Privacy-aware logging logger.Error("Production error", erro.LogFields(err, prodLogOpts...)...) ``` -------------------------------- ### Capture and Print Stack Traces for Debugging (Go) Source: https://github.com/maxbolgarin/erro/blob/main/README.md Demonstrates capturing a stack trace for a critical system failure and printing the full error details, including file and line information, for debugging purposes. ```go // Capture stack traces for debugging func CriticalOperation() error { return erro.New("critical system failure", "component", "payment_processor", "transaction_id", txID, erro.StackTrace(), // Capture stack trace erro.ClassCritical, erro.SeverityCritical, ) } // Print detailed stack trace fmt.Printf("%+v\n", err) // Full stack trace with file:line info ``` -------------------------------- ### Access Error Metadata with Error Interface in Go Source: https://context7.com/maxbolgarin/erro/llms.txt Illustrates how to create and inspect errors with rich metadata using the `erro.Error` interface in Go. It shows how to add details like ID, class, category, severity, retryability, and stack traces, and how to access this information programmatically. ```go package main import ( "encoding/json" "fmt" "github.com/maxbolgarin/erro" ) func main() { err := erro.New("operation failed", "user_id", 123, "operation", "update", erro.ID("err-abc-123"), erro.ClassValidation, erro.CategoryUserInput, erro.SeverityMedium, erro.Retryable(), erro.StackTrace(), ) // Type assert to access Error interface erroErr := err.(erro.Error) // Access metadata fmt.Printf("ID: %s\n", erroErr.ID()) // err-abc-123 fmt.Printf("Class: %s\n", erroErr.Class()) // validation fmt.Printf("Category: %s\n", erroErr.Category()) // user_input fmt.Printf("Severity: %s\n", erroErr.Severity()) // medium fmt.Printf("Retryable: %t\n", erroErr.IsRetryable()) // true fmt.Printf("Message: %s\n", erroErr.Message()) // operation failed fmt.Printf("Created: %s\n", erroErr.Created()) // timestamp // Access fields fmt.Printf("Fields: %v\n", erroErr.Fields()) // [user_id 123 operation update] fmt.Printf("All Fields: %v\n", erroErr.AllFields()) // Includes wrapped error fields // Access stack trace stack := erroErr.Stack() fmt.Printf("Stack length: %d\n", len(stack)) // JSON serialization jsonData, _ := json.MarshalIndent(erroErr, "", " ") fmt.Printf("JSON:\n%s\n", jsonData) // Convert to schema schema := erro.ErrorToJSON(erroErr) fmt.Printf("Schema ID: %s\n", schema.ID) fmt.Printf("Schema Class: %s\n", schema.Class) // Access base error (for wrapped errors) wrapped := erro.Wrap(err, "wrapper message").(erro.Error) base := wrapped.BaseError() if base != nil { fmt.Printf("Base message: %s\n", base.Message()) } } ``` -------------------------------- ### Logging Errors with Slog (Standard Library) Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Shows how to integrate the erro library with Go's standard slog logger. It demonstrates basic error logging and advanced integration with custom options like severity, category, and tracing. ```go logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) err := erro.New("payment processing failed", "order_id", 12345, "amount", 99.99, "currency", "USD", erro.CategoryPayment, erro.SeverityCritical, ) // Basic integration logger.Error("Payment failed", erro.LogFields(err)...) // With custom options logger.Error("Payment failed", erro.LogFields(err, erro.WithSeverity(true), erro.WithCategory(true), erro.WithTracing(true), )... ) ``` -------------------------------- ### Optimize Performance with Lazy Generation and Caching Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Techniques for improving performance by deferring expensive field computation until the log event occurs and implementing custom caching for repeated error field generation. ```go // Lazy field generation err := erro.New("expensive operation failed", "large_data", someExpensiveToStringData) fields := erro.LogFields(err) // Computation happens now // Field caching type CachedFieldsError struct { erro.Error cachedFields []any } func (e *CachedFieldsError) LogFields(opts ...erro.LogOptions) []any { if e.cachedFields == nil { e.cachedFields = e.Error.LogFields(opts...) } return e.cachedFields } ``` -------------------------------- ### Wrap errors with rich context in Go Source: https://github.com/maxbolgarin/erro/blob/main/README.md Demonstrates how to transition from standard error handling to using 'erro.Wrap' to include metadata, HTTP status classes, and observability hooks like OpenTelemetry spans. ```go // Standard Go return fmt.Errorf("user operation failed: %w", err) // erro return erro.Wrap(err, "failed to update user profile", "user_id", userID, "operation", "profile_update", erro.ClassValidation, erro.CategoryUserInput, erro.SeverityMedium, erro.RecordSpan(span), erro.RecordMetrics(metrics), erro.SendEvent(ctx, dispatcher), ) ``` -------------------------------- ### Logging Errors with Logrus Source: https://github.com/maxbolgarin/erro/blob/main/docs/log-fields-configuration.md Demonstrates integrating the erro library with the logrus logging framework. It covers basic error logging and advanced usage with custom options, including field prefixes. ```go logger := logrus.New() logger.SetFormatter(&logrus.JSONFormatter{}) err := erro.New("database connection lost", "host", "db.example.com", "port", 5432, "database", "users", erro.CategoryDatabase, erro.SeverityHigh, ) // Basic integration logger.WithFields(erro.LogFieldsMap(err)).Error("Database error") // With custom options customFields := erro.LogFieldsMap(err, erro.WithUserFields(true), erro.WithSeverity(true), erro.WithFunction(true), erro.WithFieldNamePrefix("db_"), ) logger.WithFields(customFields).Error("Database connection failed") ``` -------------------------------- ### Migration from Standard Errors to Erro (Go) Source: https://github.com/maxbolgarin/erro/blob/main/README.md Illustrates the process of migrating from Go's standard `errors` package to the `erro` package, showing a drop-in replacement and a gradual enhancement strategy. ```go // Before: Standard errors import "errors" err := errors.New("something failed") ``` ```go // After: Rich errors import "github.com/maxbolgarin/erro" err := erro.New("something failed") // All standard functions still work if erro.Is(err, err1) { ... } // ✅ Workserro.Unwrap(err1) // ✅ Works ``` ```go // Phase 1: Basic replacement - return errors.New("user not found") + return erro.New("user not found") // Phase 2: Add context + return erro.New("user not found", "user_id", id) // Phase 3: Add classification + return erro.New("user not found", "user_id", id, erro.ClassNotFound) // Phase 4: Full features + return erro.New("user not found", + "user_id", id, + "table", "users", + erro.ClassNotFound, + erro.CategoryDatabase, + ) ```