Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"crypto/x509"
"fmt"
"io"
"log"
"math/rand"
"net/http"
"os"
Expand All @@ -15,6 +14,7 @@ import (
"time"

"github.com/getsentry/sentry-go/internal/debug"
"github.com/getsentry/sentry-go/internal/debuglog"
)

// The identifier of the SDK.
Expand Down Expand Up @@ -78,8 +78,8 @@ type usageError struct {
}

// DebugLogger is an instance of log.Logger that is used to provide debug information about running Sentry Client
// can be enabled by either using DebugLogger.SetOutput directly or with Debug client option.
var DebugLogger = log.New(io.Discard, "[Sentry] ", log.LstdFlags)
// can be enabled by either using debuglog.SetOutput directly or with Debug client option.
var DebugLogger = debuglog.GetLogger()

// EventProcessor is a function that processes an event.
// Event processors are used to change an event before it is sent to Sentry.
Expand Down Expand Up @@ -296,7 +296,7 @@ func NewClient(options ClientOptions) (*Client, error) {
if debugWriter == nil {
debugWriter = os.Stderr
}
DebugLogger.SetOutput(debugWriter)
debuglog.SetOutput(debugWriter)
}

if options.Dsn == "" {
Expand Down Expand Up @@ -401,12 +401,12 @@ func (client *Client) setupIntegrations() {

for _, integration := range integrations {
if client.integrationAlreadyInstalled(integration.Name()) {
DebugLogger.Printf("Integration %s is already installed\n", integration.Name())
debuglog.Printf("Integration %s is already installed\n", integration.Name())
continue
}
client.integrations = append(client.integrations, integration)
integration.SetupOnce(client)
DebugLogger.Printf("Integration installed: %s\n", integration.Name())
debuglog.Printf("Integration installed: %s\n", integration.Name())
}

sort.Slice(client.integrations, func(i, j int) bool {
Expand Down Expand Up @@ -647,7 +647,7 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
// options.TracesSampler when they are started. Other events
// (errors, messages) are sampled here. Does not apply to check-ins.
if event.Type != transactionType && event.Type != checkInType && !sample(client.options.SampleRate) {
DebugLogger.Println("Event dropped due to SampleRate hit.")
debuglog.Println("Event dropped due to SampleRate hit.")
return nil
}

Expand All @@ -663,15 +663,15 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
case transactionType:
if client.options.BeforeSendTransaction != nil {
if event = client.options.BeforeSendTransaction(event, hint); event == nil {
DebugLogger.Println("Transaction dropped due to BeforeSendTransaction callback.")
debuglog.Println("Transaction dropped due to BeforeSendTransaction callback.")
return nil
}
}
case checkInType: // not a default case, since we shouldn't apply BeforeSend on check-in events
default:
if client.options.BeforeSend != nil {
if event = client.options.BeforeSend(event, hint); event == nil {
DebugLogger.Println("Event dropped due to BeforeSend callback.")
debuglog.Println("Event dropped due to BeforeSend callback.")
return nil
}
}
Expand Down Expand Up @@ -738,7 +738,7 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
id := event.EventID
event = processor(event, hint)
if event == nil {
DebugLogger.Printf("Event dropped by one of the Client EventProcessors: %s\n", id)
debuglog.Printf("Event dropped by one of the Client EventProcessors: %s\n", id)
return nil
}
}
Expand All @@ -747,7 +747,7 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
id := event.EventID
event = processor(event, hint)
if event == nil {
DebugLogger.Printf("Event dropped by one of the Global EventProcessors: %s\n", id)
debuglog.Printf("Event dropped by one of the Global EventProcessors: %s\n", id)
return nil
}
}
Expand Down
3 changes: 2 additions & 1 deletion fasthttp/sentryfasthttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/getsentry/sentry-go"
"github.com/getsentry/sentry-go/internal/debuglog"
"github.com/valyala/fasthttp"
)

Expand Down Expand Up @@ -143,7 +144,7 @@ func GetSpanFromContext(ctx *fasthttp.RequestCtx) *sentry.Span {
func convert(ctx *fasthttp.RequestCtx) *http.Request {
defer func() {
if err := recover(); err != nil {
sentry.DebugLogger.Printf("%v", err)
debuglog.Printf("%v", err)
}
}()

Expand Down
3 changes: 2 additions & 1 deletion fiber/sentryfiber.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/gofiber/fiber/v2/utils"

"github.com/getsentry/sentry-go"
"github.com/getsentry/sentry-go/internal/debuglog"
)

const (
Expand Down Expand Up @@ -143,7 +144,7 @@ func GetSpanFromContext(ctx *fiber.Ctx) *sentry.Span {
func convert(ctx *fiber.Ctx) *http.Request {
defer func() {
if err := recover(); err != nil {
sentry.DebugLogger.Printf("%v", err)
debuglog.Printf("%v", err)
}
}()

Expand Down
4 changes: 3 additions & 1 deletion hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"sync"
"time"

"github.com/getsentry/sentry-go/internal/debuglog"
)

type contextKey int
Expand Down Expand Up @@ -308,7 +310,7 @@ func (hub *Hub) AddBreadcrumb(breadcrumb *Breadcrumb, hint *BreadcrumbHint) {
hint = &BreadcrumbHint{}
}
if breadcrumb = client.options.BeforeBreadcrumb(breadcrumb, hint); breadcrumb == nil {
DebugLogger.Println("breadcrumb dropped due to BeforeBreadcrumb callback.")
debuglog.Println("breadcrumb dropped due to BeforeBreadcrumb callback.")
return
}
}
Expand Down
8 changes: 5 additions & 3 deletions integrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"runtime/debug"
"strings"
"sync"

"github.com/getsentry/sentry-go/internal/debuglog"
)

// ================================
Expand All @@ -32,7 +34,7 @@ func (mi *modulesIntegration) processor(event *Event, _ *EventHint) *Event {
mi.once.Do(func() {
info, ok := debug.ReadBuildInfo()
if !ok {
DebugLogger.Print("The Modules integration is not available in binaries built without module support.")
debuglog.Print("The Modules integration is not available in binaries built without module support.")
return
}
mi.modules = extractModules(info)
Expand Down Expand Up @@ -141,7 +143,7 @@ func (iei *ignoreErrorsIntegration) processor(event *Event, _ *EventHint) *Event
for _, suspect := range suspects {
for _, pattern := range iei.ignoreErrors {
if pattern.Match([]byte(suspect)) || strings.Contains(suspect, pattern.String()) {
DebugLogger.Printf("Event dropped due to being matched by `IgnoreErrors` option."+
debuglog.Printf("Event dropped due to being matched by `IgnoreErrors` option."+
"| Value matched: %s | Filter used: %s", suspect, pattern)
return nil
}
Expand Down Expand Up @@ -203,7 +205,7 @@ func (iei *ignoreTransactionsIntegration) processor(event *Event, _ *EventHint)

for _, pattern := range iei.ignoreTransactions {
if pattern.Match([]byte(suspect)) || strings.Contains(suspect, pattern.String()) {
DebugLogger.Printf("Transaction dropped due to being matched by `IgnoreTransactions` option."+
debuglog.Printf("Transaction dropped due to being matched by `IgnoreTransactions` option."+
"| Value matched: %s | Filter used: %s", suspect, pattern)
return nil
}
Expand Down
69 changes: 69 additions & 0 deletions internal/debuglog/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package debuglog

import (
"io"
"log"
"sync"
)

var (
logger *log.Logger
mu sync.RWMutex
)

func init() {

Check failure on line 14 in internal/debuglog/log.go

View workflow job for this annotation

GitHub Actions / Lint

don't use `init` function (gochecknoinits)
logger = log.New(io.Discard, "[Sentry] ", log.LstdFlags)
}

// SetLogger replaces the current debug logger with a new one.
// This function is thread-safe and can be called concurrently.
func SetLogger(l *log.Logger) {
mu.Lock()
defer mu.Unlock()
logger = l
}

func SetOutput(w io.Writer) {
logger.SetOutput(w)
}

// GetLogger returns the current logger instance.
// This function is thread-safe and can be called concurrently.
func GetLogger() *log.Logger {
mu.RLock()
defer mu.RUnlock()
return logger
}

// Printf calls Printf on the underlying logger.
// This function is thread-safe and can be called concurrently.
func Printf(format string, args ...interface{}) {
mu.RLock()
l := logger
mu.RUnlock()
if l != nil {
l.Printf(format, args...)
}
}

// Println calls Println on the underlying logger.
// This function is thread-safe and can be called concurrently.
func Println(args ...interface{}) {
mu.RLock()
l := logger
mu.RUnlock()
if l != nil {
l.Println(args...)
}
}

// Print calls Print on the underlying logger.
// This function is thread-safe and can be called concurrently.
func Print(args ...interface{}) {
mu.RLock()
l := logger
mu.RUnlock()
if l != nil {
l.Print(args...)
}
}
135 changes: 135 additions & 0 deletions internal/debuglog/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package debuglog

import (
"bytes"
"io"
stdlog "log"
"strings"
"sync"
"testing"
)

func TestSetLogger(t *testing.T) {
original := GetLogger()
defer SetLogger(original)

var buf bytes.Buffer
newLogger := stdlog.New(&buf, "[Test] ", stdlog.LstdFlags)
SetLogger(newLogger)

if GetLogger() != newLogger {
t.Error("SetLogger did not set the logger correctly")
}
}

func TestGetLogger(t *testing.T) {
logger := GetLogger()
if logger == nil {
t.Error("GetLogger returned nil")
}
}

func TestPrintf(t *testing.T) {
original := GetLogger()
defer SetLogger(original)

var buf bytes.Buffer
testLogger := stdlog.New(&buf, "", 0)
SetLogger(testLogger)
Printf("test %s %d", "message", 42)

output := buf.String()
if !strings.Contains(output, "test message 42") {
t.Errorf("Printf output incorrect: got %q", output)
}
}

func TestPrintln(t *testing.T) {
original := GetLogger()
defer SetLogger(original)

var buf bytes.Buffer
testLogger := stdlog.New(&buf, "", 0)
SetLogger(testLogger)
Println("test", "message")

output := buf.String()
if !strings.Contains(output, "test message") {
t.Errorf("Println output incorrect: got %q", output)
}
}

func TestPrint(t *testing.T) {
original := GetLogger()
defer SetLogger(original)

var buf bytes.Buffer
testLogger := stdlog.New(&buf, "", 0)
SetLogger(testLogger)
Print("test", "message")

output := buf.String()
if !strings.Contains(output, "testmessage") {
t.Errorf("Print output incorrect: got %q", output)
}
}

func TestConcurrentAccess(t *testing.T) {

Check failure on line 77 in internal/debuglog/log_test.go

View workflow job for this annotation

GitHub Actions / Lint

unused-parameter: parameter 't' seems to be unused, consider removing or renaming it as _ (revive)
original := GetLogger()
defer SetLogger(original)

var wg sync.WaitGroup
iterations := 100

for i := 0; i < iterations; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
Printf("concurrent message %d", n)
}(i)
}

for i := 0; i < iterations; i++ {
wg.Add(1)
go func() {
defer wg.Done()
_ = GetLogger()
}()
}

for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
newLogger := stdlog.New(io.Discard, "[Test] ", stdlog.LstdFlags)
SetLogger(newLogger)
}()
}

wg.Wait()
}

func TestInitialization(t *testing.T) {
// The logger should be initialized on package load
logger := GetLogger()
if logger == nil {
t.Error("Logger was not initialized")
}

var buf bytes.Buffer
testLogger := stdlog.New(&buf, "", 0)
SetLogger(testLogger)
Printf("test")
Println("test")
Print("test")
}

func TestNilLogger(t *testing.T) {

Check failure on line 127 in internal/debuglog/log_test.go

View workflow job for this annotation

GitHub Actions / Lint

unused-parameter: parameter 't' seems to be unused, consider removing or renaming it as _ (revive)
original := GetLogger()
defer SetLogger(original)

SetLogger(nil)
Printf("test")
Println("test")
Print("test")
}
Loading
Loading