github.com/facebookincubator/go-belt@v0.0.0-20230703220935-39cd348f1a38/tool/experimental/errmon/README.md (about)

     1  # Disclaimer
     2  
     3  This API is experimental and has no stability guarantees.
     4  
     5  # Example
     6  ```go
     7  package errmon_test
     8  
     9  import (
    10  	"context"
    11  
    12  	sentryupstream "github.com/getsentry/sentry-go"
    13  
    14  	"github.com/facebookincubator/go-belt"
    15  	"github.com/facebookincubator/go-belt/beltctx"
    16  	"github.com/facebookincubator/go-belt/tool/experimental/errmon"
    17  	"github.com/facebookincubator/go-belt/tool/experimental/errmon/implementation/logger"
    18  	"github.com/facebookincubator/go-belt/tool/experimental/errmon/implementation/sentry"
    19  )
    20  
    21  func Example() {
    22  	// easy to use:
    23  	m := logger.Default()
    24  	someFunction(1, m)
    25  
    26  	// implementation agnostic:
    27  	sentryClient, err := sentryupstream.NewClient(sentryupstream.ClientOptions{})
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  	m = sentry.New(sentryClient)
    32  	someFunction(2, m)
    33  
    34  	// one may still reuse all the features of the emitter ErrorMonitor:
    35  	_ = m.Emitter().(*sentry.Emitter).SentryClient.Options()
    36  
    37  	// use go-belt to manage the ErrorMonitor
    38  	obs := belt.New()
    39  	obs = errmon.BeltWithErrorMonitor(obs, m)
    40  	someBeltyFunction(3, obs)
    41  
    42  	// use context to manage the ErrorMonitor
    43  	ctx := context.Background()
    44  	ctx = errmon.CtxWithErrorMonitor(ctx, m)
    45  	someContextyFunction(ctx, 4)
    46  
    47  	// use a singletony ErrorMonitor:
    48  	errmon.Default = func() errmon.ErrorMonitor {
    49  		return m
    50  	}
    51  	yetOneMoreFunction(5)
    52  }
    53  
    54  func someFunction(arg int, m errmon.ErrorMonitor) {
    55  	// experience close to logrus/zap:
    56  	m = errmon.WithField(m, "arg", arg)
    57  	anotherFunction(m)
    58  }
    59  
    60  func anotherFunction(m errmon.ErrorMonitor) {
    61  	defer func() { m.ObserveRecover(nil, recover()) }()
    62  	// ..do something here..
    63  }
    64  
    65  func someBeltyFunction(arg int, obs *belt.Belt) {
    66  	obs = obs.WithField("arg", arg)
    67  	anotherBeltyFunction(obs)
    68  }
    69  
    70  func anotherBeltyFunction(obs *belt.Belt) {
    71  	defer func() { errmon.ObserveRecoverBelt(obs, recover()) }()
    72  	// ..do something here..
    73  }
    74  
    75  func someContextyFunction(ctx context.Context, arg int) {
    76  	ctx = beltctx.WithField(ctx, "arg", arg)
    77  	anotherContextyFunction(ctx)
    78  }
    79  
    80  func anotherContextyFunction(ctx context.Context) {
    81  	defer func() { errmon.ObserveRecoverCtx(ctx, recover()) }()
    82  	// ..do something here..
    83  }
    84  
    85  func yetOneMoreFunction(arg int) {
    86  	m := errmon.Default()
    87  	m = errmon.WithField(m, "arg", arg)
    88  	defer func() { m.ObserveRecover(nil, recover()) }()
    89  	// ..do something here..
    90  }
    91  ```
    92  
    93  # Interface
    94  ```go
    95  // ErrorMonitor is an observability Tool (belt.Tool) which allows
    96  // to report about any exceptions which happen for debugging. It
    97  // collects any useful information it can.
    98  //
    99  // An ErrorMonitor implementation is not supposed to be fast, but
   100  // it supposed to provide verbose reports (sufficient enough to
   101  // debug found problems).
   102  type ErrorMonitor interface {
   103  	belt.Tool
   104  
   105  	// Emitter returns the Emitter.
   106  	//
   107  	// A read-only value, do not change it.
   108  	Emitter() Emitter
   109  
   110  	// ObserveError issues an error event if `err` is not an untyped nil. Additional
   111  	// data (left by various observability tooling) is extracted from `belt`.
   112  	//
   113  	// Returns an Event only if one was issued (and for example was not sampled out by a Sampler Hook).
   114  	ObserveError(*belt.Belt, error) *Event
   115  
   116  	// ObserveRecover issues a panic event if `recoverResult` is not an untyped nil.
   117  	// Additional data (left by various observability tooling) is extracted from `belt`.
   118  	//
   119  	// Is supposed to be used in constructions like:
   120  	//
   121  	//     defer func() { errmon.ObserveRecover(ctx, recover()) }()
   122  	//
   123  	// See also: https://go.dev/ref/spec#Handling_panics
   124  	//
   125  	// Returns an Event only if one was issued (and for example was not sampled out by a Sampler Hook).
   126  	ObserveRecover(_ *belt.Belt, recoverResult any) *Event
   127  
   128  	// WithPreHooks returns a ErrorMonitor derivative which also includes/appends pre-hooks from the arguments.
   129  	//
   130  	// Special case: to reset hooks use `WithHooks()` (without any arguments).
   131  	WithPreHooks(...PreHook) ErrorMonitor
   132  
   133  	// WithHooks returns a ErrorMonitor derivative which also includes/appends hooks from the arguments.
   134  	//
   135  	// Special case: to reset hooks use `WithHooks()` (without any arguments).
   136  	WithHooks(...Hook) ErrorMonitor
   137  }
   138  ```
   139