summaryrefslogtreecommitdiff
path: root/internal/statsengine/aggregate.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-20 11:38:19 +0300
committerPaul Buetow <paul@buetow.org>2026-05-20 11:38:19 +0300
commit9310b54d439d4a1a8d4d337987aa63884df0af76 (patch)
treec6fb38085891a04ce81672f977af316a2e96b2fd /internal/statsengine/aggregate.go
parent5fd613562e2aa2ab3aac3349f44db88330046c1c (diff)
feat: add syscall aggregate sampling infrastructure (task 17)
Diffstat (limited to 'internal/statsengine/aggregate.go')
-rw-r--r--internal/statsengine/aggregate.go46
1 files changed, 46 insertions, 0 deletions
diff --git a/internal/statsengine/aggregate.go b/internal/statsengine/aggregate.go
new file mode 100644
index 0000000..03dad5d
--- /dev/null
+++ b/internal/statsengine/aggregate.go
@@ -0,0 +1,46 @@
+package statsengine
+
+import "ior/internal/types"
+
+// SyscallAggregate is the kernel-side aggregate for one sys_enter trace ID.
+type SyscallAggregate struct {
+ TraceID types.TraceId
+ Count uint64
+ Errors uint64
+ TotalLatencyNs uint64
+ MinLatencyNs uint64
+ MaxLatencyNs uint64
+ LatencyHistogramNs [8]uint64
+}
+
+// IngestSyscallAggregates folds kernel aggregate rows into the engine.
+func (e *Engine) IngestSyscallAggregates(rows []SyscallAggregate) {
+ if e == nil || len(rows) == 0 {
+ return
+ }
+
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ now := e.now()
+ var batchLatency uint64
+ var batchCount uint64
+ for _, row := range rows {
+ if row.Count == 0 {
+ continue
+ }
+
+ e.totalSyscalls += row.Count
+ e.totalErrors += row.Errors
+ e.totalLatency += row.TotalLatencyNs
+ e.syscalls.AddAggregate(row)
+ e.families.AddAggregate(row)
+ e.latencyHist.AddBucketCounts(row.LatencyHistogramNs)
+
+ batchLatency += row.TotalLatencyNs
+ batchCount += row.Count
+ }
+ if batchCount > 0 {
+ e.latencySeries.Add(float64(batchLatency)/float64(batchCount), now)
+ }
+}