Update dependencies

This commit is contained in:
eleksir
2024-07-24 22:57:56 +03:00
parent ac243bf4fd
commit 00257b8e6c
729 changed files with 47714 additions and 29066 deletions

View File

@@ -49,15 +49,14 @@ type Span struct { //nolint: maligned // prefer readability over optimal memory
// parent refers to the immediate local parent span. A remote parent span is
// only referenced by setting ParentSpanID.
parent *Span
// isTransaction is true only for the root span of a local span tree. The
// root span is the first span started in a context. Note that a local root
// span may have a remote parent belonging to the same trace, therefore
// isTransaction depends on ctx and not on parent.
isTransaction bool
// recorder stores all spans in a transaction. Guaranteed to be non-nil.
recorder *spanRecorder
// span context, can only be set on transactions
contexts map[string]Context
// collectProfile is a function that collects a profile of the current transaction. May be nil.
collectProfile transactionProfiler
// a Once instance to make sure that Finish() is only called once.
finishOnce sync.Once
}
// TraceParentContext describes the context of a (remote) parent span.
@@ -110,9 +109,8 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
StartTime: time.Now(),
Sampled: SampledUndefined,
ctx: context.WithValue(ctx, spanContextKey{}, &span),
parent: parent,
isTransaction: !hasParent,
ctx: context.WithValue(ctx, spanContextKey{}, &span),
parent: parent,
}
if hasParent {
@@ -171,42 +169,34 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
span.Sampled = span.sample()
span.recorder = &spanRecorder{}
if hasParent {
span.recorder = parent.spanRecorder()
} else {
span.recorder = &spanRecorder{}
}
span.recorder.record(&span)
hub := hubFromContext(ctx)
// Update scope so that all events include a trace context, allowing
// Sentry to correlate errors to transactions/spans.
hubFromContext(ctx).Scope().SetContext("trace", span.traceContext().Map())
hub.Scope().SetContext("trace", span.traceContext().Map())
// Start profiling only if it's a sampled root transaction.
if span.IsTransaction() && span.Sampled.Bool() {
span.sampleTransactionProfile()
}
return &span
}
// Finish sets the span's end time, unless already set. If the span is the root
// of a span tree, Finish sends the span tree to Sentry as a transaction.
//
// The logic is executed at most once per span, so that (incorrectly) calling it twice
// never double sends to Sentry.
func (s *Span) Finish() {
// TODO(tracing): maybe make Finish run at most once, such that
// (incorrectly) calling it twice never double sends to Sentry.
if s.EndTime.IsZero() {
s.EndTime = monotonicTimeSince(s.StartTime)
}
if !s.Sampled.Bool() {
return
}
event := s.toEvent()
if event == nil {
return
}
// TODO(tracing): add breadcrumbs
// (see https://github.com/getsentry/sentry-python/blob/f6f3525f8812f609/sentry_sdk/tracing.py#L372)
hub := hubFromContext(s.ctx)
hub.CaptureEvent(event)
s.finishOnce.Do(s.doFinish)
}
// Context returns the context containing the span.
@@ -236,7 +226,11 @@ func (s *Span) SetTag(name, value string) {
// SetData sets a data on the span. It is recommended to use SetData instead of
// accessing the data map directly as SetData takes care of initializing the map
// when necessary.
func (s *Span) SetData(name, value string) {
func (s *Span) SetData(name string, value interface{}) {
if value == nil {
return
}
s.mu.Lock()
defer s.mu.Unlock()
@@ -261,7 +255,7 @@ func (s *Span) SetContext(key string, value Context) {
// IsTransaction checks if the given span is a transaction.
func (s *Span) IsTransaction() bool {
return s.isTransaction
return s.parent == nil
}
// GetTransaction returns the transaction that contains this span.
@@ -293,7 +287,7 @@ func (s *Span) GetTransaction() *Span {
// func (s *Span) TransactionName() string
// func (s *Span) SetTransactionName(name string)
// ToSentryTrace returns the seralized TraceParentContext from a transaction/sapn.
// ToSentryTrace returns the seralized TraceParentContext from a transaction/span.
// Use this function to propagate the TraceParentContext to a downstream SDK,
// either as the value of the "sentry-trace" HTTP header, or as an html "sentry-trace" meta tag.
func (s *Span) ToSentryTrace() string {
@@ -330,11 +324,36 @@ func (s *Span) ToBaggage() string {
// SetDynamicSamplingContext sets the given dynamic sampling context on the
// current transaction.
func (s *Span) SetDynamicSamplingContext(dsc DynamicSamplingContext) {
if s.isTransaction {
if s.IsTransaction() {
s.dynamicSamplingContext = dsc
}
}
// doFinish runs the actual Span.Finish() logic.
func (s *Span) doFinish() {
if s.EndTime.IsZero() {
s.EndTime = monotonicTimeSince(s.StartTime)
}
if !s.Sampled.Bool() {
return
}
event := s.toEvent()
if event == nil {
return
}
if s.collectProfile != nil {
event.sdkMetaData.transactionProfile = s.collectProfile(s)
}
// TODO(tracing): add breadcrumbs
// (see https://github.com/getsentry/sentry-python/blob/f6f3525f8812f609/sentry_sdk/tracing.py#L372)
hub := hubFromContext(s.ctx)
hub.CaptureEvent(event)
}
// sentryTracePattern matches either
//
// TRACE_ID - SPAN_ID
@@ -370,7 +389,7 @@ func (s *Span) updateFromSentryTrace(header []byte) (updated bool) {
}
func (s *Span) updateFromBaggage(header []byte) {
if s.isTransaction {
if s.IsTransaction() {
dsc, err := DynamicSamplingContextFromHeader(header)
if err != nil {
return
@@ -397,14 +416,16 @@ func (s *Span) MarshalJSON() ([]byte, error) {
})
}
func (s *Span) sample() Sampled {
hub := hubFromContext(s.ctx)
var clientOptions ClientOptions
client := hub.Client()
func (s *Span) clientOptions() *ClientOptions {
client := hubFromContext(s.ctx).Client()
if client != nil {
clientOptions = hub.Client().Options()
return &client.options
}
return &ClientOptions{}
}
func (s *Span) sample() Sampled {
clientOptions := s.clientOptions()
// https://develop.sentry.dev/sdk/performance/#sampling
// #1 tracing is not enabled.
if !clientOptions.EnableTracing {
@@ -429,7 +450,7 @@ func (s *Span) sample() Sampled {
// Note: non-transaction should always have a parent, but we check both
// conditions anyway -- the first for semantic meaning, the second to
// avoid a nil pointer dereference.
if !s.isTransaction && s.parent != nil {
if !s.IsTransaction() && s.parent != nil {
return s.parent.Sampled
}
@@ -493,7 +514,7 @@ func (s *Span) toEvent() *Event {
s.mu.Lock()
defer s.mu.Unlock()
if !s.isTransaction {
if !s.IsTransaction() {
return nil // only transactions can be transformed into events
}
@@ -515,10 +536,16 @@ func (s *Span) toEvent() *Event {
contexts := map[string]Context{}
for k, v := range s.contexts {
contexts[k] = v
contexts[k] = cloneContext(v)
}
contexts["trace"] = s.traceContext().Map()
// Make sure that the transaction source is valid
transactionSource := s.Source
if !transactionSource.isValid() {
transactionSource = SourceCustom
}
return &Event{
Type: transactionType,
Transaction: s.Name,
@@ -529,7 +556,7 @@ func (s *Span) toEvent() *Event {
StartTime: s.StartTime,
Spans: finished,
TransactionInfo: &TransactionInfo{
Source: s.Source,
Source: transactionSource,
},
sdkMetaData: SDKMetaData{
dsc: s.dynamicSamplingContext,
@@ -620,6 +647,24 @@ const (
SourceTask TransactionSource = "task"
)
// A set of all valid transaction sources.
var allTransactionSources = map[TransactionSource]struct{}{
SourceCustom: {},
SourceURL: {},
SourceRoute: {},
SourceView: {},
SourceComponent: {},
SourceTask: {},
}
// isValid returns 'true' if the given transaction source is a valid
// source as recognized by the envelope protocol:
// https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations
func (ts TransactionSource) isValid() bool {
_, found := allTransactionSources[ts]
return found
}
// SpanStatus is the status of a span.
type SpanStatus uint8
@@ -782,17 +827,6 @@ func (s Sampled) Bool() bool {
// A SpanOption is a function that can modify the properties of a span.
type SpanOption func(s *Span)
// The TransactionName option sets the name of the current transaction.
//
// A span tree has a single transaction name, therefore using this option when
// starting a span affects the span tree as a whole, potentially overwriting a
// name set previously.
//
// Deprecated: Use WithTransactionSource() instead.
func TransactionName(name string) SpanOption {
return WithTransactionName(name)
}
// WithTransactionName option sets the name of the current transaction.
//
// A span tree has a single transaction name, therefore using this option when
@@ -804,11 +838,11 @@ func WithTransactionName(name string) SpanOption {
}
}
// OpName sets the operation name for a given span.
//
// Deprecated: Use WithOpName() instead.
func OpName(name string) SpanOption {
return WithOpName(name)
// WithDescription sets the description of a span.
func WithDescription(description string) SpanOption {
return func(s *Span) {
s.Description = description
}
}
// WithOpName sets the operation name for a given span.
@@ -818,27 +852,17 @@ func WithOpName(name string) SpanOption {
}
}
// TransctionSource sets the source of the transaction name.
//
// Deprecated: Use WithTransactionSource() instead.
func TransctionSource(source TransactionSource) SpanOption {
return WithTransactionSource(source)
}
// WithTransactionSource sets the source of the transaction name.
//
// Note: if the transaction source is not a valid source (as described
// by the spec https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations),
// it will be corrected to "custom" eventually, before the transaction is sent.
func WithTransactionSource(source TransactionSource) SpanOption {
return func(s *Span) {
s.Source = source
}
}
// SpanSampled updates the sampling flag for a given span.
//
// Deprecated: Use WithSpanSampled() instead.
func SpanSampled(sampled Sampled) SpanOption {
return WithSpanSampled(sampled)
}
// WithSpanSampled updates the sampling flag for a given span.
func WithSpanSampled(sampled Sampled) SpanOption {
return func(s *Span) {
@@ -901,27 +925,9 @@ func TransactionFromContext(ctx context.Context) *Span {
return nil
}
// spanFromContext returns the last span stored in the context or a dummy
// non-nil span.
//
// TODO(tracing): consider exporting this. Without this, users cannot retrieve a
// span from a context since spanContextKey is not exported.
//
// This can be added retroactively, and in the meantime think better whether it
// should return nil (like GetHubFromContext), always non-nil (like
// HubFromContext), or both: two exported functions.
//
// Note the equivalence:
//
// SpanFromContext(ctx).StartChild(...) === StartSpan(ctx, ...)
//
// So we don't aim spanFromContext at creating spans, but mutating existing
// spans that you'd have no access otherwise (because it was created in code you
// do not control, for example SDK auto-instrumentation).
//
// For now we provide TransactionFromContext, which solves the more common case
// of setting tags, etc, on the current transaction.
func spanFromContext(ctx context.Context) *Span {
// SpanFromContext returns the last span stored in the context, or nil if no span
// is set on the context.
func SpanFromContext(ctx context.Context) *Span {
if span, ok := ctx.Value(spanContextKey{}).(*Span); ok {
return span
}
@@ -943,3 +949,41 @@ func StartTransaction(ctx context.Context, name string, options ...SpanOption) *
options...,
)
}
// HTTPtoSpanStatus converts an HTTP status code to a SpanStatus.
func HTTPtoSpanStatus(code int) SpanStatus {
if code < http.StatusBadRequest {
return SpanStatusOK
}
if http.StatusBadRequest <= code && code < http.StatusInternalServerError {
switch code {
case http.StatusForbidden:
return SpanStatusPermissionDenied
case http.StatusNotFound:
return SpanStatusNotFound
case http.StatusTooManyRequests:
return SpanStatusResourceExhausted
case http.StatusRequestEntityTooLarge:
return SpanStatusFailedPrecondition
case http.StatusUnauthorized:
return SpanStatusUnauthenticated
case http.StatusConflict:
return SpanStatusAlreadyExists
default:
return SpanStatusInvalidArgument
}
}
if http.StatusInternalServerError <= code && code < 600 {
switch code {
case http.StatusGatewayTimeout:
return SpanStatusDeadlineExceeded
case http.StatusNotImplemented:
return SpanStatusUnimplemented
case http.StatusServiceUnavailable:
return SpanStatusUnavailable
default:
return SpanStatusInternalError
}
}
return SpanStatusUnknown
}