-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #270 from airbrake/feature/zerolog
add in zerolog integration
- Loading branch information
Showing
6 changed files
with
151 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/airbrake/gobrake/v5" | ||
zerobrake "github.com/airbrake/gobrake/v5/zerolog" // Named import so that we don't conflict with rs/zerolog | ||
"github.com/rs/zerolog" | ||
) | ||
|
||
var ProjectID int64 = 999999 // Insert your Project ID here | ||
var ProjectKey string = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // Insert your Project Key here | ||
|
||
func main() { | ||
airbrake := gobrake.NewNotifierWithOptions(&gobrake.NotifierOptions{ | ||
ProjectId: ProjectID, | ||
ProjectKey: ProjectKey, | ||
Environment: "production", | ||
}) | ||
|
||
defer airbrake.Close() | ||
|
||
// Note: This writer only accepts errors logs, all others will be ignored. | ||
// You can still send logs to stdout or another writer via io.MultiWriter | ||
w, err := zerobrake.New(airbrake) | ||
if err != nil { | ||
// The only way this error would be returned is if airbrake was not set up and passed in as a nil value | ||
// Either stop the execution of the code or ignore it, as w is set to an empty writer that wont write to | ||
// airbrake if a pointer to airbrake notifier is not provided. | ||
panic("airbrake was not setup correctly") | ||
} | ||
|
||
// Insert the newly created writer (w) into zerolog | ||
log := zerolog.New(io.MultiWriter(os.Stdout, w)) | ||
zerolog.SetGlobalLevel(zerolog.DebugLevel) | ||
|
||
// Creates a sub logger that has additional ctx | ||
loggerWithData := log.With(). | ||
Dict("ctx", | ||
zerolog.Dict(). | ||
Str("BUILD", "gitsha"). | ||
Str("VERSION", ""). | ||
Str("TIME", ""), | ||
). | ||
Str("file", "something.png"). | ||
Str("type", "image/png"). | ||
Str("user", "tobi"). | ||
Logger() | ||
|
||
fmt.Printf("Check your Airbrake dashboard at https://YOUR_SUBDOMAIN.airbrake.io/projects/%v to see these error occurrences\n", ProjectID) | ||
|
||
loggerWithData.Info().Msg("upload") // Sends only to stdout because log level is Info | ||
loggerWithData.Warn().Msg("upload retry") // Sends only to stdout because log level is Warn. | ||
|
||
// This error is sent to Airbrake and stdout because the log level is Error | ||
loggerWithData.Error().Err(errors.New("unauthorized")).Msg("upload failed") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package zerolog | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/airbrake/gobrake/v5" | ||
"github.com/buger/jsonparser" | ||
"github.com/rs/zerolog" | ||
) | ||
|
||
type WriteCloser struct { | ||
Gobrake *gobrake.Notifier | ||
} | ||
|
||
// Validates the WriteCloser matches the io.WriteCloser interface | ||
var _ io.WriteCloser = (*WriteCloser)(nil) | ||
|
||
// New creates a new WriteCloser | ||
func New(notifier *gobrake.Notifier) (io.WriteCloser, error) { | ||
if notifier == nil { | ||
return &WriteCloser{}, errors.New("airbrake notifier not provided") | ||
} | ||
return &WriteCloser{Gobrake: notifier}, nil | ||
} | ||
|
||
// Write parses the log data and sends off error notices to airbrake | ||
func (w *WriteCloser) Write(data []byte) (int, error) { | ||
lvl, err := jsonparser.GetUnsafeString(data, zerolog.LevelFieldName) | ||
if err != nil { | ||
return 0, fmt.Errorf("error getting zerolog level: %w", err) | ||
} | ||
|
||
if lvl != zerolog.ErrorLevel.String() { | ||
return len(data), nil | ||
} | ||
|
||
var logEntryData interface{} | ||
err = json.Unmarshal(data, &logEntryData) | ||
if err != nil { | ||
return 0, fmt.Errorf("error unmarshalling logs: %w", err) | ||
} | ||
type zeroError struct { | ||
message string | ||
error string | ||
} | ||
var ze zeroError | ||
_ = jsonparser.ObjectEach(data, func(key, value []byte, vt jsonparser.ValueType, offset int) error { | ||
switch string(key) { | ||
case zerolog.MessageFieldName: | ||
ze.message = string(value) | ||
case zerolog.ErrorFieldName: | ||
ze.error = string(value) | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
// If gobrake was not setup but the writer was still used, ignore gobrake. | ||
if w.Gobrake == nil { | ||
return len(data), nil | ||
} | ||
|
||
notice := gobrake.NewNotice(ze.message, nil, 6) | ||
notice.Context["severity"] = lvl | ||
notice.Params["logEntryData"] = logEntryData | ||
notice.Error = errors.New(ze.error) | ||
w.Gobrake.SendNoticeAsync(notice) | ||
return len(data), nil | ||
} | ||
|
||
// Close flushes any remaining notices left in gobrake queue | ||
func (w *WriteCloser) Close() error { | ||
w.Gobrake.Flush() | ||
return nil | ||
} |