chore: auto-commit (97 archivos)
- .claude/CLAUDE.md - .claude/agents/fn-recopilador/SKILL.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - bash/functions/infra/build_cpp_windows.sh - cpp/CMakeLists.txt - cpp/PATTERNS.md - cpp/framework/app_base.cpp - cpp/framework/app_base.h - dev/issues/README.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package datascience
|
||||
|
||||
import "sort"
|
||||
|
||||
// MetricsDrift calculates the relative drift of a current measurement against
|
||||
// a historical baseline computed at the given percentile.
|
||||
//
|
||||
// historical is a window of past measurements (e.g. duration_ms, bytes).
|
||||
// percentile selects the baseline: 0.5 = median, 0.95 = p95.
|
||||
// drift = (current - baseline) / baseline, e.g. 0.47 means +47% above baseline.
|
||||
//
|
||||
// Returns drift=0, baseline=0 when historical is empty or baseline is zero.
|
||||
func MetricsDrift(historical []int64, current int64, percentile float64) (drift float64, baseline int64) {
|
||||
if len(historical) == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
sorted := make([]int64, len(historical))
|
||||
copy(sorted, historical)
|
||||
sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
|
||||
|
||||
baseline = Percentile(sorted, percentile)
|
||||
if baseline == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
drift = float64(current-baseline) / float64(baseline)
|
||||
return drift, baseline
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: metrics_drift
|
||||
kind: function
|
||||
lang: go
|
||||
domain: datascience
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func MetricsDrift(historical []int64, current int64, percentile float64) (drift float64, baseline int64)"
|
||||
description: "Calcula la deriva relativa de una medicion actual respecto a una linea base historica. La linea base se obtiene como el percentil indicado del historico. drift = (current - baseline) / baseline. Retorna drift=0, baseline=0 si el historico esta vacio o la linea base es cero."
|
||||
tags: [metrics, drift, percentile, statistics, monitoring, baseline]
|
||||
uses_functions: [percentile_int64_go_datascience]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [sort]
|
||||
tested: true
|
||||
tests:
|
||||
- "historico vacio retorna drift 0 baseline 0"
|
||||
- "baseline cero retorna drift 0 baseline 0"
|
||||
- "drift positivo cuando current supera baseline"
|
||||
- "drift negativo cuando current es menor que baseline"
|
||||
test_file_path: "functions/datascience/metrics_drift_test.go"
|
||||
file_path: "functions/datascience/metrics_drift.go"
|
||||
params:
|
||||
- name: historical
|
||||
desc: "Ventana de mediciones previas en la misma unidad que current (ms, bytes, etc.). No necesita estar ordenada."
|
||||
- name: current
|
||||
desc: "Medicion actual a comparar contra la linea base historica."
|
||||
- name: percentile
|
||||
desc: "Percentil para calcular la linea base: 0.5 = mediana, 0.95 = p95. Rango [0.0, 1.0]."
|
||||
output: "drift es la desviacion relativa como fraccion (0.47 = +47% por encima de la linea base, -0.5 = 50% por debajo). baseline es el valor del percentil sobre el historico."
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
historical := []int64{100, 120, 95, 110, 105} // ms de respuesta previos
|
||||
current := int64(200) // ms de la ejecucion actual
|
||||
|
||||
drift, baseline := MetricsDrift(historical, current, 0.5)
|
||||
// baseline ≈ 105 (mediana)
|
||||
// drift ≈ 0.905 (+90.5% sobre la mediana)
|
||||
|
||||
// Con p95 como referencia de "worst case normal"
|
||||
_, p95 := MetricsDrift(historical, current, 0.95)
|
||||
// p95 = 120
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Funcion pura. El historico se ordena internamente (copia defensiva) antes de calcular el percentil con `Percentile` de `percentile_int64_go_datascience`. No muta el slice de entrada.
|
||||
|
||||
El drift puede ser negativo (mejora) o positivo (degradacion). El caller decide el umbral de alarma (ej. `drift > 0.5` = degradacion mayor al 50%).
|
||||
|
||||
Util para el agente `fn-analizador` para comparar `duration_ms` de la ejecucion actual contra el historico de `executions` en `operations.db`.
|
||||
@@ -0,0 +1,47 @@
|
||||
package datascience
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMetricsDrift(t *testing.T) {
|
||||
t.Run("historico vacio retorna drift 0 baseline 0", func(t *testing.T) {
|
||||
drift, baseline := MetricsDrift([]int64{}, 100, 0.5)
|
||||
if drift != 0 || baseline != 0 {
|
||||
t.Errorf("expected drift=0 baseline=0, got drift=%v baseline=%v", drift, baseline)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("baseline cero retorna drift 0 baseline 0", func(t *testing.T) {
|
||||
// todos ceros -> percentil = 0 -> baseline = 0
|
||||
drift, baseline := MetricsDrift([]int64{0, 0, 0}, 50, 0.5)
|
||||
if drift != 0 || baseline != 0 {
|
||||
t.Errorf("expected drift=0 baseline=0 when baseline is zero, got drift=%v baseline=%v", drift, baseline)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("drift positivo cuando current supera baseline", func(t *testing.T) {
|
||||
// historico: [100,100,100,100,100], mediana=100
|
||||
// current=147 -> drift=0.47
|
||||
drift, baseline := MetricsDrift([]int64{100, 100, 100, 100, 100}, 147, 0.5)
|
||||
if baseline != 100 {
|
||||
t.Errorf("expected baseline=100, got %v", baseline)
|
||||
}
|
||||
if math.Abs(drift-0.47) > 1e-9 {
|
||||
t.Errorf("expected drift=0.47, got %v", drift)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("drift negativo cuando current es menor que baseline", func(t *testing.T) {
|
||||
// historico: [200,200,200], mediana=200
|
||||
// current=100 -> drift=-0.5
|
||||
drift, baseline := MetricsDrift([]int64{200, 200, 200}, 100, 0.5)
|
||||
if baseline != 200 {
|
||||
t.Errorf("expected baseline=200, got %v", baseline)
|
||||
}
|
||||
if math.Abs(drift-(-0.5)) > 1e-9 {
|
||||
t.Errorf("expected drift=-0.5, got %v", drift)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user