|
| 1 | +package tracing |
| 2 | + |
| 3 | +import ( |
| 4 | + "runtime" |
| 5 | + |
| 6 | + "go.opentelemetry.io/otel/attribute" |
| 7 | + "go.opentelemetry.io/otel/trace" |
| 8 | +) |
| 9 | + |
| 10 | +// safeUint64ToInt64 safely converts uint64 to int64 for OpenTelemetry attributes |
| 11 | +// Returns int64 max value if the uint64 exceeds int64 maximum to prevent overflow |
| 12 | +func safeUint64ToInt64(val uint64) int64 { |
| 13 | + const maxInt64 = 9223372036854775807 // 2^63 - 1 |
| 14 | + if val > maxInt64 { // Check if val exceeds int64 max |
| 15 | + return maxInt64 // Return int64 max value |
| 16 | + } |
| 17 | + return int64(val) |
| 18 | +} |
| 19 | + |
| 20 | +// MemoryStats represents memory statistics at a point in time, converted to int64 for safe use |
| 21 | +type MemoryStats struct { |
| 22 | + Alloc int64 // bytes allocated and not yet freed |
| 23 | + HeapAlloc int64 // bytes allocated and not yet freed (same as Alloc above but specifically for heap objects) |
| 24 | + Sys int64 // total bytes of memory obtained from the OS |
| 25 | + NumGC int64 // number of completed GC cycles |
| 26 | + PauseTotal int64 // cumulative nanoseconds in GC stop-the-world pauses |
| 27 | +} |
| 28 | + |
| 29 | +// ReadMemoryStats captures current memory statistics and converts them to int64 |
| 30 | +func ReadMemoryStats() MemoryStats { |
| 31 | + var memStats runtime.MemStats |
| 32 | + runtime.ReadMemStats(&memStats) |
| 33 | + return MemoryStats{ |
| 34 | + Alloc: safeUint64ToInt64(memStats.Alloc), |
| 35 | + HeapAlloc: safeUint64ToInt64(memStats.HeapAlloc), |
| 36 | + Sys: safeUint64ToInt64(memStats.Sys), |
| 37 | + NumGC: int64(memStats.NumGC), |
| 38 | + PauseTotal: safeUint64ToInt64(memStats.PauseTotalNs), |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +// SetMemoryAttributes sets memory-related attributes on a span with the given prefix |
| 43 | +func SetMemoryAttributes(span trace.Span, prefix string, memStats MemoryStats) { |
| 44 | + span.SetAttributes( |
| 45 | + attribute.Int64(prefix+".memoryBytes", memStats.Alloc), |
| 46 | + attribute.Int64(prefix+".memoryHeapBytes", memStats.HeapAlloc), |
| 47 | + attribute.Int64(prefix+".memorySysBytes", memStats.Sys), |
| 48 | + attribute.Int64(prefix+".memoryNumGC", memStats.NumGC), |
| 49 | + attribute.Int64(prefix+".memoryPauseTotalNs", memStats.PauseTotal), |
| 50 | + ) |
| 51 | +} |
| 52 | + |
| 53 | +// SetMemoryDeltaAttributes sets memory delta attributes on a span with the given prefix |
| 54 | +// It calculates the difference between before and after memory stats |
| 55 | +func SetMemoryDeltaAttributes(span trace.Span, prefix string, before, after MemoryStats) { |
| 56 | + deltaAlloc := after.Alloc - before.Alloc |
| 57 | + deltaHeapAlloc := after.HeapAlloc - before.HeapAlloc |
| 58 | + deltaSys := after.Sys - before.Sys |
| 59 | + deltaNumGC := after.NumGC - before.NumGC |
| 60 | + deltaPauseTotal := after.PauseTotal - before.PauseTotal |
| 61 | + |
| 62 | + span.SetAttributes( |
| 63 | + attribute.Int64(prefix+".memoryDeltaBytes", deltaAlloc), |
| 64 | + attribute.Int64(prefix+".memoryDeltaHeapBytes", deltaHeapAlloc), |
| 65 | + attribute.Int64(prefix+".memoryDeltaSysBytes", deltaSys), |
| 66 | + attribute.Int64(prefix+".memoryDeltaNumGC", deltaNumGC), |
| 67 | + attribute.Int64(prefix+".memoryDeltaPauseTotalNs", deltaPauseTotal), |
| 68 | + ) |
| 69 | +} |
0 commit comments