fix(go.sum): update ResolveSpec dependency to v1.0.87
This commit is contained in:
+354
@@ -0,0 +1,354 @@
|
||||
package sentry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go/attribute"
|
||||
"github.com/getsentry/sentry-go/internal/debuglog"
|
||||
)
|
||||
|
||||
type LogLevel string
|
||||
|
||||
const (
|
||||
LogLevelTrace LogLevel = "trace"
|
||||
LogLevelDebug LogLevel = "debug"
|
||||
LogLevelInfo LogLevel = "info"
|
||||
LogLevelWarn LogLevel = "warn"
|
||||
LogLevelError LogLevel = "error"
|
||||
LogLevelFatal LogLevel = "fatal"
|
||||
)
|
||||
|
||||
const (
|
||||
LogSeverityTrace int = 1
|
||||
LogSeverityDebug int = 5
|
||||
LogSeverityInfo int = 9
|
||||
LogSeverityWarning int = 13
|
||||
LogSeverityError int = 17
|
||||
LogSeverityFatal int = 21
|
||||
)
|
||||
|
||||
type sentryLogger struct {
|
||||
ctx context.Context
|
||||
hub *Hub
|
||||
attributes map[string]attribute.Value
|
||||
defaultAttributes map[string]attribute.Value
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
type logEntry struct {
|
||||
logger *sentryLogger
|
||||
ctx context.Context
|
||||
level LogLevel
|
||||
severity int
|
||||
attributes map[string]attribute.Value
|
||||
shouldPanic bool
|
||||
shouldFatal bool
|
||||
}
|
||||
|
||||
// NewLogger returns a Logger that emits logs to Sentry. If logging is turned off, all logs get discarded.
|
||||
func NewLogger(ctx context.Context) Logger { // nolint: dupl
|
||||
var hub *Hub
|
||||
hub = GetHubFromContext(ctx)
|
||||
if hub == nil {
|
||||
hub = CurrentHub()
|
||||
}
|
||||
|
||||
client := hub.Client()
|
||||
if client != nil && client.options.EnableLogs {
|
||||
// Build default attrs
|
||||
serverAddr := client.options.ServerName
|
||||
if serverAddr == "" {
|
||||
serverAddr, _ = os.Hostname()
|
||||
}
|
||||
|
||||
defaults := map[string]string{
|
||||
"sentry.release": client.options.Release,
|
||||
"sentry.environment": client.options.Environment,
|
||||
"sentry.server.address": serverAddr,
|
||||
"sentry.sdk.name": client.sdkIdentifier,
|
||||
"sentry.sdk.version": client.sdkVersion,
|
||||
}
|
||||
|
||||
defaultAttrs := make(map[string]attribute.Value, len(defaults))
|
||||
for k, v := range defaults {
|
||||
if v != "" {
|
||||
defaultAttrs[k] = attribute.StringValue(v)
|
||||
}
|
||||
}
|
||||
|
||||
return &sentryLogger{
|
||||
ctx: ctx,
|
||||
hub: hub,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
defaultAttributes: defaultAttrs,
|
||||
mu: sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
debuglog.Println("fallback to noopLogger: enableLogs disabled")
|
||||
return &noopLogger{}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Write(p []byte) (int, error) {
|
||||
msg := strings.TrimRight(string(p), "\n")
|
||||
l.Info().Emit(msg)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (l *sentryLogger) log(ctx context.Context, level LogLevel, severity int, message string, entryAttrs map[string]attribute.Value, args ...interface{}) {
|
||||
if message == "" {
|
||||
return
|
||||
}
|
||||
|
||||
hub := hubFromContexts(ctx, l.ctx)
|
||||
if hub == nil {
|
||||
hub = l.hub
|
||||
}
|
||||
client := hub.Client()
|
||||
if client == nil {
|
||||
return
|
||||
}
|
||||
|
||||
scope := hub.Scope()
|
||||
traceID, spanID := resolveTrace(scope, client, ctx, l.ctx)
|
||||
|
||||
// Pre-allocate with capacity hint to avoid map growth reallocations
|
||||
estimatedCap := len(l.defaultAttributes) + len(entryAttrs) + len(args) + 8 // scope ~3 + instance ~5
|
||||
attrs := make(map[string]attribute.Value, estimatedCap)
|
||||
|
||||
// attribute precedence: default -> scope -> instance (from SetAttrs) -> entry-specific
|
||||
for k, v := range l.defaultAttributes {
|
||||
attrs[k] = v
|
||||
}
|
||||
scope.populateAttrs(attrs)
|
||||
|
||||
l.mu.RLock()
|
||||
for k, v := range l.attributes {
|
||||
attrs[k] = v
|
||||
}
|
||||
l.mu.RUnlock()
|
||||
|
||||
for k, v := range entryAttrs {
|
||||
attrs[k] = v
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
attrs["sentry.message.template"] = attribute.StringValue(message)
|
||||
for i, p := range args {
|
||||
attrs[fmt.Sprintf("sentry.message.parameters.%d", i)] = attribute.StringValue(fmt.Sprintf("%+v", p))
|
||||
}
|
||||
}
|
||||
|
||||
log := &Log{
|
||||
Timestamp: time.Now(),
|
||||
TraceID: traceID,
|
||||
SpanID: spanID,
|
||||
Level: level,
|
||||
Severity: severity,
|
||||
Body: fmt.Sprintf(message, args...),
|
||||
Attributes: attrs,
|
||||
}
|
||||
log.approximateSize = computeLogSize(log)
|
||||
|
||||
client.captureLog(log, scope)
|
||||
if client.options.Debug {
|
||||
debuglog.Printf(message, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) SetAttributes(attrs ...attribute.Builder) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
||||
for _, a := range attrs {
|
||||
if a.Value.Type() == attribute.INVALID {
|
||||
debuglog.Printf("invalid attribute: %v", a)
|
||||
continue
|
||||
}
|
||||
l.attributes[a.Key] = a.Value
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Trace() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelTrace,
|
||||
severity: LogSeverityTrace,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Debug() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelDebug,
|
||||
severity: LogSeverityDebug,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Info() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelInfo,
|
||||
severity: LogSeverityInfo,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Warn() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelWarn,
|
||||
severity: LogSeverityWarning,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Error() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelError,
|
||||
severity: LogSeverityError,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Fatal() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelFatal,
|
||||
severity: LogSeverityFatal,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
shouldFatal: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) Panic() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelFatal,
|
||||
severity: LogSeverityFatal,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
shouldPanic: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) LFatal() LogEntry {
|
||||
return &logEntry{
|
||||
logger: l,
|
||||
ctx: l.ctx,
|
||||
level: LogLevelFatal,
|
||||
severity: LogSeverityFatal,
|
||||
attributes: make(map[string]attribute.Value),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *sentryLogger) GetCtx() context.Context {
|
||||
return l.ctx
|
||||
}
|
||||
|
||||
func (e *logEntry) WithCtx(ctx context.Context) LogEntry {
|
||||
return &logEntry{
|
||||
logger: e.logger,
|
||||
ctx: ctx,
|
||||
level: e.level,
|
||||
severity: e.severity,
|
||||
attributes: maps.Clone(e.attributes),
|
||||
shouldPanic: e.shouldPanic,
|
||||
shouldFatal: e.shouldFatal,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *logEntry) String(key, value string) LogEntry {
|
||||
e.attributes[key] = attribute.StringValue(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) StringSlice(key string, value []string) LogEntry {
|
||||
e.attributes[key] = attribute.StringSliceValue(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Int(key string, value int) LogEntry {
|
||||
e.attributes[key] = attribute.Int64Value(int64(value))
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Int64Slice(key string, value []int64) LogEntry {
|
||||
e.attributes[key] = attribute.Int64SliceValue(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Int64(key string, value int64) LogEntry {
|
||||
e.attributes[key] = attribute.Int64Value(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Float64Slice(key string, value []float64) LogEntry {
|
||||
e.attributes[key] = attribute.Float64SliceValue(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Float64(key string, value float64) LogEntry {
|
||||
e.attributes[key] = attribute.Float64Value(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) BoolSlice(key string, value []bool) LogEntry {
|
||||
e.attributes[key] = attribute.BoolSliceValue(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Bool(key string, value bool) LogEntry {
|
||||
e.attributes[key] = attribute.BoolValue(value)
|
||||
return e
|
||||
}
|
||||
|
||||
// Uint64 adds uint64 attributes to the log entry.
|
||||
//
|
||||
// This method is intentionally not part of the LogEntry interface to avoid exposing uint64 in the public API.
|
||||
func (e *logEntry) Uint64(key string, value uint64) LogEntry {
|
||||
e.attributes[key] = attribute.Uint64Value(value)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *logEntry) Emit(args ...interface{}) {
|
||||
e.logger.log(e.ctx, e.level, e.severity, fmt.Sprint(args...), e.attributes)
|
||||
|
||||
if e.level == LogLevelFatal {
|
||||
if e.shouldPanic {
|
||||
panic(fmt.Sprint(args...))
|
||||
}
|
||||
if e.shouldFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *logEntry) Emitf(format string, args ...interface{}) {
|
||||
e.logger.log(e.ctx, e.level, e.severity, format, e.attributes, args...)
|
||||
|
||||
if e.level == LogLevelFatal {
|
||||
if e.shouldPanic {
|
||||
formattedMessage := fmt.Sprintf(format, args...)
|
||||
panic(formattedMessage)
|
||||
}
|
||||
if e.shouldFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user