getsentry / raven-go

Sentry client in Go
https://sentry.io
BSD 3-Clause "New" or "Revised" License
561 stars 148 forks source link

Custom/Improved Sanitize. Report* Functions. #136

Open tylerstillwater opened 7 years ago

tylerstillwater commented 7 years ago

Changes

  1. Add ability to specify custom fields to sanitize
  2. Add sanitization of headers
  3. Add ReportHandler to wrap an HTTP handler, report a panic and allow it to continue.
  4. Add ReportPanic to capture a panic and report it, then allow it to continue.
  5. Add ReportPanicAndWait to capture a panic and guarantee the report, then allow it to continue.

Motivation

Sanitization

I pass sensitive data in not only the parameters, but the headers. In addition, the field names I use are none of the default sanitization field names. By allowing the user to specify their own field names in addition the to default, any field can be sanitized.

Report* Functions

The Report* family of functions was created so that a report could be sent to the service and then the panic would be allowed to continue bubbling up. This allows panic handlers further up the chain to have their turn at the panic. For example, one of my handlers recovers the panic, packages the information nicely as an error, and returns a 500 to the client.

Implementation Notes

Please note, the usage of ReportPanic(AndWait) differs from the usage of CapturePanic(AndWait). This can be changed, of course, but I feel my approach is cleaner and easier to use.

Rather than having to pass a function to the Capture* functions, we just defer the Report* functions directly.

For example, the Capture* functions operate as so:

func testPanic() {
  raven.CapturePanic(func(){ /* my panicking code */ }, nil, nil)
}

Where the Report* functions operate like this:

func testPanic() {
  defer raven.ReportPanic(nil, nil)
  /* my panicking code */
}

I feel that being able to simply defer the Report function allows for cleaner code, as my options when using the Capture approach are:

  1. Create a separate function entirely, then pass that function to Capture
  2. Create a separate function inside my handler, then pass that function to Capture
  3. Create a closure function directly in the call to Capture

Each of these cases complicates the code and they all feel a bit lousy. I don't really want my function to be called by your function. I want my function to have the code right there, then your function grabs the panic and reports it, if it happens.