zapsentry

package module
v1.14.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2023 License: MIT Imports: 7 Imported by: 0

README

Sentry client for zap logger

Integration using Sentry Client

Integration of sentry client into zap.Logger is pretty simple:

func modifyToSentryLogger(log *zap.Logger, client *sentry.Client) *zap.Logger {
	cfg := zapsentry.Configuration{
		Level: zapcore.ErrorLevel, //when to send message to sentry
		EnableBreadcrumbs: true, // enable sending breadcrumbs to Sentry 
		BreadcrumbLevel: zapcore.InfoLevel, // at what level should we sent breadcrumbs to sentry
		Tags: map[string]string{
			"component": "system",
		},
	}
	core, err := zapsentry.NewCore(cfg, zapsentry.NewSentryClientFromClient(client))
	
	//in case of err it will return noop core. so we can safely attach it
	if err != nil {
		log.Warn("failed to init zap", zap.Error(err))
	}
	
	log = zapsentry.AttachCoreToLogger(core, log)

	// to use breadcrumbs feature - create new scope explicitly
	// and attach after attaching the core
	return log.With(zapsentry.NewScope())
}

Please note that wrapper does not guarantee that all your events will be sent before the app exits. Flush called internally only in case of writing message with severity level > zapcore.ErrorLevel (i.e. Fatal, Panic, ...). If you want to ensure your messages come to sentry - call the flush on native sentry client at defer. Example:

func main() {
	sentryClient, err := sentry.NewClient(sentry.ClientOptions{
		Dsn: "Sentry DSN",
	})
	if err != nil {
		// Handle the error here
	}
	// Flush buffered events before the program terminates.
	// Set the timeout to the maximum duration the program can afford to wait.
	defer sentryClient.Flush(2 * time.Second)
	
	// create zap log and wrapper...
	
	// create and run your app here...
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AttachCoreToLogger

func AttachCoreToLogger(sentryCore zapcore.Core, l *zap.Logger) *zap.Logger
Example
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/getsentry/sentry-go"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"go.uber.org/zap/zaptest/observer"

	"github.com/dkeysil/zapsentry"
)

func main() {
	// Setup zap with observer (for testing), originally we use
	// 		config = zap.NewDevelopmentConfig()
	//  	logger, err := config.Build()
	// to build zap logger, here we use zap/zaptest/observer for testing
	core, recordedLogs := observer.New(zapcore.DebugLevel)
	logger := zap.New(core, zap.AddStacktrace(zap.DebugLevel))

	// Setup mock sentry client for testing, in general we use sentry.NewClient
	var recordedSentryEvent *sentry.Event
	sentryClient := mockSentryClient(func(event *sentry.Event) {
		recordedSentryEvent = event
	})

	// Setup zapsentry
	core, err := zapsentry.NewCore(zapsentry.Configuration{
		Level:             zapcore.ErrorLevel, // when to send message to sentry
		EnableBreadcrumbs: true,               // enable sending breadcrumbs to Sentry
		BreadcrumbLevel:   zapcore.InfoLevel,  // at what level should we sent breadcrumbs to sentry
		Tags: map[string]string{
			"component": "system",
		},
	}, zapsentry.NewSentryClientFromClient(sentryClient))
	if err != nil {
		log.Fatal(err)
	}
	newLogger := zapsentry.AttachCoreToLogger(core, logger)

	// Send error log
	newLogger.
		With(zapsentry.NewScope()).
		Error("[error] something went wrong!", zap.String("method", "unknown"), zapsentry.Tag("service", "app"))

	// Check output
	fmt.Println(recordedLogs.All()[0].Message)
	fmt.Println(recordedSentryEvent.Message)
	fmt.Println(recordedSentryEvent.Extra)
	fmt.Println(recordedSentryEvent.Tags)
}

func mockSentryClient(f func(event *sentry.Event)) *sentry.Client {
	client, _ := sentry.NewClient(sentry.ClientOptions{
		Dsn:       "",
		Transport: &transport{MockSendEvent: f},
	})
	return client
}

type transport struct {
	MockSendEvent func(event *sentry.Event)
}

// Flush waits until any buffered events are sent to the Sentry server, blocking
// for at most the given timeout. It returns false if the timeout was reached.
func (f *transport) Flush(_ time.Duration) bool { return true }

// Configure is called by the Client itself, providing it it's own ClientOptions.
func (f *transport) Configure(_ sentry.ClientOptions) {}

// SendEvent assembles a new packet out of Event and sends it to remote server.
// We use this method to capture the event for testing
func (f *transport) SendEvent(event *sentry.Event) {
	f.MockSendEvent(event)
}
Output:

[error] something went wrong!
[error] something went wrong!
map[method:unknown]
map[component:system service:app]

func NewCore

func NewCore(cfg Configuration, factory SentryClientFactory) (zapcore.Core, error)

func NewScope

func NewScope() zapcore.Field

func NewScopeFromScope

func NewScopeFromScope(scope *sentry.Scope) zapcore.Field

func Tag

func Tag(key string, value string) zap.Field

Types

type ClientGetter

type ClientGetter interface {
	GetClient() *sentry.Client
}

type Configuration

type Configuration struct {
	// Tags are passed as is to the corresponding sentry.Event field.
	Tags map[string]string

	// LoggerNameKey is the key for zap logger name.
	// If not empty, the name is added to the rest of zapcore.Field(s),
	// so that be careful with key duplicates.
	// Leave LoggerNameKey empty to disable the feature.
	LoggerNameKey string

	// DisableStacktrace disables adding stacktrace to sentry.Event, if set.
	DisableStacktrace bool

	// Level is the minimal level of sentry.Event(s).
	Level zapcore.Level

	// EnableBreadcrumbs enables use of sentry.Breadcrumb(s).
	// This feature works only when you explicitly passed new scope.
	EnableBreadcrumbs bool

	// BreadcrumbLevel is the minimal level of sentry.Breadcrumb(s).
	// Breadcrumb specifies an application event that occurred before a Sentry event.
	// NewCore fails if BreadcrumbLevel is greater than Level.
	// The field is ignored, if EnableBreadcrumbs is not set.
	BreadcrumbLevel zapcore.Level

	// MaxBreadcrumbs is the maximum number of breadcrumb events to keep.
	// Leave it zero or set to negative for a reasonable default value.
	// The field is ignored, if EnableBreadcrumbs is not set.
	MaxBreadcrumbs int

	// FlushTimeout is the timeout for flushing events to Sentry.
	FlushTimeout time.Duration

	// Hub overrides the sentry.CurrentHub value.
	// See sentry.Hub docs for more detail.
	Hub *sentry.Hub

	// FilterEvent is a function that is called for every event before it is sent to Sentry.
	// If the function returns true, the event is dropped.
	FilterEvent func(event *sentry.Event) bool
}

Configuration is a minimal set of parameters for Sentry integration.

type LevelEnabler

type LevelEnabler struct {
	zapcore.Level
	// contains filtered or unexported fields
}

func (*LevelEnabler) Enabled

func (l *LevelEnabler) Enabled(lvl zapcore.Level) bool

type SentryClientFactory

type SentryClientFactory func() (*sentry.Client, error)

func NewSentryClientFromClient

func NewSentryClientFromClient(client *sentry.Client) SentryClientFactory

func NewSentryClientFromDSN

func NewSentryClientFromDSN(DSN string) SentryClientFactory

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL