feat: 建立可观测性、容量与恢复验证基线
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Dependency 依赖名称。
|
||||
type Dependency string
|
||||
|
||||
const (
|
||||
DependencyPostgres Dependency = "postgresql"
|
||||
DependencyRedis Dependency = "redis"
|
||||
DependencyMQTT Dependency = "mqtt"
|
||||
DependencyIoTDB Dependency = "iotdb"
|
||||
DependencyS3 Dependency = "s3"
|
||||
DependencyAI Dependency = "ai"
|
||||
DependencyWVP Dependency = "wvp"
|
||||
DependencyWechat Dependency = "wechat"
|
||||
DependencyWeather Dependency = "weather"
|
||||
)
|
||||
|
||||
// DependencyMetric 依赖调用指标。
|
||||
type DependencyMetric struct {
|
||||
Requests int64 `json:"requests"`
|
||||
Failures int64 `json:"failures"`
|
||||
LastLatencyMs float64 `json:"lastLatencyMs"`
|
||||
P50LatencyMs float64 `json:"p50LatencyMs"`
|
||||
P95LatencyMs float64 `json:"p95LatencyMs"`
|
||||
LastSuccessAt *time.Time `json:"lastSuccessAt,omitempty"`
|
||||
LastFailureAt *time.Time `json:"lastFailureAt,omitempty"`
|
||||
LastError string `json:"lastError,omitempty"`
|
||||
}
|
||||
|
||||
var dependencyMetrics sync.Map
|
||||
|
||||
// RecordDependency 记录一次依赖调用。
|
||||
func RecordDependency(dep Dependency, err error, latency time.Duration) {
|
||||
now := time.Now()
|
||||
value, _ := dependencyMetrics.LoadOrStore(dep, &DependencyMetric{})
|
||||
metric := value.(*DependencyMetric)
|
||||
metric.Requests++
|
||||
metric.LastLatencyMs = float64(latency.Microseconds()) / 1000
|
||||
if err != nil {
|
||||
metric.Failures++
|
||||
metric.LastFailureAt = &now
|
||||
metric.LastError = err.Error()
|
||||
} else {
|
||||
metric.LastSuccessAt = &now
|
||||
metric.LastError = ""
|
||||
}
|
||||
}
|
||||
|
||||
// DependencySnapshot 返回当前依赖指标快照。
|
||||
func DependencySnapshot() map[Dependency]DependencyMetric {
|
||||
result := map[Dependency]DependencyMetric{}
|
||||
dependencyMetrics.Range(func(key, value interface{}) bool {
|
||||
dep := key.(Dependency)
|
||||
metric := *value.(*DependencyMetric)
|
||||
result[dep] = metric
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
// RecordDependencyHistogram 预留直方图能力;当前仅更新最近一次指标。
|
||||
func RecordDependencyHistogram(dep Dependency, err error, latency time.Duration, samples []float64) {
|
||||
RecordDependency(dep, err, latency)
|
||||
if len(samples) == 0 {
|
||||
return
|
||||
}
|
||||
value, _ := dependencyMetrics.LoadOrStore(dep, &DependencyMetric{})
|
||||
metric := value.(*DependencyMetric)
|
||||
sort.Float64s(samples)
|
||||
metric.P50LatencyMs = percentile(samples, 0.5)
|
||||
metric.P95LatencyMs = percentile(samples, 0.95)
|
||||
}
|
||||
|
||||
func percentile(sorted []float64, p float64) float64 {
|
||||
if len(sorted) == 0 {
|
||||
return 0
|
||||
}
|
||||
idx := int(float64(len(sorted)-1) * p)
|
||||
return sorted[idx]
|
||||
}
|
||||
Reference in New Issue
Block a user