Skip to content

Commit b74c350

Browse files
committed
feat: initial release v0.1.0
This commit refactors the `stackerr` package into an open-source library with the following changes: - Configurable stack trace formatting (strip sequences, path replacements, max depth). - Added `ThrowPanic` and `Recover` for robust error handling. - Introduced `GetStack` helper and made `callStackErr` internal for better encapsulation. - Added comprehensive unit tests and examples. - Added GitHub Actions CI workflow. - Added MIT License and CHANGELOG.md. - Updated module path to `github.com/LZStock-OS/stackerr`. Closes #1
0 parents  commit b74c350

9 files changed

Lines changed: 668 additions & 0 deletions

File tree

.github/workflows/go.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
11+
build:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v5
18+
with:
19+
go-version: '1.25'
20+
21+
- name: Build
22+
run: go build -v ./...
23+
24+
- name: Test
25+
run: go test -v ./...

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
8+
# Test binary, built with `go test -c`
9+
*.test
10+
11+
# Output of the go coverage tool, specifically when used with LiteIDE
12+
*.out
13+
14+
# Dependency directories (remove the comment below to include it)
15+
# vendor/

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [0.1.0] - 2026-03-01
9+
10+
### Added
11+
- Initial release of `stackerr` library.
12+
- `Recover` function to handle panics and wrap errors with stack traces.
13+
- `ThrowPanic` function to explicitly panic with a wrapped error containing the current stack trace.
14+
- Internal `callStackErr` type implementing `error` and `Unwrap` interface.
15+
- Configuration support via `stackerr.Config`:
16+
- `StripSequences`: Custom strings to strip from function names (e.g., `(0`, `({`).
17+
- `PathReplacements`: Custom file path cleanup (e.g., replacing `$GOPATH` with `[Proj]`).
18+
- `MaxStackDepth`: Configurable stack trace depth limit (default: 10).
19+
- `Output`: Configurable `io.Writer` for panic logs (default: `os.Stderr`).
20+
- Unit tests (`stackerr_test.go`) and usage examples (`example_test.go`).
21+
- GitHub Actions CI workflow for automated testing.
22+
- MIT License.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 LZStock-OS
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# stackerr
2+
3+
`stackerr` is a lightweight Go library for panic recovery and error handling with customizable stack traces. It simplifies debugging by capturing clean, readable stack traces when panics occur or when errors are explicitly thrown.
4+
5+
## Features
6+
7+
- **Panic Recovery**: Easily recover from panics and wrap them into errors with stack traces.
8+
- **Clean Stack Traces**: Automatically strips noisy arguments and simplifies file paths (e.g., replacing `$GOPATH` with `[Proj]`).
9+
- **Customizable**: Configure which strings to strip from function names, define custom path replacements, and set stack depth limits.
10+
- **Error Wrapping**: Supports standard Go error wrapping (`Unwrap()`).
11+
12+
## Installation
13+
14+
```bash
15+
go get github.com/LZStock-OS/stackerr
16+
```
17+
18+
## Usage
19+
20+
### Basic Recovery
21+
22+
Use `stackerr.Recover` in a `defer` statement to catch panics and populate an error return variable.
23+
24+
```go
25+
package main
26+
27+
import (
28+
"fmt"
29+
"github.com/LZStock-OS/stackerr"
30+
)
31+
32+
func riskyOperation() (err error) {
33+
defer stackerr.Recover(&err)
34+
35+
// Simulating a panic
36+
panic("something went wrong")
37+
}
38+
39+
func main() {
40+
if err := riskyOperation(); err != nil {
41+
fmt.Printf("Caught error: %v\n", err)
42+
43+
if stack := stackerr.GetStack(err); stack != "" {
44+
fmt.Println("Stack Trace:")
45+
fmt.Println(stack)
46+
}
47+
}
48+
}
49+
```
50+
51+
### Throwing Errors with Stack Traces
52+
53+
Use `stackerr.ThrowPanic` to explicitly panic with a wrapped error containing the current stack trace.
54+
55+
```go
56+
func doSomething() {
57+
err := someInternalFunction()
58+
if err != nil {
59+
// This will panic and be caught by a defer stackerr.Recover up the chain
60+
stackerr.ThrowPanic(fmt.Errorf("operation failed: %w", err))
61+
}
62+
}
63+
```
64+
65+
### Configuration
66+
67+
You can customize the library's behavior by modifying the global `stackerr.Config` variable. It is recommended to do this in your `init()` function or main setup.
68+
69+
```go
70+
import (
71+
"os"
72+
"github.com/LZStock-OS/stackerr"
73+
)
74+
75+
func init() {
76+
// Customize string sequences to strip from function names
77+
stackerr.Config.StripSequences = []string{"(0", "({", "(*"}
78+
79+
// Set maximum stack depth (default: 10)
80+
stackerr.Config.MaxStackDepth = 20
81+
82+
// Customize path replacements to hide sensitive paths or make logs shorter
83+
stackerr.Config.PathReplacements = map[string]string{
84+
"/home/user/go/src/": "[Src]",
85+
"github.com/my/project/": "",
86+
}
87+
88+
// Redirect log output (default: os.Stderr)
89+
// Set to nil to disable automatic logging on recovery
90+
stackerr.Config.Output = os.Stdout
91+
}
92+
```
93+
94+
## API Reference
95+
96+
### `func Recover(err *error)`
97+
98+
Catches panics, wraps them in a `callStackErr`, and assigns it to `*err`. It also logs the panic and stack trace to the configured output.
99+
100+
### `func ThrowPanic(err error)`
101+
102+
Wraps the given error with the current stack trace and panics. Use this when you want to abort execution but preserve context for the recovery handler.
103+
104+
### `func GetStack(err error) string`
105+
Retrieves the stack trace from an error if it was created by `Recover` or `ThrowPanic`. Returns an empty string otherwise.
106+
107+
## License
108+
109+
MIT

example_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package stackerr_test
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"os"
7+
8+
"github.com/LZStock-OS/stackerr"
9+
)
10+
11+
// ExampleRecover demonstrates how to use Recover to catch panics and wrap them with a stack trace.
12+
func ExampleRecover() {
13+
// Disable default logging to stderr for this example to keep output clean
14+
stackerr.Config.Output = nil
15+
defer func() { stackerr.Config.Output = os.Stderr }() // Restore default
16+
17+
// Function that might panic
18+
riskyFunction := func() (err error) {
19+
// Defer Recover to catch panics and populate err
20+
defer stackerr.Recover(&err)
21+
22+
// Simulating a panic
23+
panic("something went wrong")
24+
}
25+
26+
err := riskyFunction()
27+
if err != nil {
28+
fmt.Printf("Error caught: %v\n", err)
29+
// Access the stack trace if needed
30+
if stack := stackerr.GetStack(err); stack != "" {
31+
fmt.Println("Stack trace captured.")
32+
}
33+
}
34+
35+
// Output:
36+
// Error caught: panic: something went wrong
37+
// Stack trace captured.
38+
}
39+
40+
// ExampleThrowPanic demonstrates how to use ThrowPanic to panic with a stack trace.
41+
func ExampleThrowPanic() {
42+
// Disable default logging
43+
stackerr.Config.Output = nil
44+
defer func() { stackerr.Config.Output = os.Stderr }()
45+
46+
// Function that throws a panic
47+
thrower := func() (err error) {
48+
defer stackerr.Recover(&err)
49+
50+
// ThrowPanic wraps the error and panics
51+
stackerr.ThrowPanic(errors.New("critical failure"))
52+
return nil
53+
}
54+
55+
err := thrower()
56+
if err != nil {
57+
fmt.Printf("Error caught: %v\n", err)
58+
}
59+
60+
// Output:
61+
// Error caught: critical failure
62+
}
63+
64+
// Example_configuration demonstrates how to configure the library.
65+
func Example_configuration() {
66+
// Configure global settings
67+
stackerr.Config.StripSequences = []string{"(0", "({", "(*"}
68+
stackerr.Config.MaxStackDepth = 5
69+
// Disable logging for this example to avoid output mismatch
70+
stackerr.Config.Output = nil
71+
72+
var err error
73+
func() {
74+
defer stackerr.Recover(&err)
75+
panic("custom config panic")
76+
}()
77+
78+
// Reset config for other tests
79+
stackerr.Config.Output = os.Stderr
80+
81+
fmt.Println("Done")
82+
83+
// Output:
84+
// Done
85+
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/LZStock-OS/stackerr
2+
3+
go 1.25.5

0 commit comments

Comments
 (0)