upgrade deps; rewrite smtp session

This commit is contained in:
Aine
2024-02-19 22:55:14 +02:00
parent 10213cc7d7
commit a01720da00
277 changed files with 106832 additions and 7641 deletions

View File

@@ -6,7 +6,6 @@
```go
import (
"errors"
"io"
stdlog "log"
"os"
@@ -15,14 +14,15 @@ import (
)
func main() {
w, err := zlogsentry.New("http://e35657dcf4fb4d7c98a1c0b8a9125088@localhost:9000/2")
w, err := zlogsentry.New("http://e35657dcf4fb4d7c98a1c0b8a9125088@localhost:9000/2", zlogsentry.WithEnvironment("dev"), zlogsentry.WithRelease("1.0.0"))
if err != nil {
stdlog.Fatal(err)
}
defer w.Close()
logger := zerolog.New(io.MultiWriter(w, os.Stdout)).With().Timestamp().Logger()
multi := zerolog.MultiLevelWriter(os.Stdout, w)
logger := zerolog.New(multi).With().Timestamp().Logger()
logger.Error().Err(errors.New("dial timeout")).Msg("test message")
}

7
vendor/github.com/archdx/zerolog-sentry/errors.go generated vendored Normal file
View File

@@ -0,0 +1,7 @@
package zlogsentry
import (
"errors"
)
var ErrFlushTimeout = errors.New("zlogsentry flush timeout")

View File

@@ -1,7 +1,10 @@
package zlogsentry
import (
"crypto/x509"
"errors"
"io"
"net/http"
"time"
"unsafe"
@@ -27,62 +30,123 @@ var now = time.Now
type Writer struct {
hub *sentry.Hub
levels map[zerolog.Level]struct{}
flushTimeout time.Duration
levels map[zerolog.Level]struct{}
flushTimeout time.Duration
withBreadcrumbs bool
}
// Write handles zerolog's json and sends events to sentry.
func (w *Writer) Write(data []byte) (int, error) {
event, ok := w.parseLogEvent(data)
if ok {
w.hub.CaptureEvent(event)
// should flush before os.Exit
if event.Level == sentry.LevelFatal {
w.hub.Flush(w.flushTimeout)
// addBreadcrumb adds event as a breadcrumb
func (w *Writer) addBreadcrumb(event *sentry.Event) {
if !w.withBreadcrumbs {
return
}
// category is totally optional, but it's nice to have
var category string
if _, ok := event.Extra["category"]; ok {
if v, ok := event.Extra["category"].(string); ok {
category = v
}
}
return len(data), nil
w.hub.AddBreadcrumb(&sentry.Breadcrumb{
Category: category,
Message: event.Message,
Level: event.Level,
Data: event.Extra,
}, nil)
}
// Write handles zerolog's json and sends events to sentry.
func (w *Writer) Write(data []byte) (n int, err error) {
n = len(data)
lvl, err := w.parseLogLevel(data)
if err != nil {
return n, nil
}
event, ok := w.parseLogEvent(data)
if !ok {
return
}
event.Level, ok = levelsMapping[lvl]
if !ok {
return
}
if _, enabled := w.levels[lvl]; !enabled {
// if the level is not enabled, add event as a breadcrumb
w.addBreadcrumb(event)
return
}
w.hub.CaptureEvent(event)
// should flush before os.Exit
if event.Level == sentry.LevelFatal {
w.hub.Flush(w.flushTimeout)
}
return
}
// implements zerolog.LevelWriter
func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
n = len(p)
event, ok := w.parseLogEvent(p)
if !ok {
return
}
event.Level, ok = levelsMapping[level]
if !ok {
return
}
if _, enabled := w.levels[level]; !enabled {
// if the level is not enabled, add event as a breadcrumb
w.addBreadcrumb(event)
return
}
w.hub.CaptureEvent(event)
// should flush before os.Exit
if event.Level == sentry.LevelFatal {
w.hub.Flush(w.flushTimeout)
}
return
}
// Close forces client to flush all pending events.
// Can be useful before application exits.
func (w *Writer) Close() error {
w.hub.Flush(w.flushTimeout)
if ok := w.hub.Flush(w.flushTimeout); !ok {
return ErrFlushTimeout
}
return nil
}
// parses the log level from the encoded log
func (w *Writer) parseLogLevel(data []byte) (zerolog.Level, error) {
lvlStr, err := jsonparser.GetUnsafeString(data, zerolog.LevelFieldName)
if err != nil {
return zerolog.Disabled, nil
}
return zerolog.ParseLevel(lvlStr)
}
// parses the event except the log level
func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) {
const logger = "zerolog"
lvlStr, err := jsonparser.GetUnsafeString(data, zerolog.LevelFieldName)
if err != nil {
return nil, false
}
lvl, err := zerolog.ParseLevel(lvlStr)
if err != nil {
return nil, false
}
_, enabled := w.levels[lvl]
if !enabled {
return nil, false
}
sentryLvl, ok := levelsMapping[lvl]
if !ok {
return nil, false
}
event := sentry.Event{
Timestamp: now(),
Level: sentryLvl,
Logger: logger,
Extra: map[string]interface{}{},
}
err = jsonparser.ObjectEach(data, func(key, value []byte, vt jsonparser.ValueType, offset int) error {
err := jsonparser.ObjectEach(data, func(key, value []byte, vt jsonparser.ValueType, offset int) error {
switch string(key) {
case zerolog.MessageFieldName:
event.Message = bytesToStrUnsafe(value)
@@ -98,7 +162,6 @@ func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) {
return nil
})
if err != nil {
return nil, false
}
@@ -152,15 +215,27 @@ type optionFunc func(*config)
func (fn optionFunc) apply(c *config) { fn(c) }
type EventHintCallback func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event
type config struct {
levels []zerolog.Level
sampleRate float64
release string
environment string
serverName string
ignoreErrors []string
debug bool
flushTimeout time.Duration
levels []zerolog.Level
sampleRate float64
release string
environment string
serverName string
ignoreErrors []string
breadcrumbs bool
debug bool
tracing bool
debugWriter io.Writer
httpClient *http.Client
httpProxy string
httpsProxy string
caCerts *x509.CertPool
maxErrorDepth int
flushTimeout time.Duration
beforeSend sentry.EventProcessor
tracesSampleRate float64
}
// WithLevels configures zerolog levels that have to be sent to Sentry.
@@ -207,6 +282,13 @@ func WithIgnoreErrors(reList []string) WriterOption {
})
}
// WithBreadcrumbs enables sentry client breadcrumbs.
func WithBreadcrumbs() WriterOption {
return optionFunc(func(cfg *config) {
cfg.breadcrumbs = true
})
}
// WithDebug enables sentry client debug logs.
func WithDebug() WriterOption {
return optionFunc(func(cfg *config) {
@@ -214,6 +296,69 @@ func WithDebug() WriterOption {
})
}
// WithTracing enables sentry client tracing.
func WithTracing() WriterOption {
return optionFunc(func(cfg *config) {
cfg.tracing = true
})
}
// WithTracingSampleRate sets tracing sample rate.
func WithTracingSampleRate(tsr float64) WriterOption {
return optionFunc(func(cfg *config) {
cfg.tracesSampleRate = tsr
})
}
// WithBeforeSend sets a callback which is called before event is sent.
func WithBeforeSend(beforeSend sentry.EventProcessor) WriterOption {
return optionFunc(func(cfg *config) {
cfg.beforeSend = beforeSend
})
}
// WithDebugWriter enables sentry client tracing.
func WithDebugWriter(w io.Writer) WriterOption {
return optionFunc(func(cfg *config) {
cfg.debugWriter = w
})
}
// WithHttpClient sets custom http client.
func WithHttpClient(httpClient *http.Client) WriterOption {
return optionFunc(func(cfg *config) {
cfg.httpClient = httpClient
})
}
// WithHttpProxy enables sentry client tracing.
func WithHttpProxy(proxy string) WriterOption {
return optionFunc(func(cfg *config) {
cfg.httpProxy = proxy
})
}
// WithHttpsProxy enables sentry client tracing.
func WithHttpsProxy(proxy string) WriterOption {
return optionFunc(func(cfg *config) {
cfg.httpsProxy = proxy
})
}
// WithCaCerts enables sentry client tracing.
func WithCaCerts(caCerts *x509.CertPool) WriterOption {
return optionFunc(func(cfg *config) {
cfg.caCerts = caCerts
})
}
// WithMaxErrorDepth sets the max depth of error chain.
func WithMaxErrorDepth(maxErrorDepth int) WriterOption {
return optionFunc(func(cfg *config) {
cfg.maxErrorDepth = maxErrorDepth
})
}
// New creates writer with provided DSN and options.
func New(dsn string, opts ...WriterOption) (*Writer, error) {
cfg := newDefaultConfig()
@@ -222,15 +367,23 @@ func New(dsn string, opts ...WriterOption) (*Writer, error) {
}
err := sentry.Init(sentry.ClientOptions{
Dsn: dsn,
SampleRate: cfg.sampleRate,
Release: cfg.release,
Environment: cfg.environment,
ServerName: cfg.serverName,
IgnoreErrors: cfg.ignoreErrors,
Debug: cfg.debug,
Dsn: dsn,
SampleRate: cfg.sampleRate,
Release: cfg.release,
Environment: cfg.environment,
ServerName: cfg.serverName,
IgnoreErrors: cfg.ignoreErrors,
Debug: cfg.debug,
EnableTracing: cfg.tracing,
DebugWriter: cfg.debugWriter,
HTTPClient: cfg.httpClient,
HTTPProxy: cfg.httpProxy,
HTTPSProxy: cfg.httpsProxy,
CaCerts: cfg.caCerts,
MaxErrorDepth: cfg.maxErrorDepth,
BeforeSend: cfg.beforeSend,
TracesSampleRate: cfg.tracesSampleRate,
})
if err != nil {
return nil, err
}
@@ -241,7 +394,31 @@ func New(dsn string, opts ...WriterOption) (*Writer, error) {
}
return &Writer{
hub: sentry.CurrentHub(),
hub: sentry.CurrentHub(),
levels: levels,
flushTimeout: cfg.flushTimeout,
withBreadcrumbs: cfg.breadcrumbs,
}, nil
}
// NewWithHub creates a writer using an existing sentry Hub and options.
func NewWithHub(hub *sentry.Hub, opts ...WriterOption) (*Writer, error) {
if hub == nil {
return nil, errors.New("hub cannot be nil")
}
cfg := newDefaultConfig()
for _, opt := range opts {
opt.apply(&cfg)
}
levels := make(map[zerolog.Level]struct{}, len(cfg.levels))
for _, lvl := range cfg.levels {
levels[lvl] = struct{}{}
}
return &Writer{
hub: hub,
levels: levels,
flushTimeout: cfg.flushTimeout,
}, nil