Created
December 20, 2025 06:23
-
-
Save radixdev/6d1cb034ccb2fb8a7ec8df62a6541999 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pprof | |
| Search regexp | |
| main alloc_space | |
| bytes.(*Buffer).grow | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/bytes/buffer.go | |
| Total: 0 88.72MB (flat, cum) 28.32% | |
| 102 . . | |
| 103 . . // Reset resets the buffer to be empty, | |
| 104 . . // but it retains the underlying storage for use by future writes. | |
| 105 . . // Reset is the same as [Buffer.Truncate](0). | |
| 106 . . func (b *Buffer) Reset() { | |
| 107 . . b.buf = b.buf[:0] | |
| 108 . . b.off = 0 | |
| 109 . . b.lastRead = opInvalid | |
| 110 . . } | |
| 111 . . | |
| 112 . . // tryGrowByReslice is an inlineable version of grow for the fast-case where the | |
| 113 . . // internal buffer only needs to be resliced. | |
| 114 . . // It returns the index where bytes should be written and whether it succeeded. | |
| 115 . . func (b *Buffer) tryGrowByReslice(n int) (int, bool) { | |
| 116 . . if l := len(b.buf); n <= cap(b.buf)-l { | |
| 117 . . b.buf = b.buf[:l+n] | |
| 118 . . return l, true | |
| 119 . . } | |
| 120 . . return 0, false | |
| 121 . . } | |
| 122 . . | |
| 123 . . // grow grows the buffer to guarantee space for n more bytes. | |
| 124 . . // It returns the index where bytes should be written. | |
| 125 . . // If the buffer can't grow it will panic with ErrTooLarge. | |
| 126 . . func (b *Buffer) grow(n int) int { | |
| 127 . . m := b.Len() | |
| 128 . . // If buffer is empty, reset to recover space. | |
| 129 . . if m == 0 && b.off != 0 { | |
| 130 . . b.Reset() | |
| 131 . . } | |
| 132 . . // Try to grow by means of a reslice. | |
| 133 . . if i, ok := b.tryGrowByReslice(n); ok { | |
| 134 . . return i | |
| 135 . . } | |
| 136 . . if b.buf == nil && n <= smallBufferSize { | |
| 137 . . b.buf = make([]byte, n, smallBufferSize) | |
| 138 . . return 0 | |
| 139 . . } | |
| 140 . . c := cap(b.buf) | |
| 141 . . if n <= c/2-m { | |
| 142 . . // We can slide things down instead of allocating a new | |
| 143 . . // slice. We only need m+n <= c to slide, but | |
| 144 . . // we instead let capacity get twice as large so we | |
| 145 . . // don't spend all our time copying. | |
| 146 . . copy(b.buf, b.buf[b.off:]) | |
| 147 . . } else if c > maxInt-c-n { | |
| 148 . . panic(ErrTooLarge) | |
| 149 . . } else { | |
| 150 . . // Add b.off to account for b.buf[:b.off] being sliced off the front. | |
| 151 . 88.72MB b.buf = growSlice(b.buf[b.off:], b.off+n) | |
| 152 . . } | |
| 153 . . // Restore b.off and len(b.buf). | |
| 154 . . b.off = 0 | |
| 155 . . b.buf = b.buf[:m+n] | |
| 156 . . return m | |
| 157 . . } | |
| 158 . . | |
| 159 . . // Grow grows the buffer's capacity, if necessary, to guarantee space for | |
| 160 . . // another n bytes. After Grow(n), at least n bytes can be written to the | |
| 161 . . // buffer without another allocation. | |
| bytes.(*Buffer).Write | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/bytes/buffer.go | |
| Total: 0 1MB (flat, cum) 0.32% | |
| 170 . . } | |
| 171 . . | |
| 172 . . // Write appends the contents of p to the buffer, growing the buffer as | |
| 173 . . // needed. The return value n is the length of p; err is always nil. If the | |
| 174 . . // buffer becomes too large, Write will panic with [ErrTooLarge]. | |
| 175 . . func (b *Buffer) Write(p []byte) (n int, err error) { | |
| 176 . . b.lastRead = opInvalid | |
| 177 . . m, ok := b.tryGrowByReslice(len(p)) | |
| 178 . . if !ok { | |
| 179 . 1MB m = b.grow(len(p)) | |
| 180 . . } | |
| 181 . . return copy(b.buf[m:], p), nil | |
| 182 . . } | |
| 183 . . | |
| 184 . . // WriteString appends the contents of s to the buffer, growing the buffer as | |
| 185 . . // needed. The return value n is the length of s; err is always nil. If the | |
| 186 . . // buffer becomes too large, WriteString will panic with [ErrTooLarge]. | |
| bytes.growSlice | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/bytes/buffer.go | |
| Total: 88.72MB 88.72MB (flat, cum) 28.32% | |
| 224 . . } | |
| 225 . . } | |
| 226 . . | |
| 227 . . // growSlice grows b by n, preserving the original content of b. | |
| 228 . . // If the allocation fails, it panics with ErrTooLarge. | |
| 229 . . func growSlice(b []byte, n int) []byte { | |
| 230 . . defer func() { | |
| 231 . . if recover() != nil { | |
| 232 . . panic(ErrTooLarge) | |
| 233 . . } | |
| 234 . . }() | |
| 235 . . // TODO(http://golang.org/issue/51462): We should rely on the append-make | |
| 236 . . // pattern so that the compiler can call runtime.growslice. For example: | |
| 237 . . // return append(b, make([]byte, n)...) | |
| 238 . . // This avoids unnecessary zero-ing of the first len(b) bytes of the | |
| 239 . . // allocated slice, but this pattern causes b to escape onto the heap. | |
| 240 . . // | |
| 241 . . // Instead use the append-make pattern with a nil slice to ensure that | |
| 242 . . // we allocate buffers rounded up to the closest size class. | |
| 243 . . c := len(b) + n // ensure enough space for n elements | |
| 244 . . if c < 2*cap(b) { | |
| 245 . . // The growth rate has historically always been 2x. In the future, | |
| 246 . . // we could rely purely on append to determine the growth rate. | |
| 247 . . c = 2 * cap(b) | |
| 248 . . } | |
| 249 88.72MB 88.72MB b2 := append([]byte(nil), make([]byte, c)...) | |
| 250 . . i := copy(b2, b) | |
| 251 . . return b2[:i] | |
| 252 . . } | |
| 253 . . | |
| 254 . . // WriteTo writes data to w until the buffer is drained or an error occurs. | |
| 255 . . // The return value n is the number of bytes written; it always fits into an | |
| 256 . . // int, but it is int64 to match the [io.WriterTo] interface. Any error | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.spanStart | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/span.go | |
| Total: 2.50MB 2.50MB (flat, cum) 0.8% | |
| 527 . . return builder.String() | |
| 528 . . } | |
| 529 . . | |
| 530 . . // setMeta sets a string tag. This method is not safe for concurrent use. | |
| 531 . . func (s *Span) setMeta(key, v string) { | |
| 532 . . if s.meta == nil { | |
| 533 2.50MB 2.50MB s.meta = make(map[string]string, 1) | |
| 534 . . } | |
| 535 . . delete(s.metrics, key) | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.spanStart | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/span.go | |
| Total: 20.51MB 20.51MB (flat, cum) 6.54% | |
| 546 20.51MB 20.51MB s.meta[key] = v | |
| 547 . . } | |
| 548 . . } | |
| 549 . . | |
| 550 . . func (s *Span) setMetaStruct(key string, v any) { | |
| 551 . . if s.metaStruct == nil { | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*Span).setMetric | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/span.go | |
| Total: 18.50MB 18.50MB (flat, cum) 5.90% | |
| 580 . . } | |
| 581 . . } | |
| 582 . . | |
| 583 . . // setMetric sets a numeric tag, in our case called a metric. This method | |
| 584 . . // is not safe for concurrent use. | |
| 585 . . func (s *Span) setMetric(key string, v float64) { | |
| 586 . . if s.metrics == nil { | |
| 587 5MB 5MB s.metrics = make(map[string]float64, 1) | |
| 588 . . } | |
| 589 . . delete(s.meta, key) | |
| 590 . . switch key { | |
| 591 . . case ext.ManualKeep: | |
| 592 . . if v == float64(samplernames.AppSec) { | |
| 593 . . s.setSamplingPriorityLocked(ext.PriorityUserKeep, samplernames.AppSec) | |
| 594 . . } | |
| 595 . . case "_sampling_priority_v1shim": | |
| 596 . . // We have this for backward compatibility with the v1 shim. | |
| 597 . . s.setSamplingPriorityLocked(int(v), samplernames.Manual) | |
| 598 . . default: | |
| 599 13.50MB 13.50MB s.metrics[key] = v | |
| 600 . . } | |
| 601 . . } | |
| 602 . . | |
| 603 . . // AddLink appends the given link to the span's span links. | |
| 604 . . func (s *Span) AddLink(link SpanLink) { | |
| 605 . . if s == nil { | |
| 606 . . return | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.newSpanContext | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 13.50MB 15MB (flat, cum) 4.79% | |
| 153 . . // newSpanContext creates a new SpanContext to serve as context for the given | |
| 154 . . // span. If the provided parent is not nil, the context will inherit the trace, | |
| 155 . . // baggage and other values from it. This method also pushes the span into the | |
| 156 . . // new context's trace and as a result, it should not be called multiple times | |
| 157 . . // for the same span. | |
| 158 . . func newSpanContext(span *Span, parent *SpanContext) *SpanContext { | |
| 159 13.50MB 13.50MB context := &SpanContext{ | |
| 160 . . spanID: span.spanID, | |
| 161 . . span: span, | |
| 162 . . } | |
| 163 . . | |
| 164 . . context.traceID.SetLower(span.traceID) | |
| 165 . . if parent != nil { | |
| 166 . . if !parent.baggageOnly { | |
| 167 . . context.traceID.SetUpper(parent.traceID.Upper()) | |
| 168 . . context.trace = parent.trace | |
| 169 . . context.origin = parent.origin | |
| 170 . . context.errors.Store(parent.errors.Load()) | |
| 171 . . } | |
| 172 . . parent.ForeachBaggageItem(func(k, v string) bool { | |
| 173 . . context.setBaggageItem(k, v) | |
| 174 . . return true | |
| 175 . . }) | |
| 176 . . } else if sharedinternal.BoolEnv("DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED", true) { | |
| 177 . . // add 128 bit trace id, if enabled, formatted as big-endian: | |
| 178 . . // <32-bit unix seconds> <32 bits of zero> <64 random bits> | |
| 179 . . id128 := time.Duration(span.start) / time.Second | |
| 180 . . // casting from int64 -> uint32 should be safe since the start time won't be | |
| 181 . . // negative, and the seconds should fit within 32-bits for the foreseeable future. | |
| 182 . . // (We only want 32 bits of time, then the rest is zero) | |
| 183 . . tUp := uint64(uint32(id128)) << 32 // We need the time at the upper 32 bits of the uint | |
| 184 . . context.traceID.SetUpper(tUp) | |
| 185 . . } | |
| 186 . . if context.trace == nil { | |
| 187 . . context.trace = newTrace() | |
| 188 . . } | |
| 189 . . if context.trace.root == nil { | |
| 190 . . // first span in the trace can safely be assumed to be the root | |
| 191 . . context.trace.root = span | |
| 192 . . } | |
| 193 . . // put span in context's trace | |
| 194 . 1.50MB context.trace.push(span) | |
| 195 . . // setting context.updated to false here is necessary to distinguish | |
| 196 . . // between initializing properties of the span (priority) | |
| 197 . . // and updating them after extracting context through propagators | |
| 198 . . context.updated = false | |
| 199 . . return context | |
| 200 . . } | |
| 201 . . | |
| 202 . . // SpanID implements ddtrace.SpanContext. | |
| 203 . . func (c *SpanContext) SpanID() uint64 { | |
| 204 . . if c == nil { | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*SpanContext).setSamplingPriority | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 0 11MB (flat, cum) 3.51% | |
| 262 . . } | |
| 263 . . } | |
| 264 . . } | |
| 265 . . | |
| 266 . . // sets the sampling priority and decision maker (based on `sampler`). | |
| 267 . . func (c *SpanContext) setSamplingPriority(p int, sampler samplernames.SamplerName) { | |
| 268 . . if c.trace == nil { | |
| 269 . . c.trace = newTrace() | |
| 270 . . } | |
| 271 . 11MB if c.trace.setSamplingPriority(p, sampler) { | |
| 272 . . // the trace's sampling priority or sampler was updated: mark this as updated | |
| 273 . . c.updated = true | |
| 274 . . } | |
| 275 . . } | |
| 276 . . | |
| 277 . . // forceSetSamplingPriority sets (and forces if the trace is locked) the sampling priority and decision maker (based on `sampler`). | |
| 278 . . func (c *SpanContext) forceSetSamplingPriority(p int, sampler samplernames.SamplerName) { | |
| 279 . . if c.trace == nil { | |
| 280 . . c.trace = newTrace() | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.newSpanContext | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 6MB 6MB (flat, cum) 1.91% | |
| 381 . . ) | |
| 382 . . | |
| 383 . . // newTrace creates a new trace using the given callback which will be called | |
| 384 . . // upon completion of the trace. | |
| 385 . . func newTrace() *trace { | |
| 386 6MB 6MB return &trace{spans: make([]*Span, 0, traceStartSize)} | |
| 387 . . } | |
| 388 . . | |
| 389 . . func (t *trace) samplingPriorityLocked() (p int, ok bool) { | |
| 390 . . if t.priority == nil { | |
| 391 . . return 0, false | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).setSamplingPriorityLockedWithForce | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 1MB 1MB (flat, cum) 0.32% | |
| 435 . . } | |
| 436 . . t.tags[key] = value | |
| 437 . . } | |
| 438 . . | |
| 439 . . func samplerToDM(sampler samplernames.SamplerName) string { | |
| 440 512.01kB 512.01kB return "-" + strconv.Itoa(int(sampler)) | |
| 441 . . } | |
| 442 . . | |
| 443 . . // setSamplingPriority sets the sampling priority and the decision maker | |
| 444 . . // and returns true if it was modified. | |
| 445 . . // | |
| 446 . . // The force parameter is used to bypass the locked sampling decision check | |
| 447 . . // when setting the sampling priority. This is used to apply a manual keep or drop decision. | |
| 448 . . func (t *trace) setSamplingPriorityLockedWithForce(p int, sampler samplernames.SamplerName, force bool) bool { | |
| 449 . . if t.locked && !force { | |
| 450 . . return false | |
| 451 . . } | |
| 452 . . | |
| 453 . . updatedPriority := t.priority == nil || *t.priority != float64(p) | |
| 454 . . | |
| 455 . . if t.priority == nil { | |
| 456 512.01kB 512.01kB t.priority = new(float64) | |
| 457 . . } | |
| 458 . . *t.priority = float64(p) | |
| 459 . . curDM, existed := t.propagatingTags[keyDecisionMaker] | |
| 460 . . if p > 0 && sampler != samplernames.Unknown { | |
| 461 . . // We have a positive priority and the sampling mechanism isn't set. | |
| 462 . . // Send nothing when sampler is `Unknown` for RFC compliance. | |
| 463 . . // If a global sampling rate is set, it was always applied first. And this call can be | |
| 464 . . // triggered again by applying a rule sampler. The sampling priority will be the same, but | |
| 465 . . // the decision maker will be different. So we compare the decision makers as well. | |
| 466 . . // Note that once global rate sampling is deprecated, we no longer need to compare | |
| 467 . . // the DMs. Sampling priority is sufficient to distinguish a change in DM. | |
| 468 . . dm := samplerToDM(sampler) | |
| 469 . . updatedDM := !existed || dm != curDM | |
| 470 . . if updatedDM { | |
| 471 . . t.setPropagatingTagLocked(keyDecisionMaker, dm) | |
| 472 . . return true | |
| 473 . . } | |
| 474 . . } | |
| 475 . . if p <= 0 && existed { | |
| 476 . . delete(t.propagatingTags, keyDecisionMaker) | |
| 477 . . } | |
| 478 . . | |
| 479 . . return updatedPriority | |
| 480 . . } | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).setSamplingPriority | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 0 11MB (flat, cum) 3.51% | |
| 482 . . func (t *trace) setSamplingPriorityLocked(p int, sampler samplernames.SamplerName) bool { | |
| 483 . 11MB return t.setSamplingPriorityLockedWithForce(p, sampler, false) | |
| 484 . . } | |
| 485 . . | |
| 486 . . func (t *trace) isLocked() bool { | |
| 487 . . t.mu.RLock() | |
| 488 . . defer t.mu.RUnlock() | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).push | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 1.50MB 1.50MB (flat, cum) 0.48% | |
| 495 . . t.locked = locked | |
| 496 . . } | |
| 497 . . | |
| 498 . . // push pushes a new span into the trace. If the buffer is full, it returns | |
| 499 . . // a errBufferFull error. | |
| 500 . . func (t *trace) push(sp *Span) { | |
| 501 . . t.mu.Lock() | |
| 502 . . defer t.mu.Unlock() | |
| 503 . . if t.full { | |
| 504 . . return | |
| 505 . . } | |
| 506 . . tr := getGlobalTracer() | |
| 507 . . if len(t.spans) >= traceMaxSize { | |
| 508 . . // capacity is reached, we will not be able to complete this trace. | |
| 509 . . t.full = true | |
| 510 . . t.spans = nil // allow our spans to be collected by GC. | |
| 511 . . log.Error("trace buffer full (%d spans), dropping trace", traceMaxSize) | |
| 512 . . if tr != nil { | |
| 513 . . tracerstats.Signal(tracerstats.TracesDropped, 1) | |
| 514 . . } | |
| 515 . . return | |
| 516 . . } | |
| 517 . . if v, ok := sp.metrics[keySamplingPriority]; ok { | |
| 518 . . t.setSamplingPriorityLocked(int(v), samplernames.Unknown) | |
| 519 . . } | |
| 520 1.50MB 1.50MB t.spans = append(t.spans, sp) | |
| 521 . . if tr != nil { | |
| 522 . . tracerstats.Signal(tracerstats.SpanStarted, 1) | |
| 523 . . } | |
| 524 . . } | |
| 525 . . | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).setTraceTags | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 0 2.50MB (flat, cum) 0.8% | |
| 527 . . // t must already be locked. | |
| 528 . . func (t *trace) setTraceTags(s *Span) { | |
| 529 . . for k, v := range t.tags { | |
| 530 . . s.setMeta(k, v) | |
| 531 . . } | |
| 532 . . for k, v := range t.propagatingTags { | |
| 533 . . s.setMeta(k, v) | |
| 534 . . } | |
| 535 . 2.50MB for k, v := range sharedinternal.GetTracerGitMetadataTags() { | |
| 536 . . s.setMeta(k, v) | |
| 537 . . } | |
| 538 . . if s.context != nil && s.context.traceID.HasUpper() { | |
| 539 . . s.setMeta(keyTraceID128, s.context.traceID.UpperHex()) | |
| 540 . . } | |
| 541 . . } | |
| 542 . . | |
| 543 . . // finishedOne acknowledges that another span in the trace has finished, and checks | |
| 544 . . // if the trace is complete, in which case it calls the onFinish function. It uses | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).finishedOne | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/spancontext.go | |
| Total: 2MB 5MB (flat, cum) 1.60% | |
| 545 . . // the given priority, if non-nil, to mark the root span. This also will trigger a partial flush | |
| 546 . . // if enabled and the total number of finished spans is greater than or equal to the partial flush limit. | |
| 547 . . // The provided span must be locked. | |
| 548 . . func (t *trace) finishedOne(s *Span) { | |
| 549 . . t.mu.Lock() | |
| 550 . . defer t.mu.Unlock() | |
| 551 . . s.finished = true | |
| 552 . . if t.full { | |
| 553 . . // capacity has been reached, the buffer is no longer tracking | |
| 554 . . // all the spans in the trace, so the below conditions will not | |
| 555 . . // be accurate and would trigger a pre-mature flush, exposing us | |
| 556 . . // to a race condition where spans can be modified while flushing. | |
| 557 . . // | |
| 558 . . // TODO(partialFlush): should we do a partial flush in this scenario? | |
| 559 . . return | |
| 560 . . } | |
| 561 . . t.finished++ | |
| 562 . . tr := getGlobalTracer() | |
| 563 . . if tr == nil { | |
| 564 . . return | |
| 565 . . } | |
| 566 . . tc := tr.TracerConf() | |
| 567 . . setPeerService(s, tc) | |
| 568 . . | |
| 569 . . // attach the _dd.base_service tag only when the globally configured service name is different from the | |
| 570 . . // span service name. | |
| 571 . . if s.service != "" && !strings.EqualFold(s.service, tc.ServiceTag) { | |
| 572 . . s.meta[keyBaseService] = tc.ServiceTag | |
| 573 . . } | |
| 574 . . if s == t.root && t.priority != nil { | |
| 575 . . // after the root has finished we lock down the priority; | |
| 576 . . // we won't be able to make changes to a span after finishing | |
| 577 . . // without causing a race condition. | |
| 578 . . t.root.setMetric(keySamplingPriority, *t.priority) | |
| 579 . . t.locked = true | |
| 580 . . } | |
| 581 . . if len(t.spans) > 0 && s == t.spans[0] { | |
| 582 . . // first span in chunk finished, lock down the tags | |
| 583 . . // | |
| 584 . . // TODO(barbayar): make sure this doesn't happen in vain when switching to | |
| 585 . . // the new wire format. We won't need to set the tags on the first span | |
| 586 . . // in the chunk there. | |
| 587 . 3MB t.setTraceTags(s) | |
| 588 . . } | |
| 589 . . | |
| 590 . . // This is here to support the mocktracer. It would be nice to be able to not do this. | |
| 591 . . // We need to track when any single span is finished. | |
| 592 . . if mtr, ok := tr.(interface{ FinishSpan(*Span) }); ok { | |
| 593 . . mtr.FinishSpan(s) | |
| 594 . . } | |
| 595 . . | |
| 596 . . if len(t.spans) == t.finished { // perform a full flush of all spans | |
| 597 . . if tr, ok := tr.(*tracer); ok { | |
| 598 2MB 2MB t.finishChunk(tr, &chunk{ | |
| 599 . . spans: t.spans, | |
| 600 . . willSend: decisionKeep == samplingDecision(atomic.LoadUint32((*uint32)(&t.samplingDecision))), | |
| 601 . . }) | |
| 602 . . } | |
| 603 . . t.spans = nil | |
| 604 . . return | |
| 605 . . } | |
| 606 . . | |
| 607 . . doPartialFlush := tc.PartialFlush && t.finished >= tc.PartialFlushMinSpans | |
| 608 . . if !doPartialFlush { | |
| 609 . . return // The trace hasn't completed and partial flushing will not occur | |
| 610 . . } | |
| 611 . . log.Debug("Partial flush triggered with %d finished spans", t.finished) | |
| 612 . . telemetry.Count(telemetry.NamespaceTracers, "trace_partial_flush.count", []string{"reason:large_trace"}).Submit(1) | |
| 613 . . finishedSpans := make([]*Span, 0, t.finished) | |
| 614 . . leftoverSpans := make([]*Span, 0, len(t.spans)-t.finished) | |
| 615 . . for _, s2 := range t.spans { | |
| 616 . . if s2.finished { | |
| 617 . . finishedSpans = append(finishedSpans, s2) | |
| 618 . . } else { | |
| 619 . . leftoverSpans = append(leftoverSpans, s2) | |
| 620 . . } | |
| 621 . . } | |
| 622 . . telemetry.Distribution(telemetry.NamespaceTracers, "trace_partial_flush.spans_closed", nil).Submit(float64(len(finishedSpans))) | |
| 623 . . telemetry.Distribution(telemetry.NamespaceTracers, "trace_partial_flush.spans_remaining", nil).Submit(float64(len(leftoverSpans))) | |
| 624 . . finishedSpans[0].setMetric(keySamplingPriority, *t.priority) | |
| 625 . . if s != t.spans[0] { | |
| 626 . . // Make sure the first span in the chunk has the trace-level tags | |
| 627 . . t.setTraceTags(finishedSpans[0]) | |
| 628 . . } | |
| 629 . . if tr, ok := tr.(*tracer); ok { | |
| 630 . . t.finishChunk(tr, &chunk{ | |
| 631 . . spans: finishedSpans, | |
| 632 . . willSend: decisionKeep == samplingDecision(atomic.LoadUint32((*uint32)(&t.samplingDecision))), | |
| 633 . . }) | |
| 634 . . } | |
| 635 . . t.spans = leftoverSpans | |
| 636 . . } | |
| 637 . . | |
| 638 . . func (t *trace) finishChunk(tr *tracer, ch *chunk) { | |
| 639 . . tr.submitChunk(ch) | |
| 640 . . t.finished = 0 // important, because a buffer can be used for several flushes | |
| 641 . . } | |
| 642 . . | |
| 643 . . // setPeerService sets the peer.service, _dd.peer.service.source, and _dd.peer.service.remapped_from | |
| 644 . . // tags as applicable for the given span. | |
| 645 . . func setPeerService(s *Span, tc TracerConf) { | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.spanStart | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/tracer.go | |
| Total: 18.50MB 52.01MB (flat, cum) 16.60% | |
| 621 . . } | |
| 622 . . default: | |
| 623 . . } | |
| 624 . . } | |
| 625 . . | |
| 626 . . func spanStart(operationName string, options ...StartSpanOption) *Span { | |
| 627 6.50MB 6.50MB var opts StartSpanConfig | |
| 628 . . for _, fn := range options { | |
| 629 . . if fn == nil { | |
| 630 . . continue | |
| 631 . . } | |
| 632 . . fn(&opts) | |
| 633 . . } | |
| 634 . . var startTime int64 | |
| 635 . . if opts.StartTime.IsZero() { | |
| 636 . . startTime = now() | |
| 637 . . } else { | |
| 638 . . startTime = opts.StartTime.UnixNano() | |
| 639 . . } | |
| 640 . . var context *SpanContext | |
| 641 . . // The default pprof context is taken from the start options and is | |
| 642 . . // not nil when using StartSpanFromContext() | |
| 643 . . pprofContext := opts.Context | |
| 644 . . if opts.Parent != nil { | |
| 645 . . context = opts.Parent | |
| 646 . . if pprofContext == nil && context.span != nil { | |
| 647 . . // Inherit the context.Context from parent span if it was propagated | |
| 648 . . // using ChildOf() rather than StartSpanFromContext(), see | |
| 649 . . // applyPPROFLabels() below. | |
| 650 . . context.span.mu.RLock() | |
| 651 . . pprofContext = context.span.pprofCtxActive | |
| 652 . . context.span.mu.RUnlock() | |
| 653 . . } | |
| 654 . . } | |
| 655 . . if pprofContext == nil { | |
| 656 . . // For root span's without context, there is no pprofContext, but we need | |
| 657 . . // one to avoid a panic() in pprof.WithLabels(). Using context.Background() | |
| 658 . . // is not ideal here, as it will cause us to remove all labels from the | |
| 659 . . // goroutine when the span finishes. However, the alternatives of not | |
| 660 . . // applying labels for such spans or to leave the endpoint/hotspot labels | |
| 661 . . // on the goroutine after it finishes are even less appealing. We'll have | |
| 662 . . // to properly document this for users. | |
| 663 . . pprofContext = gocontext.Background() | |
| 664 . . } | |
| 665 . . id := opts.SpanID | |
| 666 . . if id == 0 { | |
| 667 . . id = generateSpanID(startTime) | |
| 668 . . } | |
| 669 . . // span defaults | |
| 670 12MB 12MB span := &Span{ | |
| 671 . . name: operationName, | |
| 672 . . service: "", | |
| 673 . . resource: operationName, | |
| 674 . . spanID: id, | |
| 675 . . traceID: id, | |
| 676 . . start: startTime, | |
| 677 . . integration: "manual", | |
| 678 . . } | |
| 679 . . | |
| 680 . . span.spanLinks = append(span.spanLinks, opts.SpanLinks...) | |
| 681 . . | |
| 682 . . if context != nil && !context.baggageOnly { | |
| 683 . . // this is a child span | |
| 684 . . span.traceID = context.traceID.Lower() | |
| 685 . . span.parentID = context.spanID | |
| 686 . . if p, ok := context.SamplingPriority(); ok { | |
| 687 . 12MB span.setMetric(keySamplingPriority, float64(p)) | |
| 688 . . } | |
| 689 . . if context.span != nil { | |
| 690 . . // local parent, inherit service | |
| 691 . . context.span.mu.RLock() | |
| 692 . . span.service = context.span.service | |
| 693 . . context.span.mu.RUnlock() | |
| 694 . . } else { | |
| 695 . . // remote parent | |
| 696 . . if context.origin != "" { | |
| 697 . . // mark origin | |
| 698 . . span.setMeta(keyOrigin, context.origin) | |
| 699 . . } | |
| 700 . . } | |
| 701 . . | |
| 702 . . if context.reparentID != "" { | |
| 703 . . span.setMeta(keyReparentID, context.reparentID) | |
| 704 . . } | |
| 705 . . | |
| 706 . . } | |
| 707 . 21MB span.context = newSpanContext(span, context) | |
| 708 . . if pprofContext != nil { | |
| 709 . . setLLMObsPropagatingTags(pprofContext, span.context) | |
| 710 . . } | |
| 711 . . span.setMeta("language", "go") | |
| 712 . . // add tags from options | |
| 713 . . for k, v := range opts.Tags { | |
| 714 . 512.28kB span.SetTag(k, v) | |
| 715 . . } | |
| 716 . . isRootSpan := context == nil || context.span == nil | |
| 717 . . if isRootSpan { | |
| 718 . . traceprof.SetProfilerRootTags(span) | |
| 719 . . } | |
| 720 . . if isRootSpan || context.span.service != span.service { | |
| 721 . . // The span is the local root span. | |
| 722 . . span.setMetric(keyTopLevel, 1) | |
| 723 . . // all top level spans are measured. So the measured tag is redundant. | |
| 724 . . delete(span.metrics, keyMeasured) | |
| 725 . . } | |
| 726 . . pprofContext, span.taskEnd = startExecutionTracerTask(pprofContext, span) | |
| 727 . . span.pprofCtxRestore = pprofContext | |
| 728 . . return span | |
| 729 . . } | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*tracer).StartSpan | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/tracer.go | |
| Total: 0 81.52MB (flat, cum) 26.02% | |
| 731 . . // StartSpan creates, starts, and returns a new Span with the given `operationName`. | |
| 732 . . func (t *tracer) StartSpan(operationName string, options ...StartSpanOption) *Span { | |
| 733 . . if !t.config.enabled.current { | |
| 734 . . return nil | |
| 735 . . } | |
| 736 . 81.52MB span := spanStart(operationName, options...) | |
| 737 . . if span.service == "" { | |
| 738 . . span.service = t.config.serviceName | |
| 739 . . } | |
| 740 . . span.noDebugStack = t.config.noDebugStack | |
| 741 . . if t.config.hostname != "" { | |
| 742 . . span.setMeta(keyHostname, t.config.hostname) | |
| 743 . . } | |
| 744 . . span.supportsEvents = t.config.agent.spanEventsAvailable | |
| 745 . . | |
| 746 . . // add global tags | |
| 747 . . for k, v := range t.config.globalTags.get() { | |
| 748 . . span.SetTag(k, v) | |
| 749 . . } | |
| 750 . . if t.config.serviceMappings != nil { | |
| 751 . . if newSvc, ok := t.config.serviceMappings[span.service]; ok { | |
| 752 . . span.service = newSvc | |
| 753 . . } | |
| 754 . . } | |
| 755 . . if t.config.version != "" { | |
| 756 . . if t.config.universalVersion || (!t.config.universalVersion && span.service == t.config.serviceName) { | |
| 757 . . span.setMeta(ext.Version, t.config.version) | |
| github.com/lesismal/nbio.(*Engine).Start | |
| /Users/julian/go/pkg/mod/github.com/lesismal/nbio@v1.6.7/engine_unix.go | |
| Total: 16MB 16MB (flat, cum) 5.11% | |
| 22 . . ) | |
| 23 . . | |
| 24 . . // Start inits and starts pollers. | |
| 25 . . // | |
| 26 . . //go:norace | |
| 27 . . func (g *Engine) Start() error { | |
| 28 16MB 16MB g.connsUnix = make([]*Conn, MaxOpenFiles) | |
| 29 . . | |
| 30 . . // Create pollers and listeners. | |
| 31 . . g.pollers = make([]*poller, g.NPoller) | |
| 32 . . g.listeners = make([]*poller, len(g.Addrs))[0:0] | |
| 33 . . udpListeners := make([]*net.UDPConn, len(g.Addrs))[0:0] | |
| 34 . . | |
| 35 . . switch g.Network { | |
| 36 . . case NETWORK_UNIX, NETWORK_TCP, NETWORK_TCP4, NETWORK_TCP6: | |
| 37 . . for i := range g.Addrs { | |
| 38 . . ln, err := newPoller(g, true, i) | |
| 39 . . if err != nil { | |
| 40 . . for j := 0; j < i; j++ { | |
| 41 . . g.listeners[j].stop() | |
| 42 . . } | |
| 43 . . return err | |
| 44 . . } | |
| 45 . . g.Addrs[i] = ln.listener.Addr().String() | |
| 46 . . g.listeners = append(g.listeners, ln) | |
| 47 . . } | |
| 48 . . case NETWORK_UDP, NETWORK_UDP4, NETWORK_UDP6: | |
| 49 . . for i, addrStr := range g.Addrs { | |
| 50 . . addr, err := net.ResolveUDPAddr(g.Network, addrStr) | |
| 51 . . if err != nil { | |
| 52 . . for j := 0; j < i; j++ { | |
| 53 . . _ = udpListeners[j].Close() | |
| 54 . . } | |
| github.com/lesismal/nbio.(*Engine).Start | |
| /Users/julian/go/pkg/mod/github.com/lesismal/nbio@v1.6.7/engine_unix.go | |
| Total: 544.67kB 544.67kB (flat, cum) 0.17% | |
| 65 . . udpListeners = append(udpListeners, ln) | |
| 66 . . } | |
| 67 . . } | |
| 68 . . | |
| 69 . . // Create IO pollers. | |
| 70 . . for i := 0; i < g.NPoller; i++ { | |
| 71 . . p, err := newPoller(g, false, i) | |
| 72 . . if err != nil { | |
| 73 . . for j := 0; j < len(g.listeners); j++ { | |
| 74 . . g.listeners[j].stop() | |
| 75 . . } | |
| 76 . . | |
| 77 . . for j := 0; j < i; j++ { | |
| 78 . . g.pollers[j].stop() | |
| 79 . . } | |
| 80 . . return err | |
| 81 . . } | |
| 82 . . g.pollers[i] = p | |
| 83 . . } | |
| 84 . . | |
| 85 . . // Start IO pollers. | |
| 86 . . for i := 0; i < g.NPoller; i++ { | |
| 87 544.67kB 544.67kB g.pollers[i].ReadBuffer = make([]byte, g.ReadBufferSize) | |
| 88 . . g.Add(1) | |
| 89 . . go g.pollers[i].start() | |
| 90 . . } | |
| 91 . . | |
| 92 . . // Start TCP/Unix listener pollers. | |
| 93 . . for _, l := range g.listeners { | |
| 94 . . g.Add(1) | |
| 95 . . go l.start() | |
| 96 . . } | |
| 97 . . | |
| 98 . . // Start UDP listener pollers. | |
| 99 . . for _, ln := range udpListeners { | |
| 100 . . _, err := g.AddConn(ln) | |
| 101 . . if err != nil { | |
| 102 . . for j := 0; j < len(g.listeners); j++ { | |
| 103 . . g.listeners[j].stop() | |
| 104 . . } | |
| 105 . . | |
| 106 . . for j := 0; j < len(g.pollers); j++ { | |
| 107 . . g.pollers[j].stop() | |
| 108 . . } | |
| 109 . . | |
| 110 . . for j := 0; j < len(udpListeners); j++ { | |
| 111 . . _ = udpListeners[j].Close() | |
| 112 . . } | |
| 113 . . | |
| 114 . . return err | |
| 115 . . } | |
| 116 . . } | |
| 117 . . | |
| 118 . . g.Timer.Start() | |
| 119 . . g.isOneshot = (g.EpollMod == EPOLLET && g.EPOLLONESHOT == EPOLLONESHOT) | |
| 120 . . | |
| 121 . . if g.AsyncReadInPoller { | |
| 122 . . if g.IOExecute == nil { | |
| 123 . . g.ioTaskPool = taskpool.NewIO(0, 0, 0) | |
| 124 . . g.IOExecute = g.ioTaskPool.Go | |
| 125 . . } | |
| 126 . . } | |
| 127 . . | |
| 128 . . if len(g.Addrs) == 0 { | |
| encoding/json.(*Decoder).Decode | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/encoding/json/stream.go | |
| Total: 0 18.13MB (flat, cum) 5.79% | |
| 44 . . // Decode reads the next JSON-encoded value from its | |
| 45 . . // input and stores it in the value pointed to by v. | |
| 46 . . // | |
| 47 . . // See the documentation for [Unmarshal] for details about | |
| 48 . . // the conversion of JSON into a Go value. | |
| 49 . . func (dec *Decoder) Decode(v any) error { | |
| 50 . . if dec.err != nil { | |
| 51 . . return dec.err | |
| 52 . . } | |
| 53 . . | |
| 54 . . if err := dec.tokenPrepareForDecode(); err != nil { | |
| 55 . . return err | |
| 56 . . } | |
| 57 . . | |
| 58 . . if !dec.tokenValueAllowed() { | |
| 59 . . return &SyntaxError{msg: "not at beginning of value", Offset: dec.InputOffset()} | |
| 60 . . } | |
| 61 . . | |
| 62 . . // Read whole value into buffer. | |
| 63 . 11.61MB n, err := dec.readValue() | |
| 64 . . if err != nil { | |
| 65 . . return err | |
| 66 . . } | |
| 67 . . dec.d.init(dec.buf[dec.scanp : dec.scanp+n]) | |
| 68 . . dec.scanp += n | |
| 69 . . | |
| 70 . . // Don't save err from unmarshal into dec.err: | |
| 71 . . // the connection is still usable since we read a complete JSON | |
| 72 . . // object from it before the error happened. | |
| 73 . 6.52MB err = dec.d.unmarshal(v) | |
| 74 . . | |
| 75 . . // fixup token streaming state | |
| 76 . . dec.tokenValueEnd() | |
| 77 . . | |
| 78 . . return err | |
| 79 . . } | |
| 80 . . | |
| 81 . . // Buffered returns a reader of the data remaining in the Decoder's | |
| 82 . . // buffer. The reader is valid until the next call to [Decoder.Decode]. | |
| 83 . . func (dec *Decoder) Buffered() io.Reader { | |
| encoding/json.(*Decoder).readValue | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/encoding/json/stream.go | |
| Total: 0 11.61MB (flat, cum) 3.70% | |
| 84 . . return bytes.NewReader(dec.buf[dec.scanp:]) | |
| 85 . . } | |
| 86 . . | |
| 87 . . // readValue reads a JSON value into dec.buf. | |
| 88 . . // It returns the length of the encoding. | |
| 89 . . func (dec *Decoder) readValue() (int, error) { | |
| 90 . . dec.scan.reset() | |
| 91 . . | |
| 92 . . scanp := dec.scanp | |
| 93 . . var err error | |
| 94 . . Input: | |
| 95 . . // help the compiler see that scanp is never negative, so it can remove | |
| 96 . . // some bounds checks below. | |
| 97 . . for scanp >= 0 { | |
| 98 . . | |
| 99 . . // Look in the buffer for a new value. | |
| 100 . . for ; scanp < len(dec.buf); scanp++ { | |
| 101 . . c := dec.buf[scanp] | |
| 102 . . dec.scan.bytes++ | |
| 103 . . switch dec.scan.step(&dec.scan, c) { | |
| 104 . . case scanEnd: | |
| 105 . . // scanEnd is delayed one byte so we decrement | |
| 106 . . // the scanner bytes count by 1 to ensure that | |
| 107 . . // this value is correct in the next call of Decode. | |
| 108 . . dec.scan.bytes-- | |
| 109 . . break Input | |
| 110 . . case scanEndObject, scanEndArray: | |
| 111 . . // scanEnd is delayed one byte. | |
| 112 . . // We might block trying to get that byte from src, | |
| 113 . . // so instead invent a space byte. | |
| 114 . . if stateEndValue(&dec.scan, ' ') == scanEnd { | |
| 115 . . scanp++ | |
| 116 . . break Input | |
| 117 . . } | |
| 118 . . case scanError: | |
| 119 . . dec.err = dec.scan.err | |
| 120 . . return 0, dec.scan.err | |
| 121 . . } | |
| 122 . . } | |
| 123 . . | |
| 124 . . // Did the last read have an error? | |
| 125 . . // Delayed until now to allow buffer scan. | |
| 126 . . if err != nil { | |
| 127 . . if err == io.EOF { | |
| 128 . . if dec.scan.step(&dec.scan, ' ') == scanEnd { | |
| 129 . . break Input | |
| 130 . . } | |
| 131 . . if nonSpace(dec.buf) { | |
| 132 . . err = io.ErrUnexpectedEOF | |
| 133 . . } | |
| 134 . . } | |
| 135 . . dec.err = err | |
| 136 . . return 0, err | |
| 137 . . } | |
| 138 . . | |
| 139 . . n := scanp - dec.scanp | |
| 140 . 11.61MB err = dec.refill() | |
| 141 . . scanp = dec.scanp + n | |
| 142 . . } | |
| 143 . . return scanp - dec.scanp, nil | |
| 144 . . } | |
| encoding/json.(*Decoder).refill | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/encoding/json/stream.go | |
| Total: 11.61MB 11.61MB (flat, cum) 3.70% | |
| 145 . . | |
| 146 . . func (dec *Decoder) refill() error { | |
| 147 . . // Make room to read more into the buffer. | |
| 148 . . // First slide down data already consumed. | |
| 149 . . if dec.scanp > 0 { | |
| 150 . . dec.scanned += int64(dec.scanp) | |
| 151 . . n := copy(dec.buf, dec.buf[dec.scanp:]) | |
| 152 . . dec.buf = dec.buf[:n] | |
| 153 . . dec.scanp = 0 | |
| 154 . . } | |
| 155 . . | |
| 156 . . // Grow buffer if not large enough. | |
| 157 . . const minRead = 512 | |
| 158 . . if cap(dec.buf)-len(dec.buf) < minRead { | |
| 159 11.61MB 11.61MB newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead) | |
| 160 . . copy(newBuf, dec.buf) | |
| 161 . . dec.buf = newBuf | |
| 162 . . } | |
| 163 . . | |
| 164 . . // Read. Delay error for next iteration (after scan). | |
| 165 . . n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)]) | |
| 166 . . dec.buf = dec.buf[0 : len(dec.buf)+n] | |
| 167 . . | |
| 168 . . return err | |
| 169 . . } | |
| encoding/json.(*Encoder).Encode | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/encoding/json/stream.go | |
| Total: 0 512.04kB (flat, cum) 0.16% | |
| 197 . . // with insignificant space characters elided, | |
| 198 . . // followed by a newline character. | |
| 199 . . // | |
| 200 . . // See the documentation for [Marshal] for details about the | |
| 201 . . // conversion of Go values to JSON. | |
| 202 . . func (enc *Encoder) Encode(v any) error { | |
| 203 . . if enc.err != nil { | |
| 204 . . return enc.err | |
| 205 . . } | |
| 206 . . | |
| 207 . . e := newEncodeState() | |
| 208 . . defer encodeStatePool.Put(e) | |
| 209 . . | |
| 210 . . err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML}) | |
| 211 . . if err != nil { | |
| 212 . . return err | |
| 213 . . } | |
| 214 . . | |
| 215 . . // Terminate each value with a newline. | |
| 216 . . // This makes the output look a little nicer | |
| 217 . . // when debugging, and some kind of space | |
| 218 . . // is required if the encoded value was a number, | |
| 219 . . // so that the reader knows there aren't more | |
| 220 . . // digits coming. | |
| 221 . . e.WriteByte('\n') | |
| 222 . . | |
| 223 . . b := e.Bytes() | |
| 224 . . if enc.indentPrefix != "" || enc.indentValue != "" { | |
| 225 . . enc.indentBuf, err = appendIndent(enc.indentBuf[:0], b, enc.indentPrefix, enc.indentValue) | |
| 226 . . if err != nil { | |
| 227 . . return err | |
| 228 . . } | |
| 229 . . b = enc.indentBuf | |
| 230 . . } | |
| 231 . 512.04kB if _, err = enc.w.Write(b); err != nil { | |
| 232 . . enc.err = err | |
| 233 . . } | |
| 234 . . return err | |
| 235 . . } | |
| 236 . . | |
| 237 . . // SetIndent instructs the encoder to format each subsequent encoded | |
| 238 . . // value as if indented by the package-level function Indent(dst, src, prefix, indent). | |
| 239 . . // Calling SetIndent("", "") disables indentation. | |
| encoding/json.(*RawMessage).UnmarshalJSON | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/encoding/json/stream.go | |
| Total: 1MB 1MB (flat, cum) 0.32% | |
| 265 . . } | |
| 266 . . return m, nil | |
| 267 . . } | |
| 268 . . | |
| 269 . . // UnmarshalJSON sets *m to a copy of data. | |
| 270 . . func (m *RawMessage) UnmarshalJSON(data []byte) error { | |
| 271 . . if m == nil { | |
| 272 . . return errors.New("json.RawMessage: UnmarshalJSON on nil pointer") | |
| 273 . . } | |
| 274 1MB 1MB *m = append((*m)[0:0], data...) | |
| 275 . . return nil | |
| 276 . . } | |
| 277 . . | |
| 278 . . var _ Marshaler = (*RawMessage)(nil) | |
| 279 . . var _ Unmarshaler = (*RawMessage)(nil) | |
| 280 . . | |
| runtime/pprof.WithLabels | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/runtime/pprof/label.go | |
| Total: 2.50MB 8.50MB (flat, cum) 2.71% | |
| 55 . . return "{" + strings.Join(keyVals, ", ") + "}" | |
| 56 . . } | |
| 57 . . | |
| 58 . . // WithLabels returns a new [context.Context] with the given labels added. | |
| 59 . . // A label overwrites a prior label with the same key. | |
| 60 . . func WithLabels(ctx context.Context, labels LabelSet) context.Context { | |
| 61 . . parentLabels := labelValue(ctx) | |
| 62 2.50MB 8.50MB return context.WithValue(ctx, labelContextKey{}, &labelMap{mergeLabelSets(parentLabels.LabelSet, labels)}) | |
| 63 . . } | |
| runtime/pprof.mergeLabelSets | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/runtime/pprof/label.go | |
| Total: 2MB 2MB (flat, cum) 0.64% | |
| 64 . . | |
| 65 . . func mergeLabelSets(left, right LabelSet) LabelSet { | |
| 66 . . if len(left.list) == 0 { | |
| 67 . . return right | |
| 68 . . } else if len(right.list) == 0 { | |
| 69 . . return left | |
| 70 . . } | |
| 71 . . | |
| 72 . . l, r := 0, 0 | |
| 73 2MB 2MB result := make([]label, 0, len(right.list)) | |
| 74 . . for l < len(left.list) && r < len(right.list) { | |
| 75 . . switch strings.Compare(left.list[l].key, right.list[r].key) { | |
| 76 . . case -1: // left key < right key | |
| 77 . . result = append(result, left.list[l]) | |
| 78 . . l++ | |
| 79 . . case 1: // right key < left key | |
| 80 . . result = append(result, right.list[r]) | |
| 81 . . r++ | |
| 82 . . case 0: // keys are equal, right value overwrites left value | |
| 83 . . result = append(result, right.list[r]) | |
| 84 . . l++ | |
| 85 . . r++ | |
| 86 . . } | |
| 87 . . } | |
| 88 . . | |
| 89 . . // Append the remaining elements | |
| 90 . . result = append(result, left.list[l:]...) | |
| 91 . . result = append(result, right.list[r:]...) | |
| 92 . . | |
| 93 . . return LabelSet{list: result} | |
| 94 . . } | |
| 95 . . | |
| 96 . . // Labels takes an even number of strings representing key-value pairs | |
| 97 . . // and makes a [LabelSet] containing them. | |
| runtime/pprof.Labels | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/runtime/pprof/label.go | |
| Total: 8MB 8MB (flat, cum) 2.55% | |
| 98 . . // A label overwrites a prior label with the same key. | |
| 99 . . // Currently only the CPU and goroutine profiles utilize any labels | |
| 100 . . // information. | |
| 101 . . // See https://golang.org/issue/23458 for details. | |
| 102 . . func Labels(args ...string) LabelSet { | |
| 103 . . if len(args)%2 != 0 { | |
| 104 . . panic("uneven number of arguments to pprof.Labels") | |
| 105 . . } | |
| 106 8MB 8MB list := make([]label, 0, len(args)/2) | |
| 107 . . sortedNoDupes := true | |
| 108 . . for i := 0; i+1 < len(args); i += 2 { | |
| 109 . . list = append(list, label{key: args[i], value: args[i+1]}) | |
| 110 . . sortedNoDupes = sortedNoDupes && (i < 2 || args[i] > args[i-2]) | |
| 111 . . } | |
| 112 . . if !sortedNoDupes { | |
| 113 . . // slow path: keys are unsorted, contain duplicates, or both | |
| 114 . . slices.SortStableFunc(list, func(a, b label) int { | |
| 115 . . return strings.Compare(a.key, b.key) | |
| 116 . . }) | |
| 117 . . deduped := make([]label, 0, len(list)) | |
| 118 . . for i, lbl := range list { | |
| 119 . . if i == 0 || lbl.key != list[i-1].key { | |
| 120 . . deduped = append(deduped, lbl) | |
| 121 . . } else { | |
| 122 . . deduped[len(deduped)-1] = lbl | |
| 123 . . } | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).setSamplingPriorityLockedWithForce | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/propagating_tags.go | |
| Total: 10MB 10MB (flat, cum) 3.19% | |
| 52 . . } | |
| 53 . . | |
| 54 . . // setPropagatingTagLocked sets the key/value pair as a trace propagating tag. | |
| 55 . . // Not safe for concurrent use, setPropagatingTag should be used instead in that case. | |
| 56 . . func (t *trace) setPropagatingTagLocked(key, value string) { | |
| 57 . . if t.propagatingTags == nil { | |
| 58 512.02kB 512.02kB t.propagatingTags = make(map[string]string, 1) | |
| 59 . . } | |
| 60 9.50MB 9.50MB t.propagatingTags[key] = value | |
| 61 . . } | |
| 62 . . | |
| 63 . . // unsetPropagatingTag deletes the key/value pair from the trace's propagated tags. | |
| 64 . . func (t *trace) unsetPropagatingTag(key string) { | |
| 65 . . t.mu.Lock() | |
| github.com/braze-inc/dust/redis.BulkResolveMiteStringsToInTransitMites | |
| /Users/julian/code/dust/redis/mite_bulk_resolver.go | |
| Total: 7.51MB 14.51MB (flat, cum) 4.63% | |
| 31 . . mites []*mite.Mite, | |
| 32 . . ) (userMitesMap mite.EntityMitesMap, err error) { | |
| 33 . 1.50MB span, ctx := tracer.StartSpanFromContext(ctx, "redis.bulk_resolve_mites") | |
| context.WithValue | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/context/context.go | |
| Total: 6.50MB 6.50MB (flat, cum) 2.07% | |
| 713 . . // packages using context. Users of WithValue should define their own | |
| 714 . . // types for keys. To avoid allocating when assigning to an | |
| 715 . . // interface{}, context keys often have concrete type | |
| 716 . . // struct{}. Alternatively, exported context key variables' static | |
| 717 . . // type should be a pointer or interface. | |
| 718 . . func WithValue(parent Context, key, val any) Context { | |
| 719 . . if parent == nil { | |
| 720 . . panic("cannot create context from nil parent") | |
| 721 . . } | |
| 722 . . if key == nil { | |
| 723 . . panic("nil key") | |
| 724 . . } | |
| 725 . . if !reflectlite.TypeOf(key).Comparable() { | |
| 726 . . panic("key is not comparable") | |
| 727 . . } | |
| 728 6.50MB 6.50MB return &valueCtx{parent, key, val} | |
| 729 . . } | |
| 730 . . | |
| 731 . . // A valueCtx carries a key-value pair. It implements Value for that key and | |
| 732 . . // delegates all other calls to the embedded Context. | |
| 733 . . type valueCtx struct { | |
| reflect.growslice | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/runtime/slice.go | |
| Total: 5.02MB 5.02MB (flat, cum) 1.60% | |
| 327 . . // | |
| 328 . . // Do not remove or change the type signature. | |
| 329 . . // See go.dev/issue/67401. | |
| 330 . . // | |
| 331 . . //go:linkname reflect_growslice reflect.growslice | |
| 332 . . func reflect_growslice(et *_type, old slice, num int) slice { | |
| 333 . . // Semantically equivalent to slices.Grow, except that the caller | |
| 334 . . // is responsible for ensuring that old.len+num > old.cap. | |
| 335 . . num -= old.cap - old.len // preserve memory of old[old.len:old.cap] | |
| 336 5.02MB 5.02MB new := growslice(old.array, old.cap+num, old.cap, num, et) | |
| 337 . . // growslice does not zero out new[old.cap:new.len] since it assumes that | |
| 338 . . // the memory will be overwritten by an append() that called growslice. | |
| 339 . . // Since the caller of reflect_growslice is not append(), | |
| 340 . . // zero out this region before returning the slice to the reflect package. | |
| 341 . . if !et.Pointers() { | |
| 342 . . oldcapmem := uintptr(old.cap) * et.Size_ | |
| 343 . . newlenmem := uintptr(new.len) * et.Size_ | |
| 344 . . memclrNoHeapPointers(add(new.array, oldcapmem), newlenmem-oldcapmem) | |
| 345 . . } | |
| 346 . . new.len = old.len // preserve the old length | |
| 347 . . return new | |
| 348 . . } | |
| 349 . . | |
| 350 . . func isPowerOfTwo(x uintptr) bool { | |
| 351 . . return x&(x-1) == 0 | |
| 352 . . } | |
| github.com/braze-inc/dust/events.PublishMessageBulk | |
| /Users/julian/code/dust/events/events.go | |
| Total: 2.50MB 57.01MB (flat, cum) 18.19% | |
| 103 . . transitMites []*mite.InTransitMite, | |
| 104 . . message *json.RawMessage, | |
| 105 . . ) (err error) { | |
| 106 . 54.51MB span, ctx := tracer.StartSpanFromContext(ctx, "events.publish_message_bulk") | |
| 107 . . defer func() { span.Finish(tracer.WithError(err)) }() | |
| 108 . . | |
| strconv.formatBits | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/strconv/itoa.go | |
| Total: 4.50MB 4.50MB (flat, cum) 1.44% | |
| 131 . . // u < 1e9 | |
| 132 . . } | |
| 133 . . | |
| 134 . . // u guaranteed to fit into a uint | |
| 135 . . us := uint(u) | |
| 136 . . for us >= 100 { | |
| 137 . . is := us % 100 * 2 | |
| 138 . . us /= 100 | |
| 139 . . i -= 2 | |
| 140 . . a[i+1] = smallsString[is+1] | |
| 141 . . a[i+0] = smallsString[is+0] | |
| 142 . . } | |
| 143 . . | |
| 144 . . // us < 100 | |
| 145 . . is := us * 2 | |
| 146 . . i-- | |
| 147 . . a[i] = smallsString[is+1] | |
| 148 . . if us >= 10 { | |
| 149 . . i-- | |
| 150 . . a[i] = smallsString[is] | |
| 151 . . } | |
| 152 . . | |
| 153 . . } else if isPowerOfTwo(base) { | |
| 154 . . // Use shifts and masks instead of / and %. | |
| 155 . . shift := uint(bits.TrailingZeros(uint(base))) | |
| 156 . . b := uint64(base) | |
| 157 . . m := uint(base) - 1 // == 1<<shift - 1 | |
| 158 . . for u >= b { | |
| 159 . . i-- | |
| 160 . . a[i] = digits[uint(u)&m] | |
| 161 . . u >>= shift | |
| 162 . . } | |
| 163 . . // u < base | |
| 164 . . i-- | |
| 165 . . a[i] = digits[uint(u)] | |
| 166 . . } else { | |
| 167 . . // general case | |
| 168 . . b := uint64(base) | |
| 169 . . for u >= b { | |
| 170 . . i-- | |
| 171 . . // Avoid using r = a%b in addition to q = a/b | |
| 172 . . // since 64bit division and modulo operations | |
| 173 . . // are calculated by runtime functions on 32bit machines. | |
| 174 . . q := u / b | |
| 175 . . a[i] = digits[uint(u-q*b)] | |
| 176 . . u = q | |
| 177 . . } | |
| 178 . . // u < base | |
| 179 . . i-- | |
| 180 . . a[i] = digits[uint(u)] | |
| 181 . . } | |
| 182 . . | |
| 183 . . // add sign, if any | |
| 184 . . if neg { | |
| 185 . . i-- | |
| 186 . . a[i] = '-' | |
| 187 . . } | |
| 188 . . | |
| 189 . . if append_ { | |
| 190 . . d = append(dst, a[i:]...) | |
| 191 . . return | |
| 192 . . } | |
| 193 4.50MB 4.50MB s = string(a[i:]) | |
| 194 . . return | |
| 195 . . } | |
| 196 . . | |
| 197 . . func isPowerOfTwo(x int) bool { | |
| 198 . . return x&(x-1) == 0 | |
| 199 . . } | |
| github.com/DataDog/datadog-go/v5/statsd.newWithWriter | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/datadog-go/v5@v5.8.1/statsd/buffer.go | |
| Total: 3.01MB 3.01MB (flat, cum) 0.96% | |
| 30 . . maxElements int | |
| 31 . . elementCount int | |
| 32 . . } | |
| 33 . . | |
| 34 . . func newStatsdBuffer(maxSize, maxElements int) *statsdBuffer { | |
| 35 . . return &statsdBuffer{ | |
| 36 3.01MB 3.01MB buffer: make([]byte, 0, maxSize+metricOverhead), // pre-allocate the needed size + metricOverhead to avoid having Go re-allocate on it's own if an element does not fit | |
| 37 . . maxSize: maxSize, | |
| 38 . . maxElements: maxElements, | |
| 39 . . } | |
| 40 . . } | |
| 41 . . | |
| 42 . . func (b *statsdBuffer) writeGauge(namespace string, globalTags []string, name string, value float64, tags []string, rate float64, timestamp int64, originDetection bool, overrideCard Cardinality) error { | |
| 43 . . if b.elementCount >= b.maxElements { | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.ContextWithSpan | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/context.go | |
| Total: 0 5MB (flat, cum) 1.60% | |
| 13 . . illmobs "github.com/DataDog/dd-trace-go/v2/internal/llmobs" | |
| 14 . . "github.com/DataDog/dd-trace-go/v2/internal/orchestrion" | |
| 15 . . ) | |
| 16 . . | |
| 17 . . // ContextWithSpan returns a copy of the given context which includes the span s. | |
| 18 . . func ContextWithSpan(ctx context.Context, s *Span) context.Context { | |
| 19 . 2.50MB newCtx := orchestrion.CtxWithValue(ctx, internal.ActiveSpanKey, s) | |
| 20 . 2.50MB return contextWithPropagatedLLMSpan(newCtx, s) | |
| 21 . . } | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.contextWithPropagatedLLMSpan | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/context.go | |
| Total: 0 2.50MB (flat, cum) 0.8% | |
| 22 . . | |
| 23 . . func contextWithPropagatedLLMSpan(ctx context.Context, s *Span) context.Context { | |
| 24 . . if s == nil { | |
| 25 . . return ctx | |
| 26 . . } | |
| 27 . . // if there is a propagated llm span already just skip | |
| 28 . . if _, ok := illmobs.PropagatedLLMSpanFromContext(ctx); ok { | |
| 29 . . return ctx | |
| 30 . . } | |
| 31 . . newCtx := ctx | |
| 32 . . | |
| 33 . 2.50MB propagatedLLMObs := propagatedLLMSpanFromTags(s) | |
| 34 . . if propagatedLLMObs.SpanID == "" || propagatedLLMObs.TraceID == "" { | |
| 35 . . return newCtx | |
| 36 . . } | |
| 37 . . return illmobs.ContextWithPropagatedLLMSpan(newCtx, propagatedLLMObs) | |
| 38 . . } | |
| 39 . . | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.propagatedLLMSpanFromTags | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/context.go | |
| Total: 2.50MB 2.50MB (flat, cum) 0.8% | |
| 40 . . // propagatedLLMSpanFromTags extracts LLMObs propagation information from the trace propagating tags. | |
| 41 . . // This is used during distributed tracing to set the correct parent span for the current span. | |
| 42 . . func propagatedLLMSpanFromTags(s *Span) *illmobs.PropagatedLLMSpan { | |
| 43 2.50MB 2.50MB propagatedLLMObs := &illmobs.PropagatedLLMSpan{} | |
| 44 . . if s.context == nil || s.context.trace == nil { | |
| 45 . . return propagatedLLMObs | |
| 46 . . } | |
| 47 . . if parentID := s.context.trace.propagatingTag(keyPropagatedLLMObsParentID); parentID != "" { | |
| 48 . . propagatedLLMObs.SpanID = parentID | |
| 49 . . } | |
| 50 . . if mlApp := s.context.trace.propagatingTag(keyPropagatedLLMObsMLAPP); mlApp != "" { | |
| 51 . . propagatedLLMObs.MLApp = mlApp | |
| 52 . . } | |
| 53 . . if trID := s.context.trace.propagatingTag(keyPropagatedLLMObsTraceID); trID != "" { | |
| 54 . . propagatedLLMObs.TraceID = trID | |
| 55 . . } | |
| 56 . . return propagatedLLMObs | |
| 57 . . } | |
| 58 . . | |
| 59 . . // SpanFromContext returns the span contained in the given context. A second return | |
| 60 . . // value indicates if a span was found in the context. If no span is found, a no-op | |
| 61 . . // span is returned. | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.StartSpanFromContext | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/context.go | |
| Total: 0 120.52MB (flat, cum) 38.46% | |
| 74 . . } | |
| 75 . . | |
| 76 . . // StartSpanFromContext returns a new span with the given operation name and options. If a span | |
| 77 . . // is found in the context, it will be used as the parent of the resulting span. If the ChildOf | |
| 78 . . // option is passed, it will only be used as the parent if there is no span found in `ctx`. | |
| 79 . . func StartSpanFromContext(ctx context.Context, operationName string, opts ...StartSpanOption) (*Span, context.Context) { | |
| 80 . . // copy opts in case the caller reuses the slice in parallel | |
| 81 . . // we will add at least 1, at most 2 items | |
| 82 . . optsLocal := options.Expand(opts, 0, 2) | |
| 83 . . if ctx == nil { | |
| 84 . . // default to context.Background() to avoid panics on Go >= 1.15 | |
| 85 . . ctx = context.Background() | |
| 86 . . } else if s, ok := SpanFromContext(ctx); ok { | |
| 87 . . optsLocal = append(optsLocal, ChildOf(s.Context())) | |
| 88 . . } | |
| 89 . . optsLocal = append(optsLocal, withContext(ctx)) | |
| 90 . 115.52MB s := StartSpan(operationName, optsLocal...) | |
| 91 . . if s != nil && s.pprofCtxActive != nil { | |
| 92 . . ctx = s.pprofCtxActive | |
| 93 . . } | |
| 94 . 5MB return s, ContextWithSpan(ctx, s) | |
| 95 . . } | |
| github.com/DataDog/dd-trace-go/v2/internal.GetTracerGitMetadataTags | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/internal/gitmetadata.go | |
| Total: 2.50MB 2.50MB (flat, cum) 0.8% | |
| 131 . . | |
| 132 . . // GetTracerGitMetadataTags returns git metadata tags for tracer | |
| 133 . . // NB: Currently tracer inject tags with some workaround | |
| 134 . . // (only with _dd prefix and only for the first span in payload) | |
| 135 . . // So we provide different tag names | |
| 136 . . func GetTracerGitMetadataTags() map[string]string { | |
| 137 2.50MB 2.50MB res := make(map[string]string) | |
| 138 . . tags := GetGitMetadataTags() | |
| 139 . . | |
| 140 . . updateTags(res, TraceTagRepositoryURL, tags[TagRepositoryURL]) | |
| 141 . . updateTags(res, TraceTagCommitSha, tags[TagCommitSha]) | |
| 142 . . updateTags(res, TraceTagGoPath, tags[TagGoPath]) | |
| 143 . . | |
| 144 . . return res | |
| 145 . . } | |
| 146 . . | |
| 147 . . // removeCredentials returns the passed url with potential credentials removed. | |
| 148 . . // If the input string is not a valid URL, the string is returned as is. | |
| 149 . . func removeCredentials(urlStr string) string { | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.StartSpanFromContext | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/option.go | |
| Total: 2.50MB 2.50MB (flat, cum) 0.8% | |
| 1448 . . | |
| 1449 . . // ChildOf tells StartSpan to use the given span context as a parent for the created span. | |
| 1450 . . // | |
| 1451 . . // Deprecated: Use [Span.StartChild] instead. | |
| 1452 . . func ChildOf(ctx *SpanContext) StartSpanOption { | |
| 1453 512.01kB 512.01kB return func(cfg *StartSpanConfig) { | |
| 1454 . . cfg.Parent = ctx | |
| 1455 . . } | |
| 1456 . . } | |
| 1457 . . | |
| 1458 . . // withContext associates the ctx with the span. | |
| 1459 . . func withContext(ctx context.Context) StartSpanOption { | |
| 1460 2MB 2MB return func(cfg *StartSpanConfig) { | |
| 1461 . . cfg.Context = ctx | |
| 1462 . . } | |
| 1463 . . } | |
| 1464 . . | |
| 1465 . . // StartTime sets a custom time as the start time for the created span. By | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*prioritySampler).apply | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/ddtrace/tracer/sampler.go | |
| Total: 2MB 13MB (flat, cum) 4.15% | |
| 169 . . return ps.defaultRate | |
| 170 . . } | |
| 171 . . | |
| 172 . . // apply applies sampling priority to the given span. Caller must ensure it is safe | |
| 173 . . // to modify the span. | |
| 174 . . func (ps *prioritySampler) apply(spn *Span) { | |
| 175 . . rate := ps.getRate(spn) | |
| 176 . . if sampledByRate(spn.traceID, rate) { | |
| 177 . 11MB spn.setSamplingPriority(ext.PriorityAutoKeep, samplernames.AgentRate) | |
| 178 . . } else { | |
| 179 . . spn.setSamplingPriority(ext.PriorityAutoReject, samplernames.AgentRate) | |
| 180 . . } | |
| 181 512.01kB 512.01kB spn.SetTag(keySamplingPriorityRate, rate) | |
| 182 . . // Set the Knuth sampling rate tag when sampled by agent rate | |
| 183 1.50MB 1.50MB spn.SetTag(keyKnuthSamplingRate, formatKnuthSamplingRate(rate)) | |
| 184 . . } | |
| github.com/redis/go-redis/v9/internal/proto.(*Reader).ReadReply | |
| /Users/julian/go/pkg/mod/github.com/redis/go-redis/v9@v9.16.0/internal/proto/reader.go | |
| Total: 2MB 7MB (flat, cum) 2.23% | |
| 244 . . return nil, fmt.Errorf("redis: invalid reply: %q", b) | |
| 245 . . } | |
| 246 . . return b[:len(b)-2], nil | |
| 247 . . } | |
| 248 . . | |
| 249 . . func (r *Reader) ReadReply() (interface{}, error) { | |
| 250 . . line, err := r.ReadLine() | |
| 251 . . if err != nil { | |
| 252 . . return nil, err | |
| 253 . . } | |
| 254 . . | |
| 255 . . switch line[0] { | |
| 256 . . case RespStatus: | |
| 257 . . return string(line[1:]), nil | |
| 258 . . case RespInt: | |
| 259 . . return util.ParseInt(line[1:], 10, 64) | |
| 260 . . case RespFloat: | |
| 261 . . return r.readFloat(line) | |
| 262 . . case RespBool: | |
| 263 . . return r.readBool(line) | |
| 264 . . case RespBigInt: | |
| 265 . . return r.readBigInt(line) | |
| 266 . . | |
| 267 . . case RespString: | |
| 268 2MB 3.50MB return r.readStringReply(line) | |
| 269 . . case RespVerbatim: | |
| 270 . . return r.readVerb(line) | |
| 271 . . | |
| 272 . . case RespArray, RespSet, RespPush: | |
| 273 . 3.50MB return r.readSlice(line) | |
| 274 . . case RespMap: | |
| 275 . . return r.readMap(line) | |
| 276 . . } | |
| 277 . . return nil, fmt.Errorf("redis: can't parse %.100q", line) | |
| 278 . . } | |
| 279 . . | |
| 280 . . func (r *Reader) readFloat(line []byte) (float64, error) { | |
| 281 . . v := string(line[1:]) | |
| 282 . . switch string(line[1:]) { | |
| runtime.allocm | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/runtime/proc.go | |
| Total: 1.50MB 1.50MB (flat, cum) 0.48% | |
| 2220 . . // | |
| 2221 . . // This function is allowed to have write barriers even if the caller | |
| 2222 . . // isn't because it borrows pp. | |
| 2223 . . // | |
| 2224 . . //go:yeswritebarrierrec | |
| 2225 . . func allocm(pp *p, fn func(), id int64) *m { | |
| 2226 . . allocmLock.rlock() | |
| 2227 . . | |
| 2228 . . // The caller owns pp, but we may borrow (i.e., acquirep) it. We must | |
| 2229 . . // disable preemption to ensure it is not stolen, which would make the | |
| 2230 . . // caller lose ownership. | |
| 2231 . . acquirem() | |
| 2232 . . | |
| 2233 . . gp := getg() | |
| 2234 . . if gp.m.p == 0 { | |
| 2235 . . acquirep(pp) // temporarily borrow p for mallocs in this function | |
| 2236 . . } | |
| 2237 . . | |
| 2238 . . // Release the free M list. We need to do this somewhere and | |
| 2239 . . // this may free up a stack we can use. | |
| 2240 . . if sched.freem != nil { | |
| 2241 . . lock(&sched.lock) | |
| 2242 . . var newList *m | |
| 2243 . . for freem := sched.freem; freem != nil; { | |
| 2244 . . // Wait for freeWait to indicate that freem's stack is unused. | |
| 2245 . . wait := freem.freeWait.Load() | |
| 2246 . . if wait == freeMWait { | |
| 2247 . . next := freem.freelink | |
| 2248 . . freem.freelink = newList | |
| 2249 . . newList = freem | |
| 2250 . . freem = next | |
| 2251 . . continue | |
| 2252 . . } | |
| 2253 . . // Drop any remaining trace resources. | |
| 2254 . . // Ms can continue to emit events all the way until wait != freeMWait, | |
| 2255 . . // so it's only safe to call traceThreadDestroy at this point. | |
| 2256 . . if traceEnabled() || traceShuttingDown() { | |
| 2257 . . traceThreadDestroy(freem) | |
| 2258 . . } | |
| 2259 . . // Free the stack if needed. For freeMRef, there is | |
| 2260 . . // nothing to do except drop freem from the sched.freem | |
| 2261 . . // list. | |
| 2262 . . if wait == freeMStack { | |
| 2263 . . // stackfree must be on the system stack, but allocm is | |
| 2264 . . // reachable off the system stack transitively from | |
| 2265 . . // startm. | |
| 2266 . . systemstack(func() { | |
| 2267 . . stackfree(freem.g0.stack) | |
| 2268 . . }) | |
| 2269 . . } | |
| 2270 . . freem = freem.freelink | |
| 2271 . . } | |
| 2272 . . sched.freem = newList | |
| 2273 . . unlock(&sched.lock) | |
| 2274 . . } | |
| 2275 . . | |
| 2276 1.50MB 1.50MB mp := new(m) | |
| 2277 . . mp.mstartfn = fn | |
| 2278 . . mcommoninit(mp, id) | |
| 2279 . . | |
| 2280 . . // In case of cgo or Solaris or illumos or Darwin, pthread_create will make us a stack. | |
| 2281 . . // Windows and Plan 9 will layout sched stack on OS stack. | |
| 2282 . . if iscgo || mStackIsSystemAllocated() { | |
| 2283 . . mp.g0 = malg(-1) | |
| 2284 . . } else { | |
| 2285 . . mp.g0 = malg(16384 * sys.StackGuardMultiplier) | |
| 2286 . . } | |
| 2287 . . mp.g0.m = mp | |
| 2288 . . | |
| 2289 . . if pp == gp.m.p.ptr() { | |
| 2290 . . releasep() | |
| 2291 . . } | |
| 2292 . . | |
| 2293 . . releasem(gp.m) | |
| 2294 . . allocmLock.runlock() | |
| 2295 . . return mp | |
| 2296 . . } | |
| 2297 . . | |
| 2298 . . // needm is called when a cgo callback happens on a | |
| 2299 . . // thread without an m (a thread not created by Go). | |
| 2300 . . // In this case, needm is expected to find an m to use | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.StartSpanFromContext | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/instrumentation/options/options.go | |
| Total: 512.01kB 512.01kB (flat, cum) 0.16% | |
| 25 . . // appended to the new slice. | |
| 26 . . // The new slice will have a capacity of initialPosition + len(opts) + trailCapacity | |
| 27 . . // and a length of initialPosition + len(opts). | |
| 28 . . func Expand[T any](opts []T, initialPosition, trailCapacity int) []T { | |
| 29 . . capacity := initialPosition + len(opts) | |
| 30 512.01kB 512.01kB dup := make([]T, capacity, capacity+trailCapacity) | |
| 31 . . copy(dup[initialPosition:], opts) | |
| 32 . . return dup | |
| 33 . . } | |
| 34 . . | |
| 35 . . // This is a workaround needed because of v2 changes that prevents contribs from accessing | |
| 36 . . // the internal directory. This function should not be used if the internal directory | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.(*trace).setTraceTags | |
| /Users/julian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.darwin-arm64/src/encoding/hex/hex.go | |
| Total: 512.01kB 512.01kB (flat, cum) 0.16% | |
| 122 . . return dst[:len(dst)+n], err | |
| 123 . . } | |
| 124 . . | |
| 125 . . // EncodeToString returns the hexadecimal encoding of src. | |
| 126 . . func EncodeToString(src []byte) string { | |
| 127 . . dst := make([]byte, EncodedLen(len(src))) | |
| 128 . . Encode(dst, src) | |
| 129 512.01kB 512.01kB return string(dst) | |
| 130 . . } | |
| 131 . . | |
| 132 . . // DecodeString returns the bytes represented by the hexadecimal string s. | |
| 133 . . // | |
| 134 . . // DecodeString expects that src contains only hexadecimal | |
| github.com/DataDog/datadog-go/v5/statsd.newWithWriter | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/datadog-go/v5@v5.8.1/statsd/statsdex.go | |
| Total: 0 514.63kB (flat, cum) 0.16% | |
| 468 . . } | |
| 469 . . | |
| 470 . . // Inject values of DD_* environment variables as global tags. | |
| 471 . . for _, mapping := range ddEnvTagsMapping { | |
| 472 . . if value := os.Getenv(mapping.envName); value != "" { | |
| 473 . . c.tags = append(c.tags, fmt.Sprintf("%s:%s", mapping.tagName, value)) | |
| 474 . . } | |
| 475 . . } | |
| 476 . . // Whether origin detection is enabled or not for this client, we need to initialize the global | |
| 477 . . // external environment variable in case another client has enabled it and needs to access it. | |
| 478 . . initExternalEnv() | |
| 479 . . | |
| 480 . . // Initializes the global tag cardinality with either the value passed in by the user or the value from the DD_CARDINALITY/DATADOG_CARDINALITY environment variable. | |
| 481 . . initTagCardinality(o.tagCardinality) | |
| 482 . . | |
| 483 . . initContainerID(o.containerID, fillInContainerID(o), isHostCgroupNamespace()) | |
| 484 . . isUDS := writerName == writerNameUDS | |
| 485 . . | |
| 486 . . if o.maxBytesPerPayload == 0 { | |
| 487 . . if isUDS { | |
| 488 . . o.maxBytesPerPayload = DefaultMaxAgentPayloadSize | |
| 489 . . } else { | |
| 490 . . o.maxBytesPerPayload = OptimalUDPPayloadSize | |
| 491 . . } | |
| 492 . . } | |
| 493 . . if o.bufferPoolSize == 0 { | |
| 494 . . if isUDS { | |
| 495 . . o.bufferPoolSize = DefaultUDSBufferPoolSize | |
| 496 . . } else { | |
| 497 . . o.bufferPoolSize = DefaultUDPBufferPoolSize | |
| 498 . . } | |
| 499 . . } | |
| 500 . . if o.senderQueueSize == 0 { | |
| 501 . . if isUDS { | |
| 502 . . o.senderQueueSize = DefaultUDSBufferPoolSize | |
| 503 . . } else { | |
| 504 . . o.senderQueueSize = DefaultUDPBufferPoolSize | |
| 505 . . } | |
| 506 . . } | |
| 507 . . | |
| 508 . . bufferPool := newBufferPool(o.bufferPoolSize, o.maxBytesPerPayload, o.maxMessagesPerPayload) | |
| 509 . . c.sender = newSender(w, o.senderQueueSize, bufferPool, o.errorHandler) | |
| 510 . . c.aggregatorMode = o.receiveMode | |
| 511 . . | |
| 512 . . c.workersMode = o.receiveMode | |
| 513 . . // channelMode mode at the worker level is not enabled when | |
| 514 . . // ExtendedAggregation is since the user app will not directly | |
| 515 . . // use the worker (the aggregator sit between the app and the | |
| 516 . . // workers). | |
| 517 . . if o.extendedAggregation { | |
| 518 . . c.workersMode = mutexMode | |
| 519 . . } | |
| 520 . . | |
| 521 . . if o.aggregation || o.extendedAggregation || o.maxBufferedSamplesPerContext > 0 { | |
| 522 . . c.agg = newAggregator(&c, int64(o.maxBufferedSamplesPerContext)) | |
| 523 . . c.agg.start(o.aggregationFlushInterval) | |
| 524 . . | |
| 525 . . if o.extendedAggregation { | |
| 526 . . c.aggExtended = c.agg | |
| 527 . . | |
| 528 . . if c.aggregatorMode == channelMode { | |
| 529 . . c.agg.startReceivingMetric(o.channelModeBufferSize, o.workersCount) | |
| 530 . . } | |
| 531 . . } | |
| 532 . . } | |
| 533 . . | |
| 534 . . for i := 0; i < o.workersCount; i++ { | |
| 535 . 514.63kB w := newWorker(bufferPool, c.sender) | |
| 536 . . c.workers = append(c.workers, w) | |
| 537 . . | |
| 538 . . if c.workersMode == channelMode { | |
| 539 . . w.startReceivingMetric(o.channelModeBufferSize) | |
| 540 . . } | |
| 541 . . } | |
| 542 . . | |
| 543 . . c.flushTime = o.bufferFlushInterval | |
| 544 . . c.stop = make(chan struct{}, 1) | |
| 545 . . | |
| 546 . . c.wg.Add(1) | |
| 547 . . go func() { | |
| 548 . . defer c.wg.Done() | |
| 549 . . c.watch() | |
| 550 . . }() | |
| 551 . . | |
| 552 . . if o.telemetry { | |
| 553 . . if o.telemetryAddr == "" { | |
| 554 . . c.telemetryClient = newTelemetryClient(&c, c.agg != nil) | |
| 555 . . } else { | |
| 556 . . var err error | |
| 557 . . c.telemetryClient, err = newTelemetryClientWithCustomAddr(&c, o.telemetryAddr, c.agg != nil, bufferPool, o.writeTimeout, o.connectTimeout) | |
| 558 . . if err != nil { | |
| 559 . . return nil, err | |
| github.com/DataDog/dd-trace-go/v2/ddtrace/tracer.spanStart | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/internal/traceprof/profiler.go | |
| Total: 0 6.50MB (flat, cum) 2.07% | |
| 16 . . func SetProfilerEnabled(val bool) bool { | |
| 17 . . return atomic.SwapUint32(&profiler.enabled, boolToUint32(val)) != 0 | |
| 18 . . } | |
| 19 . . | |
| 20 . . func profilerEnabled() int { | |
| 21 . . return int(atomic.LoadUint32(&profiler.enabled)) | |
| 22 . . } | |
| 23 . . | |
| 24 . . func boolToUint32(b bool) uint32 { | |
| 25 . . if b { | |
| 26 . . return 1 | |
| 27 . . } | |
| 28 . . return 0 | |
| 29 . . } | |
| 30 . . | |
| 31 . . func SetProfilerRootTags(localRootSpan TagSetter) { | |
| 32 . 6.50MB localRootSpan.SetTag("_dd.profiling.enabled", profilerEnabled()) | |
| 33 . . } | |
| 34 . . | |
| 35 . . type TagSetter interface{ SetTag(string, interface{}) } | |
| github.com/DataDog/dd-trace-go/v2/internal.NewStatsdClient | |
| /Users/julian/go/pkg/mod/github.com/!data!dog/dd-trace-go/v2@v2.4.0/internal/statsd.go | |
| Total: 0 3.51MB (flat, cum) 1.12% | |
| 24 . . Flush() error | |
| 25 . . Close() error | |
| 26 . . } | |
| 27 . . | |
| 28 . . // NewStatsdClient returns a new statsd client with the provided address and globaltags | |
| 29 . . func NewStatsdClient(addr string, globalTags []string) (StatsdClient, error) { | |
| 30 . . if addr == "" { | |
| 31 . . addr = DefaultDogstatsdAddr | |
| 32 . . } | |
| 33 . 3.51MB client, err := statsd.NewDirect(addr, statsd.WithMaxMessagesPerPayload(40), statsd.WithTags(globalTags)) | |
| 34 . . if err != nil { | |
| 35 . . return &statsd.NoOpClientDirect{}, err | |
| 36 . . } | |
| 37 . . return client, nil | |
| 38 . . } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment