feat(openclaw-monitor): add MinIO telemetry
This commit is contained in:
@@ -3,7 +3,9 @@ package openclaw
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -196,6 +198,78 @@ func CollectBackupStatus(instanceName string) (*BackupStatus, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CollectMinIOMetrics(instanceName string) (*MinIOMetrics, error) {
|
||||
targetInstance := envDefault("OPENCLAW_MINIO_INSTANCE", "zap")
|
||||
if instanceName != targetInstance {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
endpoint := envDefault("OPENCLAW_MINIO_ENDPOINT", "http://192.168.153.253:9000")
|
||||
bucket := envDefault("OPENCLAW_MINIO_BUCKET", "zap")
|
||||
prefix := envDefault("OPENCLAW_MINIO_PREFIX", "backups")
|
||||
|
||||
metrics := &MinIOMetrics{
|
||||
Endpoint: endpoint,
|
||||
Bucket: bucket,
|
||||
Prefix: prefix,
|
||||
}
|
||||
|
||||
healthURL := strings.TrimRight(endpoint, "/") + "/minio/health/live"
|
||||
statusOutput, err := exec.Command("curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--connect-timeout", "5", healthURL).CombinedOutput()
|
||||
if err != nil {
|
||||
metrics.Error = fmt.Sprintf("health check failed: %v", err)
|
||||
return metrics, nil
|
||||
}
|
||||
if code, err := strconv.Atoi(strings.TrimSpace(string(statusOutput))); err == nil {
|
||||
metrics.HTTPStatus = code
|
||||
metrics.Reachable = code == 200
|
||||
}
|
||||
|
||||
listOutput, err := exec.Command(
|
||||
"aws",
|
||||
"--endpoint-url", endpoint,
|
||||
"s3api", "list-objects-v2",
|
||||
"--bucket", bucket,
|
||||
"--prefix", strings.Trim(prefix, "/")+"/",
|
||||
"--output", "json",
|
||||
).CombinedOutput()
|
||||
if err != nil {
|
||||
msg := strings.TrimSpace(string(listOutput))
|
||||
if msg == "" {
|
||||
msg = err.Error()
|
||||
}
|
||||
metrics.Error = msg
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
Contents []struct {
|
||||
Key string `json:"Key"`
|
||||
Size int64 `json:"Size"`
|
||||
LastModified time.Time `json:"LastModified"`
|
||||
} `json:"Contents"`
|
||||
}
|
||||
if err := json.Unmarshal(listOutput, &resp); err != nil {
|
||||
metrics.Error = fmt.Sprintf("invalid usage response: %v", err)
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
metrics.ObjectCount = len(resp.Contents)
|
||||
for _, obj := range resp.Contents {
|
||||
metrics.TotalBytes += obj.Size
|
||||
}
|
||||
|
||||
if len(resp.Contents) > 0 {
|
||||
sort.Slice(resp.Contents, func(i, j int) bool {
|
||||
return resp.Contents[i].LastModified.After(resp.Contents[j].LastModified)
|
||||
})
|
||||
metrics.LatestKey = resp.Contents[0].Key
|
||||
metrics.LatestBackup = resp.Contents[0].LastModified.UTC().Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
func DetectIssues(metrics Metrics) Issues {
|
||||
issues := Issues{}
|
||||
|
||||
@@ -270,6 +344,13 @@ func LoadInstances(registryPath string) ([]Instance, error) {
|
||||
return instances, nil
|
||||
}
|
||||
|
||||
func envDefault(key, def string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func virshCmd(args ...string) (string, error) {
|
||||
cmd := exec.Command("virsh", append([]string{"-c", "qemu:///system"}, args...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
Reference in New Issue
Block a user