Skip to content

hanagantig/aerrors

Repository files navigation

GoDoc Build Status

aerrors

Package aerrors adds async errors handling support in GO

This is effective when you want to recover panics in all your goroutines, build an error from it and handle all such errors in one place (logging them or monitor).

There is additionally the Wrap() method, which helps you to build manually 'stacktrace' with errors chain.

Getting started

To download the package, run:

go get github.com/hanagantig/aerrors

Import it in your program as:

import "github.com/hanagantig/aerrors"

It requires Go 1.13 or later.

Refer to the documentation here: http://godoc.org/github.com/hanagantig/aerrors

Basic usage

package main

import (
    "github.com/hanagantig/aerrors"
)

func crashFunc()  {
    panic("crashFunc panic")
}

func main() {
    aerror := aerrors.New()
    aerror.StartHandle()
    
    server := runHTTP()
    
    // runs crashFunc in panic-safe goroutine and adds error to handle
    aerror.Go(crashFunc)

    server.Stop()
    aerror.Stop()
}

With custom handler function

You also can implement your custom handler. Merely use available option aerrors.WithHandler().

package main

import (
    "github.com/hanagantig/aerrors"
)

type CustomErrorHandler struct {}
func (eh *CustomErrorHandler) HandleError(err error)  {
    // do what you want with your error here
}

func main() {
    h := CustomErrorHandler{}
    aerror := aerrors.New(aerrors.WithHandler(&h))
    _ = aerror.StartHandle()
    
    aerror.Close() // for graceful shutdown
}

Global usage

As well as create particular error struct you can initialize it globally and call from where you want.

package main

import (
    "errors"
    "log"
    "github.com/hanagantig/aerrors"
)

func foo(id int) (err error) {
    aerrors.Get().Go(crashFunc)
    aerrors.Get().Add(errors.New("some error to handle"))
}

func crashFunc()  {
    panic("crashFunc panic")
}

func main() {
    err := aerrors.Init()
    if err != nil {
        log.Fatal(err)
    }
    
    aerrors.Get().StartHandle()

    server := runHTTP()
    
    server.Stop()
    aerrors.Get().Stop()
}

Some more features

In addition, you are capable to build your own stack trace with needed functions contains all desired information.

package main

import (
    "fmt"
    "errors"
    "github.com/hanagantig/aerrors"
)

func foo(id int) (err error){
    defer aerrors.Wrap(&err, "foo(%v)", id)

    err = errors.New("errors in foo")
    return
}

func bar(id int, tag string) (err error)  {
    defer aerrors.Wrap(&err, "bar(%v, %v)", id, tag)
    
    err = foo(id)
    return
}

func main() {
    err := bar(1, "aerrors_wrap")
    fmt.Printf("%v", err)   
}

// output
// bar(1, aerrors_wrap): foo(1): errors in foo