Files
browser/platform/validator/observability.go
T

101 lines
4.2 KiB
Go

package validator
import (
"fmt"
"strings"
"browser.local/platform/domain"
)
const (
MaxMetricSamplesPerQuery = 500
MaxBackupRecordsPerQuery = 200
)
func ValidateMetricSample(sample domain.MetricSample) error {
var violations []string
violations = appendRequired(violations, "id", sample.ID)
violations = appendRequired(violations, "serverInstanceId", sample.ServerInstanceID)
violations = appendRequired(violations, "source", sample.Source)
if sample.CollectedAt.IsZero() {
violations = append(violations, "collectedAt is required")
}
for name, value := range map[string]*float64{"tps": sample.TPS, "latencyMs": sample.LatencyMS, "cpuPercent": sample.CPUPercent, "memoryPercent": sample.MemoryPercent, "diskPercent": sample.DiskPercent} {
if value != nil && (value == nil || *value < 0) {
violations = append(violations, fmt.Sprintf("%s must not be negative", name))
}
}
return finish(violations)
}
func ValidateMetricSampleFilter(filter domain.MetricSampleFilter) error {
var violations []string
if filter.Limit < 0 || filter.Limit > MaxMetricSamplesPerQuery {
violations = append(violations, fmt.Sprintf("limit must be between 0 and %d", MaxMetricSamplesPerQuery))
}
if filter.Before.Before(filter.After) {
violations = append(violations, "before must not precede after")
}
return finish(violations)
}
func ValidateBackupRecord(record domain.BackupRecord) error {
var violations []string
violations = appendRequired(violations, "id", record.ID)
violations = appendRequired(violations, "serverInstanceId", record.ServerInstanceID)
violations = appendRequired(violations, "artifactId", record.ArtifactID)
violations = appendRequired(violations, "checksum", record.Checksum)
if record.SizeBytes <= 0 {
violations = append(violations, "sizeBytes must be positive")
}
if record.State != domain.BackupStatePending && record.State != domain.BackupStateAvailable && record.State != domain.BackupStateFailed && record.State != domain.BackupStateExpired {
violations = append(violations, "state is invalid")
}
if len(record.RecoveryStatus) > 256 {
violations = append(violations, "recoveryStatus is too long")
}
return finish(violations)
}
func ValidateBackupFilter(filter domain.BackupFilter) error {
if filter.State != "" && filter.State != domain.BackupStatePending && filter.State != domain.BackupStateAvailable && filter.State != domain.BackupStateFailed && filter.State != domain.BackupStateExpired {
return ValidationError{Violations: []string{"state is invalid"}}
}
return nil
}
func ValidateRemoteAdapterDeclaration(declaration domain.RemoteAdapterDeclaration) error {
var violations []string
violations = appendRequired(violations, "key", declaration.Key)
violations = appendRequired(violations, "kind", string(declaration.Kind))
if len(declaration.TargetKeys) == 0 {
violations = append(violations, "targetKeys must not be empty")
}
if declaration.TimeoutSeconds <= 0 || declaration.TimeoutSeconds > 300 {
violations = append(violations, "timeoutSeconds must be between 1 and 300")
}
if declaration.MaxAttempts <= 0 || declaration.MaxAttempts > 5 {
violations = append(violations, "maxAttempts must be between 1 and 5")
}
return finish(violations)
}
func ValidateRemoteAdapterRequest(request domain.RemoteAdapterRequest) error {
var violations []string
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
violations = appendRequired(violations, "declarationKey", request.DeclarationKey)
violations = appendRequired(violations, "targetKey", request.TargetKey)
violations = appendRequired(violations, "capability", request.Capability)
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
if request.TimeoutSeconds < 0 || request.TimeoutSeconds > 300 {
violations = append(violations, "timeoutSeconds must be between 0 and 300")
}
if request.MaxAttempts < 0 || request.MaxAttempts > 5 {
violations = append(violations, "maxAttempts must be between 0 and 5")
}
if strings.ContainsAny(request.TargetKey, "\\\n\r") || strings.Contains(request.TargetKey, "://") || strings.ContainsAny(request.TargetKey, " ") {
violations = append(violations, "targetKey must be a logical key")
}
return finish(violations)
}