### Run Go Example and Print All Output Source: https://github.com/samber/oops/blob/main/examples/sources/README.md Execute the Go example program and pipe its entire output to `jq` for pretty-printing. ```sh go run examples/sources/example.go | jq ``` -------------------------------- ### Quick Start Source: https://github.com/samber/oops/blob/main/README.md A brief introduction and example of how to use the Oops library for composing structured errors. ```APIDOC ## Quick Start ### Description This library provides a simple `error` builder for composing structured errors, with contextual attributes and stack trace. Since `oops.OopsError` implements the `error` interface, you will be able to compose and wrap native errors with `oops.OopsError`. ### Code Example ```go import "github.com/samber/oops" func main() { // Simple error with context err := oops. In("user-service"). Tags("database", "postgres"). Code("network_failure"). User("user-123", "email", "foo@bar.com"). With("path", "/hello/world"). Errorf("failed to fetch user: %s", "connection timeout") // Error wrapping if err != nil { return oops. Trace("req-123"). With("product_id", "456"). Wrapf(err, "user operation failed") } } ``` ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/samber/oops/blob/main/README.md Use this command to install necessary development tools for the project. ```bash # Install some dev dependencies make tools ``` -------------------------------- ### Run Go log logger example Source: https://github.com/samber/oops/blob/main/examples/log/README.md Execute the example Go program that utilizes the standard library's log logger. ```sh go run examples/log/example.go ``` -------------------------------- ### Install Oops Go Library Source: https://github.com/samber/oops/blob/main/README.md Use 'go get' to install the Oops library. This library is version 1 and adheres to SemVer. It has no external dependencies. ```sh go get github.com/samber/oops # AI Agent Skill: npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-oops ``` -------------------------------- ### Run Go Example and Print Specific Error Sources Source: https://github.com/samber/oops/blob/main/examples/sources/README.md Execute the Go example program and pipe its output to `jq`, filtering to display only the error sources in raw format. ```sh go run examples/sources/example.go | jq .error.sources -r ``` -------------------------------- ### Integration Examples Source: https://github.com/samber/oops/blob/main/docs/API.md Examples of integrating the Oops library with popular Go logging frameworks. ```APIDOC ## Integration with Zap Logger ### Description Example of logging an Oops error using the Zap logger. ### Request Example ```go logger, _ := zap.NewProduction() err := oops.Errorf("database connection failed") logger.Error("error occurred", zap.Any("error", err)) ``` ## Integration with Zerolog ### Description Example of logging an Oops error using the Zerolog logger. ### Request Example ```go logger := zerolog.New(os.Stdout).With().Timestamp().Logger() err := oops.Errorf("authentication failed") logger.Error().Interface("error", err).Msg("auth error") ``` ## Integration with Logrus ### Description Example of logging an Oops error using the Logrus logger. ### Request Example ```go logger := logrus.New() err := oops.Errorf("file not found") logger.WithField("error", err).Error("file operation failed") ``` ## Integration with Slog ### Description Example of logging an Oops error using the Slog logger. ### Request Example ```go logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) err := oops.Errorf("network timeout") logger.Error("network error", slog.Any("error", err)) ``` ``` -------------------------------- ### Run Zerolog Example and Pipe to jq Source: https://github.com/samber/oops/blob/main/examples/zerolog/README.md Execute the Zerolog example Go program and pipe its standard error output to jq for JSON parsing. This is useful for inspecting structured logs. ```sh go run examples/zerolog/example.go 2>&1 | jq ``` -------------------------------- ### Run Segfault Example and Parse Output Source: https://github.com/samber/oops/blob/main/examples/segfault/README.md Execute the Go segfault example and pipe its output to jq for JSON parsing. This is useful for inspecting the raw segfault data. ```sh go run examples/segfault/example.go 2>&1 | jq ``` ```sh go run examples/segfault/example.go 2>&1 | jq .stacktrace -r ``` -------------------------------- ### Migrate from pkg/errors to oops.Wrapf Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Example showing migration from pkg/errors to Oops, using In() for domain, With() for attributes, and Wrapf() for wrapping. ```go // Before return errors.Wrapf(err, "failed to process user %d", userID) // After return oops. In("user_processing"). With("user_id", userID). Wrapf(err, "failed to process user %d", userID) ``` -------------------------------- ### Run Zerolog Example and Extract Stack Trace Source: https://github.com/samber/oops/blob/main/examples/zerolog/README.md Execute the Zerolog example Go program and pipe its standard error output to jq, specifically extracting the 'stack' field in raw format. This is useful for debugging and analyzing stack traces from logs. ```sh go run examples/zerolog/example.go 2>&1 | jq .stack -r ``` -------------------------------- ### Run Slog Logger Example and Pipe to jq Source: https://github.com/samber/oops/blob/main/examples/slog/README.md Execute the slog logger example and pipe its output to jq for pretty-printing JSON. This is useful for inspecting log output. ```sh go run examples/slog/example.go | jq ``` -------------------------------- ### Standard Go Error Handling Example Source: https://github.com/samber/oops/blob/main/docs/COMPARISON.md Demonstrates basic error creation and wrapping using fmt.Errorf. Suitable for simple error reporting without extensive context. ```go func processUser(userID int) error { if userID <= 0 { return fmt.Errorf("invalid user ID: %d", userID) } if err := databaseOperation(userID); err != nil { return fmt.Errorf("failed to process user %d: %w", userID, err) } return nil } ``` -------------------------------- ### Run Logrus Example and Pipe to jq Source: https://github.com/samber/oops/blob/main/examples/logrus/README.md Execute the Logrus example script and pipe its standard error output to jq for JSON parsing. This is useful for inspecting structured logs. ```sh go run examples/logrus/example.go 2>&1 | jq ``` -------------------------------- ### Migrate from fmt.Errorf to oops.Errorf Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Example demonstrating migration from standard Go errors to Oops, using In() for domain, With() for attributes, and Wrapf() for wrapping. ```go // Before return fmt.Errorf("failed to process user %d: %w", userID, err) // After return oops. In("user_processing"). With("user_id", userID). Wrapf(err, "failed to process user %d", userID) ``` -------------------------------- ### Run Go Panic Example and Pipe to jq Source: https://github.com/samber/oops/blob/main/examples/panic/README.md Execute a Go program that might panic and pipe its standard error to `jq` for JSON parsing. This is useful for structured error inspection. ```sh go run examples/panic/example.go 2>&1 | jq ``` -------------------------------- ### Log an Error with Oops and Zerolog Source: https://github.com/samber/oops/blob/main/loggers/zerolog/README.md Create and log an error using Oops's fluent API, then log it with Zerolog, including the stack trace. This example demonstrates how to attach context to an error and then output it using Zerolog's structured logging. ```go func main() { err := oops. With("driver", "postgresql"). With("query", query). With("query.duration", queryDuration). Errorf("could not fetch user") if err != nil { zerolog.New(os.Stderr).Error().Stack().Err(err).Msg(err.Error()) } } ``` -------------------------------- ### Create New Errors with `oops.New` Source: https://github.com/samber/oops/blob/main/README.md This example shows how to create a basic `OopsError` using the `New` method, providing only a message string. Contextual information can be added using chained methods like `In` and `Tags`. ```go // oops.New err3 := oops. In("repository"). Tags("database", "sql"). New("an error message") ``` -------------------------------- ### Update Oops Dependency in Go Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Use the `go get` command to update the Oops library to the latest version. This command fetches and installs the specified package and its dependencies. ```bash go get -u github.com/samber/oops ``` -------------------------------- ### Set Error Duration from Start Time using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.Since()` builder method to calculate and set the error duration based on a provided start time. ```go start := time.Now() // ... do work ... err := oops.Since(start).Errorf("operation took too long") ``` -------------------------------- ### Extract Stacktrace with jq Source: https://github.com/samber/oops/blob/main/examples/logrus/README.md Run the Logrus example script and specifically extract the 'stacktrace' field from the JSON output using jq with the -r flag for raw output. This is helpful for debugging. ```sh go run examples/logrus/example.go 2>&1 | jq .stacktrace -r ``` -------------------------------- ### Handle Errors in Go HTTP Handlers Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Implement robust error handling in Go HTTP handlers using the Oops library. This example shows how to handle missing parameters, log full errors for debugging, and return user-safe messages. ```go func userHandler(w http.ResponseWriter, r *http.Request) { userID := r.URL.Query().Get("user_id") if userID == "" { err := oops. Code("missing_user_id"). Request(r, false). Public("User ID is required"). Errorf("missing user_id parameter") http.Error(w, err.Error(), http.StatusBadRequest) return } if err := processUser(userID); err != nil { // Log the full error for debugging logger.Error("user processing failed", zap.Any("error", err)) // Return user-safe message publicMsg := oops.GetPublic(err, "An unexpected error occurred") http.Error(w, publicMsg, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) } ``` -------------------------------- ### Extract Slog Error Stacktrace with jq Source: https://github.com/samber/oops/blob/main/examples/slog/README.md Run the slog logger example and use jq to extract and display the error stacktrace in raw format. This helps in debugging specific error details. ```sh go run examples/slog/example.go | jq .error.stacktrace -r ``` -------------------------------- ### Integrate Oops Errors with Zap Logger in Go Source: https://github.com/samber/oops/blob/main/docs/API.md Example of logging an Oops error using the Zap logger. The error object is passed as an any type, allowing Zap to inspect its details. ```go logger, _ := zap.NewProduction() err := oops.Errorf("database connection failed") logger.Error("error occurred", zap.Any("error", err)) ``` -------------------------------- ### Adding Debugging Hints Source: https://github.com/samber/oops/blob/main/README.md Demonstrates using `.Hint()` to provide additional information that aids in debugging the error. ```go err.Hint() string ``` -------------------------------- ### Checking for Oops Error Type Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Provides an example of how to check if a given error is an instance of OopsError using errors.As. ```go var oopsErr oops.OopsError if errors.As(err, &oopsErr) { // This is an Oops error fmt.Printf("Code: %v\n", oopsErr.Code()) } else { // This is not an Oops error fmt.Printf("Standard error: %s\n", err.Error()) } ``` -------------------------------- ### Get User-Safe Error Message in Go Source: https://github.com/samber/oops/blob/main/docs/API.md Use oops.GetPublic to extract a user-friendly message from an error. Provides a default message if a public message cannot be determined. ```go publicMsg := oops.GetPublic(err, "An unexpected error occurred") ``` -------------------------------- ### Run Tests Source: https://github.com/samber/oops/blob/main/README.md Commands to execute the project's test suite. 'make watch-test' provides a continuous testing experience. ```bash # Run tests make test # or make watch-test ``` -------------------------------- ### Retrieve Error Builder from Context in Go Source: https://github.com/samber/oops/blob/main/docs/API.md Use oops.FromContext to get an error builder that is already associated with a Go context. This allows errors to be propagated and enriched through context. ```go builder := oops.FromContext(ctx) err := builder.Errorf("context error") ``` -------------------------------- ### Create Simple Error with Stacktrace Source: https://github.com/samber/oops/blob/main/README.md Use this to create a basic error with a stack trace. ```go err1 := oops.New("could not fetch user") ``` -------------------------------- ### Integrate Oops Errors with Slog in Go Source: https://github.com/samber/oops/blob/main/docs/API.md Example of logging an Oops error with Go's standard slog logger. The error is passed as a slog.Any attribute for structured logging. ```go logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) err := oops.Errorf("network timeout") logger.Error("network error", slog.Any("error", err)) ``` -------------------------------- ### Create Permission Denied Error in Go Source: https://github.com/samber/oops/blob/main/assets/README.md Use this to create a detailed error with context, user information, and a runbook hint. It's useful for indicating permission issues. ```go func d() { Time(time.Now()). With("user_id", 1234). With("permission", "post.create"). Hint("Runbook: https://doc.acme.org/doc/abcd.md"). User("user-123", "firstname", "john", "lastname", "doe"). Errorf("permission denied") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^```json{ ``` -------------------------------- ### Comparison: pkg/errors vs. Oops Error Handling Source: https://github.com/samber/oops/blob/main/docs/COMPARISON.md Shows equivalent error handling logic using both pkg/errors for stack traces and Oops for richer context and structured attributes. ```go // pkg/errors import "github.com/pkg/errors" func processUser(userID int) error { if userID <= 0 { return errors.Errorf("invalid user ID: %d", userID) } if err := databaseOperation(userID); err != nil { return errors.Wrapf(err, "failed to process user %d", userID) } return nil } // Oops import "github.com/samber/oops" func processUser(userID int) error { if userID <= 0 { return oops. Code("invalid_user_id"). In("user_processing"). With("user_id", userID). Errorf("invalid user ID: %d", userID) } if err := databaseOperation(userID); err != nil { return oops. In("user_processing"). With("user_id", userID). Wrapf(err, "failed to process user %d", userID) } return nil } ``` -------------------------------- ### Create and Format Errors Source: https://github.com/samber/oops/blob/main/docs/EXAMPLES.md Use `oops.New` for basic errors and `oops.Errorf` for formatted errors. These functions are fundamental for creating error instances. ```go package main import ( "fmt" "github.com/samber/oops" ) func main() { // Basic error err := oops.New("something went wrong") fmt.Println(err) // Formatted error err = oops.Errorf("failed to process user %d", 123) fmt.Println(err) } ``` -------------------------------- ### Add Tenant Information using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.Tenant()` builder method to attach tenant-specific identifiers and attributes to the error. ```go err := oops.Tenant("tenant-456", map[string]any{ "name": "Acme Corp", "plan": "premium", }).Errorf("tenant operation failed") ``` -------------------------------- ### Include User and Tenant Context Source: https://github.com/samber/oops/blob/main/docs/EXAMPLES.md Enrich errors with user and tenant-specific data using `User` and `Tenant` methods. This is useful for auditing and debugging issues related to specific users or tenants. ```go func processOrder(userID string, orderID string, tenantID string) error { userData := map[string]any{ "email": "john@example.com", "role": "customer", "plan": "premium", } tenantData := map[string]any{ "name": "Acme Corp", "plan": "enterprise", "region": "us-west", } // Simulate order processing error return oops. Code("order_processing_failed"). In("order_management"). Tags("order", "processing"). Trace("e76031ee-a0c4-4a80-88cb-17086fdd19c0"). Span("order_creation"). User(userID, userData). Tenant(tenantID, tenantData). With("order_id", orderID). With("amount", 99.99). Hint("Check inventory and payment processing"). Owner("orders-team@company.com"). Errorf("failed to process order %s for user %s", orderID, userID) } ``` -------------------------------- ### Create Basic and Formatted Errors in Go Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Use `oops.New` for simple error messages and `oops.Errorf` for formatted error messages with arguments. ```go // Basic error err := oops.New("something went wrong") ``` ```go // Formatted error err := oops.Errorf("failed to process user %d", userID) ``` -------------------------------- ### Create Error with Hint and Ownership Source: https://github.com/samber/oops/blob/main/README.md Use this to provide a hint for developers on how to solve the issue and specify the owner of the error. ```go err5 := oops. Hint("The user could have been removed. Please check deleted_at column."). Owner("Slack: #api-gateway"). Errorf("could not fetch user") ``` -------------------------------- ### Create Error with User and Tenant Data Source: https://github.com/samber/oops/blob/main/README.md Use this to attach both user and tenant information, including maps and slog.Attr. ```go err8 := oops. User(userID, "firstname", "Samuel"). Tenant(workspaceID, map[string]any{"name": "my little project"}, slog.String("country", "fr"), "locale", "fr-FR"). Errorf("could not fetch user") ``` -------------------------------- ### Test Oops Errors Using errors.As Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Demonstrates how to test Oops errors by asserting the error type and checking its properties like Code() and Domain(). ```go func TestUserProcessing(t *testing.T) { err := processUser(0) var oopsErr oops.OopsError if !errors.As(err, &oopsErr) { t.Fatal("expected OopsError") } if oopsErr.Code() != "invalid_user_id" { t.Errorf("expected code 'invalid_user_id', got %s", oopsErr.Code()) } if oopsErr.Domain() != "user_processing" { t.Errorf("expected domain 'user_processing', got %s", oopsErr.Domain()) } } ``` -------------------------------- ### Define and Use Error Codes in Go Source: https://github.com/samber/oops/blob/main/docs/EXAMPLES.md Shows how to define error codes as constants and use them with Oops for standardized error reporting. This promotes consistency in error handling across the application. ```go // Define error codes as constants const ( ErrCodeAuthFailed = "auth_failed" ErrCodeValidationFailed = "validation_failed" ErrCodeDatabaseError = "database_error" ErrCodeNetworkTimeout = "network_timeout" ErrCodeFileNotFound = "file_not_found" ErrCodePermissionDenied = "permission_denied" ) func authenticateUser(username, password string) error { if username == "" { return oops. Code(ErrCodeValidationFailed). In("authentication"). Tags("auth", "validation"). With("field", "username"). Hint("Username is required"). Errorf("missing username") } // Simulate authentication failure return oops. Code(ErrCodeAuthFailed). In("authentication"). Tags("auth", "security"). With("username", username). Hint("Check credentials"). Public("Invalid username or password"). Errorf("authentication failed for user %s", username) } ``` -------------------------------- ### Create and Log Errors with Slog Source: https://github.com/samber/oops/blob/main/docs/EXAMPLES.md Demonstrates creating a structured error with Oops and logging it using Go's slog package. Ensure slog is imported and configured. ```go package main import ( "log/slog" "os" "github.com/samber/oops" ) func main() { logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) err := oops. Code("validation_error"). In("validation"). Tags("validation", "input"). With("field", "email"). With("value", "invalid-email"). Hint("Email must be in valid format (e.g., user@domain.com)"). Public("Please enter a valid email address"). Errorf("invalid email format: %s", "invalid-email") logger.Error("Validation failed", slog.Any("error", err), slog.String("operation", "validate_email"), ) } ``` -------------------------------- ### Add Debugging Hint using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.Hint()` builder method to provide developers with specific debugging suggestions or information. ```go err := oops.Hint("Check database connection and user permissions").Errorf("database error") ``` -------------------------------- ### Chaining Builder Methods in Oops Source: https://github.com/samber/oops/blob/main/README.md Illustrates chaining multiple builder methods, such as `oops.In` and `oops.User`, to progressively build a more detailed error object. This approach allows for complex error construction. ```go oops.In("iam").User("user-42") ``` -------------------------------- ### Oops Error Handling with Context and Attributes Source: https://github.com/samber/oops/blob/main/docs/COMPARISON.md Illustrates Oops's fluent API for adding rich context, codes, tags, and hints to errors. Useful for detailed error reporting and debugging. ```go func processUser(userID int) error { if userID <= 0 { return oops. Code("invalid_user_id"). In("user_processing"). Tags("validation", "user"). With("user_id", userID). Hint("User ID must be a positive integer"). Errorf("invalid user ID: %d", userID) } if err := databaseOperation(userID); err != nil { return oops. In("user_processing"). Tags("database", "user"). With("user_id", userID). Wrapf(err, "failed to process user %d", userID) } return nil } ``` -------------------------------- ### Correct Error Wrapping with Wrapf Source: https://github.com/samber/oops/blob/main/README.md Illustrates the correct way to use oops.Wrapf to chain errors, avoiding common pitfalls. Always return the result of Wrapf directly. ```go return oops.Wrapf(mayFail(), ...) ``` -------------------------------- ### Add User Information using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.User()` builder method to attach user-specific identifiers and attributes to the error. ```go err := oops.User("user-123", map[string]any{ "email": "john@example.com", "role": "admin", }).Errorf("user operation failed") ``` -------------------------------- ### Add Debugging Hints to Errors Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Utilize Hint() to provide developers with debugging information to help resolve issues quickly. ```go err := oops. Hint("Check database connection and user permissions"). Errorf("database error") ``` -------------------------------- ### Integrate with Zerolog in Go Source: https://github.com/samber/oops/blob/main/docs/EXAMPLES.md Log errors with context using `zerolog`. The `oops` library's error details can be passed as an interface to Zerolog's `Error` method for structured logging. ```go package main import ( "os" "github.com/samber/oops" "github.com/rs/zerolog" ) func main() { logger := zerolog.New(os.Stdout).With().Timestamp().Logger() err := oops. Code("file_not_found"). In("file_system"). Tags("file", "io"). With("path", "/tmp/file.txt"). Hint("Check if file exists and has proper permissions"). Errorf("file not found: %s", "/tmp/file.txt") logger.Error(). Interface("error", err). Msg(err.Error()) } ``` -------------------------------- ### Build Structured Errors with Context Source: https://github.com/samber/oops/blob/main/README.md Use this to create a simple error with context, tags, and specific attributes. Ensure the `github.com/samber/oops` package is imported. ```go import "github.com/samber/oops" func main() { // Simple error with context err := oops. In("user-service"). Tags("database", "postgres"). Code("network_failure"). User("user-123", "email", "foo@bar.com"). With("path", "/hello/world"). Errorf("failed to fetch user: %s", "connection timeout") // Error wrapping if err != nil { return oops. Trace("req-123"). With("product_id", "456"). Wrapf(err, "user operation failed") } } ``` -------------------------------- ### Create Error with Domain and Tags Source: https://github.com/samber/oops/blob/main/README.md Use this to add domain context and tags to an error, useful for categorizing errors. ```go err2 := oops. In("repository"). Tags("database", "sql"). Errorf("could not fetch user") ``` -------------------------------- ### Create New Error with Message Source: https://github.com/samber/oops/blob/main/docs/API.md Use `oops.New` to create a basic error with a simple string message. ```go err := oops.New("something went wrong") ``` -------------------------------- ### Create Error with User Data (Map and slog.Attr) Source: https://github.com/samber/oops/blob/main/README.md Use this to attach user data using a map and slog.Attr for structured logging attributes. ```go err7b := oops. User(userID, map[string]any{"plan": "pro"}, slog.String("email", "samuel@example.com"), "name", "Samuel"). Errorf("could not fetch user") ``` -------------------------------- ### Reuse ErrorBuilder from Context Source: https://github.com/samber/oops/blob/main/README.md Demonstrates how to retrieve and reuse an existing OopsErrorBuilder that was previously stored in a Go context. ```go ctx := oops.WithBuilder(context.TODO(), err9) // [...] err10 := oops. FromContext(ctx). Errorf("could not fetch user") ``` -------------------------------- ### Using Oops Error Builder Standalone Source: https://github.com/samber/oops/blob/main/README.md Demonstrates how to use the `oops.With` method independently to add context to an error. This is useful for simple error enrichment. ```go oops.With("key", "value") ``` -------------------------------- ### Setting Error Domain Source: https://github.com/samber/oops/blob/main/README.md Demonstrates using `.In()` to categorize an error by its feature or domain. This helps in organizing and filtering errors by their origin. ```go err.Domain() string ``` -------------------------------- ### Setting User-Friendly Error Messages Source: https://github.com/samber/oops/blob/main/README.md Demonstrates setting a public-facing message using `.Public()`. This message is intended to be safely displayed to end-users. ```go err.Public() string ``` -------------------------------- ### Create Error with User ID and Attributes Source: https://github.com/samber/oops/blob/main/README.md Use this to attach a user ID along with string key-value attributes. ```go err7 := oops. User(userID, "firstname", "Samuel"). Errorf("could not fetch user") ``` -------------------------------- ### Log Full Error Context with Zap Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Illustrates the correct way to log an error object with Zap logger to include the full error context, not just the message string. ```go // Wrong - only logs the message logger.Error(err.Error()) // Correct - logs the full error context logger.Error(err.Error(), zap.Any("error", err)) ``` -------------------------------- ### Wrap Multiple Errors with Oops in Go Source: https://github.com/samber/oops/blob/main/docs/ARCHITECTURE.md Shows how to efficiently wrap multiple errors using `Wrap3`, a specialized function for cases where three return values are expected alongside an error. This is cleaner than manually handling each return value. ```go // ❌ Bad a, b, c, err := mayFail() if err != nil { return a, b, c, oops.Wrap(err) } return a, b, c, nil // ✅ Good return oops.With("key", "value"). Tenant("user-123"). Wrap3(mayFail(), "an error") ``` -------------------------------- ### Integrate Oops Errors with Zerolog in Go Source: https://github.com/samber/oops/blob/main/docs/API.md Demonstrates logging an Oops error with Zerolog. The error is added as an interface field, enabling Zerolog to handle it appropriately. ```go logger := zerolog.New(os.Stdout).With().Timestamp().Logger() err := oops.Errorf("authentication failed") logger.Error().Interface("error", err).Msg("auth error") ``` -------------------------------- ### Initialize Oops Zerolog Formatters Source: https://github.com/samber/oops/blob/main/loggers/zerolog/README.md Configure Zerolog to use Oops's custom marshallers for error stacks and messages during initialization. This ensures that errors created with Oops are logged with their full context and stack traces by Zerolog. ```go import oopszerolog "github.com/samber/oops/loggers/zerolog" func init() { zerolog.ErrorStackMarshaler = oopszerolog.OopsStackMarshaller zerolog.ErrorMarshalFunc = oopszerolog.OopsMarshalFunc } ``` -------------------------------- ### Lazy Stack Trace Formatting in Go Oops Errors Source: https://github.com/samber/oops/blob/main/docs/ARCHITECTURE.md Illustrates lazy evaluation of stack traces. The `format()` method is only called if `e.stackTrace` is not nil, optimizing performance by avoiding unnecessary computation. ```go func (e *oopsError) ToMap() slog.Attr { if e.stackTrace != nil { output["stacktrace"] = e.stacktrace.format() } return output } ``` -------------------------------- ### Perform Assertions with Formatted Messages Source: https://github.com/samber/oops/blob/main/README.md Use `Assertf` to check conditions and generate an error with a formatted message if the assertion fails. This is useful for critical, unexpected errors. ```go func mayPanic() { x := 42 oops. Trace("6710668a-2b2a-4de6-b8cf-3272a476a1c9"). Hint("Runbook: https://doc.acme.org/doc/abcd.md"). Assertf(time.Now().Weekday() == 1, "This code should run on Monday only."). With("x", x). Assertf(x == 42, "expected x to be equal to 42, but got %d", x) oops.Assert(re.Match(email)) // ... } func handlePanic() error { return oops. Code("iam_authz_missing_permission"). In("authz"). Recover(func() { // ... mayPanic() // ... }) } ``` -------------------------------- ### Efficient Error Wrapping with Oops in Go Source: https://github.com/samber/oops/blob/main/docs/ARCHITECTURE.md Demonstrates the preferred method for wrapping errors using the `Wrap` function, which is more concise and readable than manually constructing a new error with the original error as an attribute. ```go // ❌ Bad err := mayFail() if err != nil { return oops.With("key", "value"). Tenant("user-123"). With("error", err). Errorf("an error") } return nil // ✅ Good return oops.With("key", "value"). Tenant("user-123"). Wrap(mayFail(), "an error") ``` -------------------------------- ### Enable and Print Source Fragments Source: https://github.com/samber/oops/blob/main/README.md Enable the display of source code fragments for errors by setting `oops.SourceFragmentsHidden = false`. This feature requires the source code to be available at runtime. ```go oops.SourceFragmentsHidden = false err1 := oops.Errorf("permission denied") // ... err2 := oops.Wrapf(err1, "something failed") fmt.Println(err2.(oops.OopsError).Sources()) ``` -------------------------------- ### Add Key-Value Attributes using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.With()` builder method to add arbitrary key-value pairs as attributes to the error. ```go err := oops.With("user_id", 123, "attempt", 3).Errorf("login failed") ``` -------------------------------- ### Wrap SQL Errors with Context Source: https://github.com/samber/oops/blob/main/README.md This snippet demonstrates wrapping a SQL execution error with additional context. It uses `Wrapf` which returns `nil` if the wrapped error is `nil`. ```go // with error wrapping err0 := oops. In("repository"). Tags("database", "sql"). Wrapf(sql.Exec(query), "could not fetch user") // Wrapf returns nil when sql.Exec() is nil ``` -------------------------------- ### Assigning Error Ownership Source: https://github.com/samber/oops/blob/main/README.md Shows how to use `.Owner()` to specify the responsible colleague or team for handling an error. This is particularly useful for alerting and issue resolution. ```go err.Owner() string ``` -------------------------------- ### Perform Assertions and Handle Failures Source: https://github.com/samber/oops/blob/main/README.md The `Assertf` method can be used to check conditions and panic with a formatted error message if the condition is false. This is useful for validating assumptions within code. ```go // with assertion err2 := oops. In("repository"). Tags("database", "sql"). Recover(func () { // ... oops.Assertf(time.Now().Weekday() == 1, "This code should run on Monday only.") // ... }) ``` -------------------------------- ### Extract Stacktrace from Go Panic Output Source: https://github.com/samber/oops/blob/main/examples/panic/README.md Run a Go program that panics and specifically extract the stacktrace information using `jq`. The `-r` flag ensures raw output without JSON string escaping. ```sh go run examples/panic/example.go 2>&1 | jq .stacktrace -r ``` -------------------------------- ### Builder Pattern Methods Source: https://github.com/samber/oops/blob/main/docs/API.md Fluent builder methods for enriching errors with context and attributes. ```APIDOC ## Builder Pattern Methods The Oops library uses a fluent builder pattern. All methods return an `*oops.OopsErrorBuilder` that can be chained. ### Context Methods #### `.Code(code any) OopsErrorBuilder` Sets an error code for machine-readable identification. ```go err := oops.Code("auth_failed").Errorf("authentication failed") ``` #### `.In(domain string) OopsErrorBuilder` Sets the domain or feature category where the error occurred. ```go err := oops.In("authentication").Errorf("user not found") ``` #### `.Tags(tags ...string) OopsErrorBuilder` Adds tags for categorization and filtering. ```go err := oops.Tags("security", "auth", "user").Errorf("permission denied") ``` #### `.Trace(trace string) OopsErrorBuilder` Sets a transaction ID, trace ID, or correlation ID. ```go err := oops.Trace("e76031ee-a0c4-4a80-88cb-17086fdd19c0").Errorf("request failed") ``` #### `.Span(span string) OopsErrorBuilder` Sets a unit of work or operation identifier. ```go err := oops.Span("user_creation").Errorf("failed to create user") ``` ### Time and Duration #### `.Time(time time.Time) OopsErrorBuilder` Sets the error timestamp. ```go err := oops.Time(time.Now()).Errorf("timeout occurred") ``` #### `.Since(time time.Time) OopsErrorBuilder` Sets the error duration from a start time. ```go start := time.Now() // ... do work ... err := oops.Since(start).Errorf("operation took too long") ``` #### `.Duration(duration time.Duration) OopsErrorBuilder` Sets the error duration directly. ```go err := oops.Duration(5 * time.Second).Errorf("operation timeout") ``` ### Attributes and Context #### `.With(kv ...any) OopsErrorBuilder` Adds key-value pairs as attributes. ```go err := oops.With("user_id", 123, "attempt", 3).Errorf("login failed") ``` #### `.WithContext(ctx context.Context, keys ...any) OopsErrorBuilder` Extracts values from Go context. ```go err := oops.WithContext(ctx, "request_id", "user_id").Errorf("context error") ``` ### User and Tenant Information #### `.User(userID string, data map[string]any) OopsErrorBuilder` Adds user information and attributes. ```go err := oops.User("user-123", map[string]any{ "email": "john@example.com", "role": "admin", }).Errorf("user operation failed") ``` #### `.Tenant(tenantID string, data map[string]any) OopsErrorBuilder` Adds tenant information and attributes. ```go err := oops.Tenant("tenant-456", map[string]any{ "name": "Acme Corp", "plan": "premium", }).Errorf("tenant operation failed") ``` ### HTTP Context #### `.Request(req *http.Request, withBody bool) OopsErrorBuilder` Adds HTTP request information. ```go err := oops.Request(req, false).Errorf("request processing failed") ``` #### `.Response(res *http.Response, withBody bool) OopsErrorBuilder` Adds HTTP response information. ```go err := oops.Response(res, false).Errorf("response processing failed") ``` ### Debugging and Hints #### `.Hint(hint string) OopsErrorBuilder` Adds debugging hints for developers. ```go err := oops.Hint("Check database connection and user permissions").Errorf("database error") ``` #### `.Public(public string) OopsErrorBuilder` Sets a user-safe error message. ```go err := oops.Public("Unable to process your request. Please try again later.").Errorf("internal server error") ``` #### `.Owner(owner string) OopsErrorBuilder` Sets the team or person responsible for handling the error. ```go err := oops.Owner("backend-team@company.com").Errorf("service unavailable") ``` ``` -------------------------------- ### Extract Context Values using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.WithContext()` builder method to extract specific values from a Go `context.Context` and attach them as attributes. ```go err := oops.WithContext(ctx, "request_id", "user_id").Errorf("context error") ``` -------------------------------- ### Add HTTP Response Information using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.Response()` builder method to include details from an `http.Response` object with the error. The `withBody` flag controls whether the response body is included. ```go err := oops.Response(res, false).Errorf("response processing failed") ``` -------------------------------- ### Deferred Error String Formatting in Go Source: https://github.com/samber/oops/blob/main/docs/ARCHITECTURE.md Demonstrates deferred string formatting for errors. The `format()` method is called only when the `Error()` method is invoked and `e.err` is not nil, ensuring the string representation is generated only when needed. ```go func (e *oopsError) Error() string { if e.err != nil { return e.format() } return "" } ``` -------------------------------- ### Wrap Existing Errors in Go with Oops Source: https://github.com/samber/oops/blob/main/docs/FAQ.md Wrap existing errors using `oops.Wrap` for simple wrapping or `oops.Wrapf` to add formatted context. ```go // Simple wrapping err := oops.Wrap(originalError) ``` ```go // Wrapping with additional context err := oops.Wrapf(originalError, "failed to process user %d", userID) ``` -------------------------------- ### Add Tags using Builder Source: https://github.com/samber/oops/blob/main/docs/API.md Use the `.Tags()` builder method to add multiple string tags for error categorization and filtering. ```go err := oops.Tags("security", "auth", "user").Errorf("permission denied") ```