{"id":22441243,"url":"https://github.com/hyp3rd/ewrap","last_synced_at":"2026-03-13T20:13:15.523Z","repository":{"id":266132975,"uuid":"897346129","full_name":"hyp3rd/ewrap","owner":"hyp3rd","description":"A sophisticated, configurable error wrapper for Go applications that provides:  Stack trace capture Error wrapping with context, Metadata attachment, Logger integration, Compatibility with Go 1.13+ error chains, Rich error information for debugging, Thread-safe operations.","archived":false,"fork":false,"pushed_at":"2026-01-16T19:50:45.000Z","size":1351,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-17T07:17:41.953Z","etag":null,"topics":["error","error-handling","errors","go","golang","multi-error","multierror","retry"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hyp3rd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["hyp3rd"]}},"created_at":"2024-12-02T13:26:31.000Z","updated_at":"2026-01-16T19:50:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"f00ca3e5-4bea-442e-ac0c-c4a5f2df8a81","html_url":"https://github.com/hyp3rd/ewrap","commit_stats":null,"previous_names":["hyp3rd/ewrap"],"tags_count":15,"template":false,"template_full_name":"hyp3rd/go-base-app-skel","purl":"pkg:github/hyp3rd/ewrap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fewrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fewrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fewrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fewrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hyp3rd","download_url":"https://codeload.github.com/hyp3rd/ewrap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fewrap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30474307,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T17:15:31.527Z","status":"ssl_error","status_checked_at":"2026-03-13T17:15:22.394Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["error","error-handling","errors","go","golang","multi-error","multierror","retry"],"created_at":"2024-12-06T02:13:29.892Z","updated_at":"2026-03-13T20:13:15.514Z","avatar_url":"https://github.com/hyp3rd.png","language":"Go","funding_links":["https://github.com/sponsors/hyp3rd"],"categories":[],"sub_categories":[],"readme":"# ewrap\n\n[![Go](https://github.com/hyp3rd/ewrap/actions/workflows/go.yml/badge.svg)](https://github.com/hyp3rd/ewrap/actions/workflows/go.yml) [![Docs](https://img.shields.io/badge/docs-passing-brightgreen)](https://hyp3rd.github.io/ewrap/) [![Go Report Card](https://goreportcard.com/badge/github.com/hyp3rd/ewrap)](https://goreportcard.com/report/github.com/hyp3rd/ewrap) [![Go Reference](https://pkg.go.dev/badge/github.com/hyp3rd/ewrap.svg)](https://pkg.go.dev/github.com/hyp3rd/ewrap) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![GitHub Sponsors](https://img.shields.io/github/sponsors/hyp3rd)\n\nA sophisticated, modern error handling library for Go applications that provides comprehensive error management with advanced features, observability hooks, and seamless integration with Go 1.25+ features.\n\n## Core Features\n\n### Error Management \u0026 Context\n\n- **Advanced Stack Traces**: Programmatic stack frame inspection with iterators and structured access\n- **Smart Error Wrapping**: Maintains error chains with unified context handling and metadata preservation\n- **Rich Metadata**: Type-safe metadata attachment with optional generics support\n- **Context Integration**: Unified context handling preventing divergence between error context and metadata\n\n### Logging \u0026 Observability\n\n- **Modern Logging**: Support for slog (Go 1.21+), logrus, zap, zerolog with structured output\n- **Observability Hooks**: Built-in metrics and tracing for error frequencies and circuit-breaker states\n- **Recovery Guidance**: Integrated recovery suggestions in error output and logging\n\n### Performance \u0026 Efficiency\n\n- **Go 1.25+ Optimizations**: Uses `maps.Clone` and `slices.Clone` for efficient copying operations\n- **Pool-based Error Groups**: Memory-efficient error aggregation with `errors.Join` compatibility\n- **Thread-Safe Operations**: Zero-allocation hot paths with minimal contention\n- **Structured Serialization**: JSON/YAML export with full error group serialization\n\n### Advanced Features\n\n- **Circuit Breaker Pattern**: Protect systems from cascading failures with state transition monitoring\n- **Custom Retry Logic**: Configurable per-error retry strategies with `RetryInfo` extension\n- **Error Categorization**: Built-in types, severity levels, and optional generic type constraints\n- **Timestamp Formatting**: Proper timestamp formatting with customizable formats\n\n## Installation\n\n```bash\ngo get github.com/hyp3rd/ewrap\n```\n\n## Documentation\n\n`ewrap` provides comprehensive documentation covering all features and advanced usage patterns. Visit the [complete documentation](https://hyp3rd.github.io/ewrap/) for detailed guides, examples, and API reference.\n\n## Usage Examples\n\n### Basic Error Handling\n\nCreate and wrap errors with context:\n\n```go\n// Create a new error\nerr := ewrap.New(\"database connection failed\")\n\n// Wrap an existing error with context\nif err != nil {\n    return ewrap.Wrap(err, \"failed to process request\")\n}\n\nerr = ewrap.Newf(\"failed to process request id: %v\", requestID)\n```\n\n### Advanced Error Context with Unified Handling\n\nAdd rich context and metadata with the new unified context system:\n\n```go\nerr := ewrap.New(\"operation failed\",\n    ewrap.WithContext(ctx, ewrap.ErrorTypeDatabase, ewrap.SeverityCritical),\n    ewrap.WithLogger(logger),\n    ewrap.WithRecoverySuggestion(\"Check database connection and retry\")).\n    WithMetadata(\"query\", \"SELECT * FROM users\").\n    WithMetadata(\"retry_count\", 3).\n    WithMetadata(\"connection_pool_size\", 10)\n\n// Log the error with all context and recovery suggestions\nerr.Log()\n```\n\n### Modern Error Groups with errors.Join Integration\n\nUse error groups efficiently with Go 1.25+ features:\n\n```go\n// Create an error group pool with initial capacity\npool := ewrap.NewErrorGroupPool(4)\n\n// Get an error group from the pool\neg := pool.Get()\ndefer eg.Release()  // Return to pool when done\n\n// Add errors as needed\neg.Add(err1)\neg.Add(err2)\n\n// Use errors.Join compatibility for standard library integration\nif err := eg.Join(); err != nil {\n    return err\n}\n\n// Or serialize the entire error group\njsonOutput, _ := eg.ToJSON(ewrap.WithTimestampFormat(time.RFC3339))\n```\n\n### Stack Frame Inspection and Iteration\n\nProgrammatically inspect stack traces:\n\n```go\nif wrappedErr, ok := err.(*ewrap.Error); ok {\n    // Get a stack iterator for programmatic access\n    iterator := wrappedErr.GetStackIterator()\n\n    for iterator.HasNext() {\n        frame := iterator.Next()\n        fmt.Printf(\"Function: %s\\n\", frame.Function)\n        fmt.Printf(\"File: %s:%d\\n\", frame.File, frame.Line)\n        fmt.Printf(\"PC: %x\\n\", frame.PC)\n    }\n\n    // Or get all frames at once\n    frames := wrappedErr.GetStackFrames()\n    for _, frame := range frames {\n        // Process each frame...\n    }\n}\n```\n\n### Custom Retry Logic with Extended RetryInfo\n\nConfigure per-error retry strategies:\n\n```go\n// Define custom retry logic\nshouldRetry := func(err error, attempt int) bool {\n    if attempt \u003e= 5 {\n        return false\n    }\n\n    // Custom logic based on error type\n    if wrappedErr, ok := err.(*ewrap.Error); ok {\n        return wrappedErr.ErrorType() == ewrap.ErrorTypeNetwork\n    }\n    return false\n}\n\n// Create error with custom retry configuration\nerr := ewrap.New(\"network timeout\",\n    ewrap.WithRetryInfo(3, time.Second*2, shouldRetry))\n\n// Use the retry information\nif retryInfo := err.GetRetryInfo(); retryInfo != nil {\n    if retryInfo.ShouldRetry(err, currentAttempt) {\n        // Perform retry logic\n    }\n}\n```\n\n### Observability Hooks and Monitoring\n\nMonitor error patterns and circuit breaker states:\n\n```go\n// Set up observability hooks\nobserver := \u0026MyObserver{\n    metricsClient: metricsClient,\n    tracer:       tracer,\n}\n\n// Create circuit breaker with observability\ncb := ewrap.NewCircuitBreaker(\"payment-service\", 5, time.Minute*2,\n    ewrap.WithObserver(observer))\n\n// The observer will receive notifications for:\n// - Error frequency changes\n// - Circuit breaker state transitions\n// - Recovery suggestions triggered\n```\n\n### Circuit Breaker Pattern\n\nProtect your system from cascading failures:\n\n```go\n// Create a circuit breaker for database operations\ncb := ewrap.NewCircuitBreaker(\"database\", 3, time.Minute)\n\nif cb.CanExecute() {\n    if err := performDatabaseOperation(); err != nil {\n        cb.RecordFailure()\n        return ewrap.Wrap(err, \"database operation failed\",\n            ewrap.WithContext(ctx, ewrap.ErrorTypeDatabase, ewrap.SeverityCritical))\n    }\n    cb.RecordSuccess()\n}\n```\n\n### Complete Example\n\nHere's a comprehensive example combining multiple features:\n\n```go\nfunc processOrder(ctx context.Context, orderID string) error {\n    // Get an error group from the pool\n    pool := ewrap.NewErrorGroupPool(4)\n    eg := pool.Get()\n    defer eg.Release()\n\n    // Create a circuit breaker for database operations\n    cb := ewrap.NewCircuitBreaker(\"database\", 3, time.Minute)\n\n    // Validate order\n    if err := validateOrderID(orderID); err != nil {\n        eg.Add(ewrap.Wrap(err, \"invalid order ID\",\n            ewrap.WithContext(ctx, ewrap.ErrorTypeValidation, ewrap.SeverityError)))\n    }\n\n    if !eg.HasErrors() \u0026\u0026 cb.CanExecute() {\n        if err := saveToDatabase(orderID); err != nil {\n            cb.RecordFailure()\n            return ewrap.Wrap(err, \"database operation failed\",\n                ewrap.WithContext(ctx, ewrap.ErrorTypeDatabase, ewrap.SeverityCritical))\n        }\n        cb.RecordSuccess()\n    }\n\n    return eg.Error()\n}\n```\n\n## Error Types and Severity\n\nThe package provides pre-defined error types and severity levels:\n\n```go\n// Error Types\nErrorTypeValidation    // Input validation failures\nErrorTypeNotFound      // Resource not found\nErrorTypePermission    // Authorization/authentication failures\nErrorTypeDatabase      // Database operation failures\nErrorTypeNetwork       // Network-related failures\nErrorTypeConfiguration // Configuration issues\nErrorTypeInternal      // Internal system errors\nErrorTypeExternal      // External service errors\n\n// Severity Levels\nSeverityInfo      // Informational messages\nSeverityWarning   // Warning conditions\nSeverityError     // Error conditions\nSeverityCritical  // Critical failures\n```\n\n## Logging Integration\n\nImplement the Logger interface to integrate with your logging system:\n\n```go\ntype Logger interface {\n    Error(msg string, keysAndValues ...any)\n    Debug(msg string, keysAndValues ...any)\n    Info(msg string, keysAndValues ...any)\n}\n```\n\nBuilt-in adapters are provided for popular logging frameworks including modern slog support:\n\n```go\n// Slog logger (Go 1.21+) - Recommended for new projects\nslogLogger := slog.New(slog.NewJSONHandler(os.Stdout, \u0026slog.HandlerOptions{\n    Level: slog.LevelDebug,\n}))\nerr := ewrap.New(\"error occurred\",\n    ewrap.WithLogger(adapters.NewSlogAdapter(slogLogger)))\n\n// Zap logger\nzapLogger, _ := zap.NewProduction()\nerr := ewrap.New(\"error occurred\",\n    ewrap.WithLogger(adapters.NewZapAdapter(zapLogger)))\n\n// Logrus logger\nlogrusLogger := logrus.New()\nerr := ewrap.New(\"error occurred\",\n    ewrap.WithLogger(adapters.NewLogrusAdapter(logrusLogger)))\n\n// Zerolog logger\nzerologLogger := zerolog.New(os.Stdout)\nerr := ewrap.New(\"error occurred\",\n    ewrap.WithLogger(adapters.NewZerologAdapter(zerologLogger)))\n```\n\n### Recovery Suggestions in Logging\n\nRecovery suggestions are now automatically included in log output:\n\n```go\nerr := ewrap.New(\"database connection failed\",\n    ewrap.WithRecoverySuggestion(\"Check database connectivity and connection pool settings\"))\n\n// When logged, includes recovery guidance for operations teams\nerr.Log() // Outputs recovery suggestion in structured format\n```\n\n## Error Formatting\n\nConvert errors to structured formats with proper timestamp formatting:\n\n```go\n// Convert to JSON with proper timestamp formatting\njsonStr, _ := err.ToJSON(\n    ewrap.WithTimestampFormat(time.RFC3339),\n    ewrap.WithStackTrace(true),\n    ewrap.WithRecoverySuggestion(true))\n\n// Convert to YAML with custom formatting\nyamlStr, _ := err.ToYAML(\n    ewrap.WithTimestampFormat(\"2006-01-02T15:04:05Z07:00\"),\n    ewrap.WithStackTrace(true))\n\n// Serialize entire error groups\npool := ewrap.NewErrorGroupPool(4)\neg := pool.Get()\neg.Add(err1)\neg.Add(err2)\n\n// Export all errors in the group\ngroupJSON, _ := eg.ToJSON(ewrap.WithTimestampFormat(time.RFC3339))\n```\n\n### Modern Go Features Integration\n\nLeverage Go 1.25+ features for efficient operations:\n\n```go\n// Efficient metadata copying using maps.Clone\noriginalErr := ewrap.New(\"base error\").WithMetadata(\"key1\", \"value1\")\nclonedErr := originalErr.Clone() // Uses maps.Clone internally\n\n// Error group integration with errors.Join\neg := pool.Get()\neg.Add(err1, err2, err3)\nstandardErr := eg.Join() // Returns standard errors.Join result\n\n// Use with standard library error handling\nif errors.Is(standardErr, expectedErr) {\n    // Handle specific error type\n}\n```\n\n## Performance Considerations\n\nThe package is designed with performance in mind and leverages modern Go features:\n\n### Go 1.25+ Optimizations\n\n- Uses `maps.Clone` and `slices.Clone` for efficient copying operations\n- Zero-allocation paths for error creation and wrapping in hot paths\n- Optimized stack trace capture with intelligent filtering\n\n### Memory Management\n\n- Error groups use `sync.Pool` for efficient memory reuse\n- Stack frame iterators provide lazy evaluation\n- Minimal allocations during error metadata operations\n\n### Concurrency \u0026 Safety\n\n- Thread-safe operations with low lock contention\n- Atomic operations for circuit breaker state management\n- Lock-free observability hook notifications\n\n### Structured Operations\n\n- Pre-allocated buffers for JSON/YAML serialization\n- Efficient stack trace capture and filtering\n- Optimized metadata storage and retrieval\n\n## Observability Features\n\n### Built-in Monitoring\n\n- Error frequency tracking and reporting\n- Circuit breaker state transition monitoring\n- Recovery suggestion effectiveness metrics\n\n### Integration Points\n\n```go\n// Implement the Observer interface for custom monitoring\ntype Observer interface {\n    OnErrorCreated(err *Error, context ErrorContext)\n    OnCircuitBreakerStateChange(name string, from, to CircuitState)\n    OnRecoverySuggestionTriggered(suggestion string, context ErrorContext)\n}\n\n// Register observers for monitoring\newrap.RegisterGlobalObserver(myObserver)\n```\n\n## Development Setup\n\n1. Clone this repository:\n\n   ```bash\n   git clone https://github.com/hyp3rd/ewrap.git\n   ```\n\n1. Install VS Code Extensions Recommended (optional):\n\n   ```json\n   {\n     \"recommendations\": [\n       \"github.vscode-github-actions\",\n       \"golang.go\",\n       \"ms-vscode.makefile-tools\",\n       \"esbenp.prettier-vscode\",\n       \"pbkit.vscode-pbkit\",\n       \"trunk.io\",\n       \"streetsidesoftware.code-spell-checker\",\n       \"ms-azuretools.vscode-docker\",\n       \"eamodio.gitlens\"\n     ]\n   }\n   ```\n\n   1. Install [**Golang**](https://go.dev/dl).\n   1. Install [**GitVersion**](https://github.com/GitTools/GitVersion).\n   1. Install [**Make**](https://www.gnu.org/software/make/), follow the procedure for your OS.\n   1. **Set up the toolchain:**\n\n      ```bash\n      make prepare-toolchain\n      ```\n\n   1. Initialize `pre-commit` (strongly recommended to create a virtual env, using for instance [PyEnv](https://github.com/pyenv/pyenv)) and its hooks:\n\n   ```bash\n      pip install pre-commit\n      pre-commit install\n      pre-commit install-hooks\n   ```\n\n## Project Structure\n\n```txt\n├── internal/ # Private code\n│   └── logger/ # Application specific code\n├── pkg/ # Public libraries)\n├── scripts/ # Scripts for development\n├── test/ # Additional test files\n└── docs/ # Documentation\n```\n\n## Best Practices\n\n- Follow the [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments)\n- Run `golangci-lint` before committing code\n- Ensure the pre-commit hooks pass\n- Write tests for new functionality\n- Keep packages small and focused\n- Use meaningful package names\n- Document exported functions and types\n\n## Available Make Commands\n\n- `make test`: Run tests.\n- `make benchmark`: Run benchmark tests.\n- `make update-deps`: Update all dependencies in the project.\n- `make prepare-toolchain`: Install all tools required to build the project.\n- `make lint`: Run the staticcheck and golangci-lint static analysis tools on all packages in the project.\n- `make run`: Build and run the application in Docker.\n\n## License\n\n[MIT License](LICENSE)\n\n## Contributing\n\n1. Fork the repository\n1. Create your feature branch\n1. Commit your changes\n1. Push to the branch\n1. Create a Pull Request\n\nRefer to [CONTRIBUTING](CONTRIBUTING.md) for more information.\n\n## Author\n\nI'm a surfer, and a software architect with 15 years of experience designing highly available distributed production systems and developing cloud-native apps in public and private clouds. Feel free to connect with me on LinkedIn.\n\n[![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white)](https://www.linkedin.com/in/francesco-cosentino/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyp3rd%2Fewrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhyp3rd%2Fewrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyp3rd%2Fewrap/lists"}