...
This commit is contained in:
		| @@ -5,7 +5,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/hetznerinstall" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/hetznerinstall" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
|   | ||||
| @@ -6,10 +6,10 @@ import ( | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/dependencies" | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/gosp" | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/postgres" | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/verification" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/dependencies" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/gosp" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/postgres" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/verification" | ||||
| ) | ||||
|  | ||||
| // Constants for PostgreSQL installation | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/postgres" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/postgres" | ||||
| ) | ||||
|  | ||||
| // Constants for Go stored procedure | ||||
| @@ -46,10 +46,10 @@ func (b *GoSPBuilder) run(cmd string, args ...string) error { | ||||
| 	fmt.Println("Running:", cmd, args) | ||||
| 	c := exec.Command(cmd, args...) | ||||
| 	// Set environment variables | ||||
| 	c.Env = append(os.Environ(),  | ||||
| 	c.Env = append(os.Environ(), | ||||
| 		"GOROOT=/usr/local/go", | ||||
| 		"GOPATH=/root/go",  | ||||
| 		"PATH=/usr/local/go/bin:" + os.Getenv("PATH")) | ||||
| 		"GOPATH=/root/go", | ||||
| 		"PATH=/usr/local/go/bin:"+os.Getenv("PATH")) | ||||
| 	c.Stdout = os.Stdout | ||||
| 	c.Stderr = os.Stderr | ||||
| 	return c.Run() | ||||
| @@ -58,7 +58,7 @@ func (b *GoSPBuilder) run(cmd string, args ...string) error { | ||||
| // Build builds a Go stored procedure | ||||
| func (b *GoSPBuilder) Build() error { | ||||
| 	fmt.Println("Building Go stored procedure...") | ||||
| 	 | ||||
|  | ||||
| 	// Use the explicitly provided Go path if available | ||||
| 	var goExePath string | ||||
| 	if b.GoPath != "" { | ||||
| @@ -74,7 +74,7 @@ func (b *GoSPBuilder) Build() error { | ||||
| 		} | ||||
| 		fmt.Printf("Using detected Go executable from: %s\n", goExePath) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	if err := os.MkdirAll(b.GoSharedLibDir, 0755); err != nil { | ||||
| 		return fmt.Errorf("failed to create directory: %w", err) | ||||
| 	} | ||||
| @@ -98,27 +98,27 @@ func main() {} | ||||
|  | ||||
| 	// Use the full path to Go rather than relying on PATH | ||||
| 	fmt.Println("Running Go build with full path:", goExePath) | ||||
| 	 | ||||
|  | ||||
| 	// Show debug information | ||||
| 	fmt.Println("Environment variables that will be set:") | ||||
| 	fmt.Println("  GOROOT=/usr/local/go") | ||||
| 	fmt.Println("  GOPATH=/root/go") | ||||
| 	fmt.Println("  PATH=/usr/local/go/bin:" + os.Getenv("PATH")) | ||||
| 	 | ||||
|  | ||||
| 	// Verify that the Go executable exists before using it | ||||
| 	if _, err := os.Stat(goExePath); err != nil { | ||||
| 		return fmt.Errorf("Go executable not found at %s: %w", goExePath, err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Create the output directory if it doesn't exist | ||||
| 	outputDir := filepath.Join(b.InstallPrefix, "lib") | ||||
| 	if err := os.MkdirAll(outputDir, 0755); err != nil { | ||||
| 		return fmt.Errorf("failed to create output directory %s: %w", outputDir, err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Prepare output path | ||||
| 	outputPath := filepath.Join(outputDir, "libgosp.so") | ||||
| 	 | ||||
|  | ||||
| 	// Instead of relying on environment variables, create a wrapper shell script | ||||
| 	// that sets all required environment variables and then calls the Go executable | ||||
| 	tempDir, err := os.MkdirTemp("", "go-build-") | ||||
| @@ -126,7 +126,7 @@ func main() {} | ||||
| 		return fmt.Errorf("failed to create temp directory: %w", err) | ||||
| 	} | ||||
| 	defer os.RemoveAll(tempDir) // Clean up when done | ||||
| 	 | ||||
|  | ||||
| 	goRoot := filepath.Dir(filepath.Dir(goExePath)) // /usr/local/go | ||||
| 	wrapperScript := filepath.Join(tempDir, "go-wrapper.sh") | ||||
| 	wrapperContent := fmt.Sprintf(`#!/bin/sh | ||||
| @@ -143,25 +143,25 @@ echo "PATH=$PATH" | ||||
| echo "=== Running Go command ===" | ||||
| echo "%s $@" | ||||
| exec %s "$@" | ||||
| `,  | ||||
| 		goRoot,  | ||||
| `, | ||||
| 		goRoot, | ||||
| 		filepath.Dir(goExePath), | ||||
| 		goExePath, | ||||
| 		goExePath) | ||||
| 	 | ||||
|  | ||||
| 	// Write the wrapper script | ||||
| 	if err := os.WriteFile(wrapperScript, []byte(wrapperContent), 0755); err != nil { | ||||
| 		return fmt.Errorf("failed to write wrapper script: %w", err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	fmt.Printf("Created wrapper script at %s\n", wrapperScript) | ||||
| 	 | ||||
|  | ||||
| 	// Use the wrapper script to build the Go shared library | ||||
| 	cmd := exec.Command(wrapperScript, "build", "-buildmode=c-shared", "-o", outputPath, libPath) | ||||
| 	cmd.Dir = filepath.Dir(libPath) // Set working directory to where the source file is | ||||
| 	cmd.Stdout = os.Stdout | ||||
| 	cmd.Stderr = os.Stderr | ||||
| 	 | ||||
|  | ||||
| 	fmt.Printf("Executing Go build via wrapper script\n") | ||||
| 	if err := cmd.Run(); err != nil { | ||||
| 		return fmt.Errorf("failed to build Go stored procedure: %w", err) | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/mholt/archiver/v3" | ||||
| 	"github.com/mholt/archiver/v4" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| @@ -51,14 +51,14 @@ func (g *GoInstaller) GetGoVersion() (string, error) { | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to get Go version: %w", err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Parse go version output (format: "go version go1.x.x ...") | ||||
| 	version := strings.TrimSpace(string(output)) | ||||
| 	parts := strings.Split(version, " ") | ||||
| 	if len(parts) < 3 { | ||||
| 		return "", fmt.Errorf("unexpected go version output format: %s", version) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Return just the version number without the "go" prefix | ||||
| 	return strings.TrimPrefix(parts[2], "go"), nil | ||||
| } | ||||
| @@ -77,7 +77,7 @@ func (g *GoInstaller) InstallGo() (string, error) { | ||||
| 	// Default Go installation location | ||||
| 	var installDir string = "/usr/local" | ||||
| 	var goExePath string = filepath.Join(installDir, "go", "bin", "go") | ||||
| 	 | ||||
|  | ||||
| 	// Check if Go is already installed by checking the binary directly | ||||
| 	if _, err := os.Stat(goExePath); err == nil { | ||||
| 		version, err := g.GetGoVersion() | ||||
| @@ -86,7 +86,7 @@ func (g *GoInstaller) InstallGo() (string, error) { | ||||
| 			return goExePath, nil | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Also check if Go is available in PATH as a fallback | ||||
| 	if g.IsGoInstalled() { | ||||
| 		path, err := exec.LookPath("go") | ||||
| @@ -98,31 +98,31 @@ func (g *GoInstaller) InstallGo() (string, error) { | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	fmt.Printf("Installing Go version %s...\n", g.Version) | ||||
| 	 | ||||
|  | ||||
| 	// Determine architecture and OS | ||||
| 	goOS := runtime.GOOS | ||||
| 	goArch := runtime.GOARCH | ||||
| 	 | ||||
|  | ||||
| 	// Construct download URL | ||||
| 	downloadURL := fmt.Sprintf("https://golang.org/dl/go%s.%s-%s.tar.gz", g.Version, goOS, goArch) | ||||
| 	 | ||||
|  | ||||
| 	// Create a temporary directory for download | ||||
| 	tempDir, err := os.MkdirTemp("", "go-install-") | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to create temporary directory: %w", err) | ||||
| 	} | ||||
| 	defer os.RemoveAll(tempDir) | ||||
| 	 | ||||
|  | ||||
| 	// Download Go tarball | ||||
| 	tarballPath := filepath.Join(tempDir, "go.tar.gz") | ||||
| 	if err := downloadFile(downloadURL, tarballPath); err != nil { | ||||
| 		return "", fmt.Errorf("failed to download Go: %w", err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Install directory - typically /usr/local for Linux/macOS | ||||
| 	 | ||||
|  | ||||
| 	// Check if existing Go installation exists and remove it | ||||
| 	existingGoDir := filepath.Join(installDir, "go") | ||||
| 	if _, err := os.Stat(existingGoDir); err == nil { | ||||
| @@ -131,34 +131,34 @@ func (g *GoInstaller) InstallGo() (string, error) { | ||||
| 			return "", fmt.Errorf("failed to remove existing Go installation: %w", err) | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Extract tarball to install directory | ||||
| 	fmt.Printf("Extracting Go to %s\n", installDir) | ||||
| 	err = extractTarGz(tarballPath, installDir) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to extract Go tarball: %w", err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Verify installation | ||||
| 	var goExePathVerify = filepath.Join(installDir, "go", "bin", "go") // Use = instead of := to avoid variable shadowing | ||||
| 	 | ||||
|  | ||||
| 	// Check if the Go binary exists | ||||
| 	var statErr error | ||||
| 	_, statErr = os.Stat(goExePathVerify) | ||||
| 	if statErr != nil { | ||||
| 		return "", fmt.Errorf("Go installation failed - go executable not found at %s", goExePathVerify) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Set up environment variables | ||||
| 	fmt.Println("Setting up Go environment variables...") | ||||
| 	 | ||||
|  | ||||
| 	// Update PATH in /etc/profile | ||||
| 	profilePath := "/etc/profile" | ||||
| 	profileContent, err := os.ReadFile(profilePath) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to read profile: %w", err) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Add Go bin to PATH if not already there | ||||
| 	goBinPath := filepath.Join(installDir, "go", "bin") | ||||
| 	if !strings.Contains(string(profileContent), goBinPath) { | ||||
| @@ -167,7 +167,7 @@ func (g *GoInstaller) InstallGo() (string, error) { | ||||
| 			return "", fmt.Errorf("failed to update profile: %w", err) | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	fmt.Printf("✅ Go %s installed successfully!\n", g.Version) | ||||
| 	return goExePath, nil | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/stats" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/stats" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| @@ -18,11 +18,11 @@ func main() { | ||||
| 	// Create a new stats manager with Redis connection | ||||
| 	// Create a custom configuration | ||||
| 	config := &stats.Config{ | ||||
| 		RedisAddr:     "localhost:6379", | ||||
| 		RedisPassword: "", | ||||
| 		RedisDB:       0, | ||||
| 		Debug:         false, | ||||
| 		QueueSize:     100, | ||||
| 		RedisAddr:      "localhost:6379", | ||||
| 		RedisPassword:  "", | ||||
| 		RedisDB:        0, | ||||
| 		Debug:          false, | ||||
| 		QueueSize:      100, | ||||
| 		DefaultTimeout: 5 * time.Second, | ||||
| 		ExpirationTimes: map[string]time.Duration{ | ||||
| 			"system":   60 * time.Second,  // System info expires after 60 seconds | ||||
| @@ -32,7 +32,7 @@ func main() { | ||||
| 			"hardware": 120 * time.Second, // Hardware stats expire after 2 minutes | ||||
| 		}, | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	manager, err := stats.NewStatsManager(config) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error creating stats manager: %v\n", err) | ||||
| @@ -61,12 +61,12 @@ func main() { | ||||
| 		fmt.Printf("  Cores: %d\n", sysInfo.CPU.Cores) | ||||
| 		fmt.Printf("  Model: %s\n", sysInfo.CPU.ModelName) | ||||
| 		fmt.Printf("  Usage: %.1f%%\n", sysInfo.CPU.UsagePercent) | ||||
| 		 | ||||
|  | ||||
| 		fmt.Println("\nMemory Information:") | ||||
| 		fmt.Printf("  Total: %.1f GB\n", sysInfo.Memory.Total) | ||||
| 		fmt.Printf("  Used: %.1f GB (%.1f%%)\n", sysInfo.Memory.Used, sysInfo.Memory.UsedPercent) | ||||
| 		fmt.Printf("  Free: %.1f GB\n", sysInfo.Memory.Free) | ||||
| 		 | ||||
|  | ||||
| 		fmt.Println("\nNetwork Information:") | ||||
| 		fmt.Printf("  Upload Speed: %s\n", sysInfo.Network.UploadSpeed) | ||||
| 		fmt.Printf("  Download Speed: %s\n", sysInfo.Network.DownloadSpeed) | ||||
| @@ -81,7 +81,7 @@ func main() { | ||||
| 	} else { | ||||
| 		fmt.Printf("Found %d disks:\n", len(diskStats.Disks)) | ||||
| 		for _, disk := range diskStats.Disks { | ||||
| 			fmt.Printf("  %s: %.1f GB total, %.1f GB free (%.1f%% used)\n",  | ||||
| 			fmt.Printf("  %s: %.1f GB total, %.1f GB free (%.1f%% used)\n", | ||||
| 				disk.Path, disk.Total, disk.Free, disk.UsedPercent) | ||||
| 		} | ||||
| 	} | ||||
| @@ -93,12 +93,12 @@ func main() { | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting process stats: %v\n", err) | ||||
| 	} else { | ||||
| 		fmt.Printf("Total processes: %d (showing top %d)\n",  | ||||
| 		fmt.Printf("Total processes: %d (showing top %d)\n", | ||||
| 			processStats.Total, len(processStats.Processes)) | ||||
| 		 | ||||
|  | ||||
| 		fmt.Println("\nTop Processes by CPU Usage:") | ||||
| 		for i, proc := range processStats.Processes { | ||||
| 			fmt.Printf("  %d. PID %d: %s (CPU: %.1f%%, Memory: %.1f MB)\n",  | ||||
| 			fmt.Printf("  %d. PID %d: %s (CPU: %.1f%%, Memory: %.1f MB)\n", | ||||
| 				i+1, proc.PID, proc.Name, proc.CPUPercent, proc.MemoryMB) | ||||
| 		} | ||||
| 	} | ||||
| @@ -107,10 +107,10 @@ func main() { | ||||
| 	fmt.Println("\n4. CACHING DEMONSTRATION") | ||||
| 	fmt.Println("----------------------") | ||||
| 	fmt.Println("Getting network speed multiple times (should use cache):") | ||||
| 	 | ||||
|  | ||||
| 	for i := 0; i < 3; i++ { | ||||
| 		netSpeed := manager.GetNetworkSpeedResult() | ||||
| 		fmt.Printf("  Request %d: Upload: %s, Download: %s\n",  | ||||
| 		fmt.Printf("  Request %d: Upload: %s, Download: %s\n", | ||||
| 			i+1, netSpeed.UploadSpeed, netSpeed.DownloadSpeed) | ||||
| 		time.Sleep(500 * time.Millisecond) | ||||
| 	} | ||||
| @@ -127,17 +127,17 @@ func main() { | ||||
| 	fmt.Println("--------------------------") | ||||
| 	fmt.Println("Enabling debug mode (direct fetching without cache)...") | ||||
| 	manager.Debug = true | ||||
| 	 | ||||
|  | ||||
| 	fmt.Println("Getting system info in debug mode:") | ||||
| 	debugSysInfo, err := manager.GetSystemInfo() | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error: %v\n", err) | ||||
| 	} else { | ||||
| 		fmt.Printf("  CPU Usage: %.1f%%\n", debugSysInfo.CPU.UsagePercent) | ||||
| 		fmt.Printf("  Memory Used: %.1f GB (%.1f%%)\n",  | ||||
| 		fmt.Printf("  Memory Used: %.1f GB (%.1f%%)\n", | ||||
| 			debugSysInfo.Memory.Used, debugSysInfo.Memory.UsedPercent) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Reset debug mode | ||||
| 	manager.Debug = false | ||||
|  | ||||
| @@ -148,17 +148,17 @@ func main() { | ||||
| 	for statsType, duration := range manager.Expiration { | ||||
| 		fmt.Printf("  %s: %v\n", statsType, duration) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	fmt.Println("\nChanging system stats expiration to 10 seconds...") | ||||
| 	manager.Expiration["system"] = 10 * time.Second | ||||
| 	 | ||||
|  | ||||
| 	fmt.Println("Updated expiration times:") | ||||
| 	for statsType, duration := range manager.Expiration { | ||||
| 		fmt.Printf("  %s: %v\n", statsType, duration) | ||||
| 	} | ||||
|  | ||||
| 	fmt.Println("\nDemo complete. Press Ctrl+C to exit.") | ||||
| 	 | ||||
|  | ||||
| 	// Keep the program running | ||||
| 	select {} | ||||
| } | ||||
|   | ||||
| @@ -11,27 +11,27 @@ import ( | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/stats" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/stats" | ||||
| 	"github.com/shirou/gopsutil/v3/cpu" | ||||
| 	"github.com/shirou/gopsutil/v3/process" | ||||
| ) | ||||
|  | ||||
| // TestResult stores the results of a single test run | ||||
| type TestResult struct { | ||||
| 	StartTime       time.Time | ||||
| 	EndTime         time.Time | ||||
| 	SystemInfoTime  time.Duration | ||||
| 	DiskStatsTime   time.Duration | ||||
| 	ProcessTime     time.Duration | ||||
| 	NetworkTime     time.Duration | ||||
| 	HardwareTime    time.Duration | ||||
| 	TotalTime       time.Duration | ||||
| 	UserCPU         float64 | ||||
| 	SystemCPU       float64 | ||||
| 	TotalCPU        float64 | ||||
| 	OverallCPU      float64 | ||||
| 	MemoryUsageMB   float32 | ||||
| 	NumGoroutines   int | ||||
| 	StartTime      time.Time | ||||
| 	EndTime        time.Time | ||||
| 	SystemInfoTime time.Duration | ||||
| 	DiskStatsTime  time.Duration | ||||
| 	ProcessTime    time.Duration | ||||
| 	NetworkTime    time.Duration | ||||
| 	HardwareTime   time.Duration | ||||
| 	TotalTime      time.Duration | ||||
| 	UserCPU        float64 | ||||
| 	SystemCPU      float64 | ||||
| 	TotalCPU       float64 | ||||
| 	OverallCPU     float64 | ||||
| 	MemoryUsageMB  float32 | ||||
| 	NumGoroutines  int | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| @@ -66,11 +66,11 @@ func main() { | ||||
|  | ||||
| 	// Create a new stats manager with Redis connection | ||||
| 	config := &stats.Config{ | ||||
| 		RedisAddr:     "localhost:6379", | ||||
| 		RedisPassword: "", | ||||
| 		RedisDB:       0, | ||||
| 		Debug:         false, | ||||
| 		QueueSize:     100, | ||||
| 		RedisAddr:      "localhost:6379", | ||||
| 		RedisPassword:  "", | ||||
| 		RedisDB:        0, | ||||
| 		Debug:          false, | ||||
| 		QueueSize:      100, | ||||
| 		DefaultTimeout: 5 * time.Second, | ||||
| 		ExpirationTimes: map[string]time.Duration{ | ||||
| 			"system":   60 * time.Second,  // System info expires after 60 seconds | ||||
| @@ -80,7 +80,7 @@ func main() { | ||||
| 			"hardware": 120 * time.Second, // Hardware stats expire after 2 minutes | ||||
| 		}, | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	manager, err := stats.NewStatsManager(config) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error creating stats manager: %v\n", err) | ||||
| @@ -101,11 +101,11 @@ func main() { | ||||
| 	// Set up signal handling for graceful shutdown | ||||
| 	sigChan := make(chan os.Signal, 1) | ||||
| 	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) | ||||
| 	 | ||||
|  | ||||
| 	// Create a ticker for running tests at the specified interval | ||||
| 	ticker := time.NewTicker(time.Duration(*intervalPtr) * time.Second) | ||||
| 	defer ticker.Stop() | ||||
| 	 | ||||
|  | ||||
| 	// Store the sleep duration between operations | ||||
| 	sleepDuration := time.Duration(*sleepPtr) * time.Millisecond | ||||
|  | ||||
| @@ -118,7 +118,7 @@ func main() { | ||||
|  | ||||
| 	// Store test results | ||||
| 	var results []TestResult | ||||
| 	 | ||||
|  | ||||
| 	// Print header | ||||
| 	fmt.Printf("%-20s %-20s %-12s %-12s %-12s %-12s %-12s %-12s %-12s %-12s %-12s %-12s %-12s\n", | ||||
| 		"Start Time", "End Time", "System(ms)", "Disk(ms)", "Process(ms)", "Network(ms)", "Hardware(ms)", "Total(ms)", "UserCPU(%)", "SysCPU(%)", "TotalCPU(%)", "Memory(MB)", "Goroutines") | ||||
| @@ -131,7 +131,7 @@ func main() { | ||||
| 			// Run a test and record the results | ||||
| 			result := runTest(manager, currentProcess, sleepDuration) | ||||
| 			results = append(results, result) | ||||
| 			 | ||||
|  | ||||
| 			// Print the result | ||||
| 			fmt.Printf("%-20s %-20s %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f %-12.2f %-12d\n", | ||||
| 				result.StartTime.Format("15:04:05.000000"), | ||||
| @@ -147,16 +147,16 @@ func main() { | ||||
| 				result.TotalCPU, | ||||
| 				result.MemoryUsageMB, | ||||
| 				result.NumGoroutines) | ||||
| 			 | ||||
|  | ||||
| 		case <-sigChan: | ||||
| 			// Calculate and print summary statistics | ||||
| 			fmt.Println("\nTest Summary:") | ||||
| 			fmt.Println(strings.Repeat("-", 50)) | ||||
| 			 | ||||
|  | ||||
| 			var totalSystemTime, totalDiskTime, totalProcessTime, totalNetworkTime, totalHardwareTime, totalTime time.Duration | ||||
| 			var totalUserCPU, totalSystemCPU, totalCombinedCPU, totalOverallCPU float64 | ||||
| 			var totalMemory float32 | ||||
| 			 | ||||
|  | ||||
| 			for _, r := range results { | ||||
| 				totalSystemTime += r.SystemInfoTime | ||||
| 				totalDiskTime += r.DiskStatsTime | ||||
| @@ -170,7 +170,7 @@ func main() { | ||||
| 				totalOverallCPU += r.OverallCPU | ||||
| 				totalMemory += r.MemoryUsageMB | ||||
| 			} | ||||
| 			 | ||||
|  | ||||
| 			count := float64(len(results)) | ||||
| 			if count > 0 { | ||||
| 				fmt.Printf("Average System Info Time:  %.2f ms\n", float64(totalSystemTime.Microseconds())/(count*1000)) | ||||
| @@ -185,7 +185,7 @@ func main() { | ||||
| 				fmt.Printf("Average Overall CPU:       %.2f%%\n", totalOverallCPU/count) | ||||
| 				fmt.Printf("Average Memory Usage:      %.2f MB\n", float64(totalMemory)/count) | ||||
| 			} | ||||
| 			 | ||||
|  | ||||
| 			fmt.Println("\nTest completed. Exiting...") | ||||
| 			return | ||||
| 		} | ||||
| @@ -196,90 +196,90 @@ func main() { | ||||
| func runTest(manager *stats.StatsManager, proc *process.Process, sleepBetweenOps time.Duration) TestResult { | ||||
| 	// Get initial CPU times for the process | ||||
| 	initialTimes, _ := proc.Times() | ||||
| 	 | ||||
|  | ||||
| 	// Get initial overall CPU usage | ||||
| 	_, _ = cpu.Percent(0, false) // Discard initial reading, we'll only use the final reading | ||||
| 	 | ||||
|  | ||||
| 	result := TestResult{ | ||||
| 		StartTime: time.Now(), | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Measure total time | ||||
| 	totalStart := time.Now() | ||||
| 	 | ||||
|  | ||||
| 	// Measure system info time | ||||
| 	start := time.Now() | ||||
| 	_, _ = manager.GetSystemInfo() | ||||
| 	result.SystemInfoTime = time.Since(start) | ||||
| 	 | ||||
|  | ||||
| 	// Sleep between operations if configured | ||||
| 	if sleepBetweenOps > 0 { | ||||
| 		time.Sleep(sleepBetweenOps) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Measure disk stats time | ||||
| 	start = time.Now() | ||||
| 	_, _ = manager.GetDiskStats() | ||||
| 	result.DiskStatsTime = time.Since(start) | ||||
| 	 | ||||
|  | ||||
| 	// Sleep between operations if configured | ||||
| 	if sleepBetweenOps > 0 { | ||||
| 		time.Sleep(sleepBetweenOps) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Measure process stats time | ||||
| 	start = time.Now() | ||||
| 	_, _ = manager.GetProcessStats(10) | ||||
| 	result.ProcessTime = time.Since(start) | ||||
| 	 | ||||
|  | ||||
| 	// Sleep between operations if configured | ||||
| 	if sleepBetweenOps > 0 { | ||||
| 		time.Sleep(sleepBetweenOps) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Measure network speed time | ||||
| 	start = time.Now() | ||||
| 	_ = manager.GetNetworkSpeedResult() | ||||
| 	result.NetworkTime = time.Since(start) | ||||
| 	 | ||||
|  | ||||
| 	// Sleep between operations if configured | ||||
| 	if sleepBetweenOps > 0 { | ||||
| 		time.Sleep(sleepBetweenOps) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Measure hardware stats time | ||||
| 	start = time.Now() | ||||
| 	_ = manager.GetHardwareStatsJSON() | ||||
| 	result.HardwareTime = time.Since(start) | ||||
| 	 | ||||
|  | ||||
| 	// Record total time | ||||
| 	result.TotalTime = time.Since(totalStart) | ||||
| 	result.EndTime = time.Now() | ||||
| 	 | ||||
|  | ||||
| 	// Get final CPU times for the process | ||||
| 	finalTimes, _ := proc.Times() | ||||
| 	 | ||||
|  | ||||
| 	// Calculate CPU usage for this specific operation | ||||
| 	if initialTimes != nil && finalTimes != nil { | ||||
| 		result.UserCPU = (finalTimes.User - initialTimes.User) * 100 | ||||
| 		result.SystemCPU = (finalTimes.System - initialTimes.System) * 100 | ||||
| 		result.TotalCPU = result.UserCPU + result.SystemCPU | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Get overall CPU usage | ||||
| 	finalOverallCPU, _ := cpu.Percent(0, false) | ||||
| 	if len(finalOverallCPU) > 0 { | ||||
| 		result.OverallCPU = finalOverallCPU[0] | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Measure memory usage | ||||
| 	memInfo, _ := proc.MemoryInfo() | ||||
| 	if memInfo != nil { | ||||
| 		result.MemoryUsageMB = float32(memInfo.RSS) / (1024 * 1024) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Record number of goroutines | ||||
| 	result.NumGoroutines = runtime.NumGoroutine() | ||||
| 	 | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"os" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/stats" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/stats" | ||||
| 	"github.com/redis/go-redis/v9" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"os" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/freeflowuniverse/heroagent/pkg/system/stats" | ||||
| 	"git.ourworld.tf/herocode/heroagent/pkg/system/stats" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| @@ -15,21 +15,21 @@ func main() { | ||||
|  | ||||
| 	// Create a new stats manager with Redis connection | ||||
| 	config := &stats.Config{ | ||||
| 		RedisAddr:     "localhost:6379", | ||||
| 		RedisPassword: "", | ||||
| 		RedisDB:       0, | ||||
| 		Debug:         false, | ||||
| 		QueueSize:     100, | ||||
| 		RedisAddr:      "localhost:6379", | ||||
| 		RedisPassword:  "", | ||||
| 		RedisDB:        0, | ||||
| 		Debug:          false, | ||||
| 		QueueSize:      100, | ||||
| 		DefaultTimeout: 5 * time.Second, | ||||
| 		ExpirationTimes: map[string]time.Duration{ | ||||
| 			"system":   30 * time.Second,  // System info expires after 30 seconds | ||||
| 			"disk":     60 * time.Second,  // Disk info expires after 1 minute | ||||
| 			"process":  15 * time.Second,  // Process info expires after 15 seconds | ||||
| 			"network":  20 * time.Second,  // Network info expires after 20 seconds | ||||
| 			"hardware": 60 * time.Second,  // Hardware stats expire after 1 minute | ||||
| 			"system":   30 * time.Second, // System info expires after 30 seconds | ||||
| 			"disk":     60 * time.Second, // Disk info expires after 1 minute | ||||
| 			"process":  15 * time.Second, // Process info expires after 15 seconds | ||||
| 			"network":  20 * time.Second, // Network info expires after 20 seconds | ||||
| 			"hardware": 60 * time.Second, // Hardware stats expire after 1 minute | ||||
| 		}, | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	manager, err := stats.NewStatsManager(config) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error creating stats manager: %v\n", err) | ||||
| @@ -40,7 +40,7 @@ func main() { | ||||
| 	// DISK INFORMATION | ||||
| 	fmt.Println("\n1. DISK INFORMATION") | ||||
| 	fmt.Println("------------------") | ||||
| 	 | ||||
|  | ||||
| 	// Get all disk stats using the manager | ||||
| 	diskStats, err := manager.GetDiskStats() | ||||
| 	if err != nil { | ||||
| @@ -48,7 +48,7 @@ func main() { | ||||
| 	} else { | ||||
| 		fmt.Printf("Found %d disks:\n", len(diskStats.Disks)) | ||||
| 		for _, disk := range diskStats.Disks { | ||||
| 			fmt.Printf("  %s: %.1f GB total, %.1f GB free (%.1f%% used)\n",  | ||||
| 			fmt.Printf("  %s: %.1f GB total, %.1f GB free (%.1f%% used)\n", | ||||
| 				disk.Path, disk.Total, disk.Free, disk.UsedPercent) | ||||
| 		} | ||||
| 	} | ||||
| @@ -58,7 +58,7 @@ func main() { | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting root disk info: %v\n", err) | ||||
| 	} else { | ||||
| 		fmt.Printf("\nRoot Disk: %.1f GB total, %.1f GB free (%.1f%% used)\n",  | ||||
| 		fmt.Printf("\nRoot Disk: %.1f GB total, %.1f GB free (%.1f%% used)\n", | ||||
| 			rootDisk.Total, rootDisk.Free, rootDisk.UsedPercent) | ||||
| 	} | ||||
|  | ||||
| @@ -68,7 +68,7 @@ func main() { | ||||
| 	// SYSTEM INFORMATION | ||||
| 	fmt.Println("\n2. SYSTEM INFORMATION") | ||||
| 	fmt.Println("--------------------") | ||||
| 	 | ||||
|  | ||||
| 	// Get system info using the manager | ||||
| 	sysInfo, err := manager.GetSystemInfo() | ||||
| 	if err != nil { | ||||
| @@ -78,12 +78,12 @@ func main() { | ||||
| 		fmt.Printf("  Cores: %d\n", sysInfo.CPU.Cores) | ||||
| 		fmt.Printf("  Model: %s\n", sysInfo.CPU.ModelName) | ||||
| 		fmt.Printf("  Usage: %.1f%%\n", sysInfo.CPU.UsagePercent) | ||||
| 		 | ||||
|  | ||||
| 		fmt.Println("\nMemory Information:") | ||||
| 		fmt.Printf("  Total: %.1f GB\n", sysInfo.Memory.Total) | ||||
| 		fmt.Printf("  Used: %.1f GB (%.1f%%)\n", sysInfo.Memory.Used, sysInfo.Memory.UsedPercent) | ||||
| 		fmt.Printf("  Free: %.1f GB\n", sysInfo.Memory.Free) | ||||
| 		 | ||||
|  | ||||
| 		fmt.Println("\nNetwork Information:") | ||||
| 		fmt.Printf("  Upload Speed: %s\n", sysInfo.Network.UploadSpeed) | ||||
| 		fmt.Printf("  Download Speed: %s\n", sysInfo.Network.DownloadSpeed) | ||||
| @@ -98,18 +98,18 @@ func main() { | ||||
| 	// PROCESS INFORMATION | ||||
| 	fmt.Println("\n3. PROCESS INFORMATION") | ||||
| 	fmt.Println("---------------------") | ||||
| 	 | ||||
|  | ||||
| 	// Get process stats using the manager | ||||
| 	processStats, err := manager.GetProcessStats(5) // Get top 5 processes | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting process stats: %v\n", err) | ||||
| 	} else { | ||||
| 		fmt.Printf("Total processes: %d (showing top %d)\n",  | ||||
| 		fmt.Printf("Total processes: %d (showing top %d)\n", | ||||
| 			processStats.Total, len(processStats.Processes)) | ||||
| 		 | ||||
|  | ||||
| 		fmt.Println("\nTop Processes by CPU Usage:") | ||||
| 		for i, proc := range processStats.Processes { | ||||
| 			fmt.Printf("  %d. PID %d: %s (CPU: %.1f%%, Memory: %.1f MB)\n",  | ||||
| 			fmt.Printf("  %d. PID %d: %s (CPU: %.1f%%, Memory: %.1f MB)\n", | ||||
| 				i+1, proc.PID, proc.Name, proc.CPUPercent, proc.MemoryMB) | ||||
| 		} | ||||
| 	} | ||||
| @@ -128,7 +128,7 @@ func main() { | ||||
| 	// COMBINED STATS | ||||
| 	fmt.Println("\n4. COMBINED STATS FUNCTIONS") | ||||
| 	fmt.Println("--------------------------") | ||||
| 	 | ||||
|  | ||||
| 	// Hardware stats using the manager | ||||
| 	fmt.Println("\nHardware Stats:") | ||||
| 	hardwareStats := manager.GetHardwareStats() | ||||
| @@ -151,17 +151,17 @@ func main() { | ||||
| 	// Wait and measure network speed again | ||||
| 	fmt.Println("\nWaiting 2 seconds for another network speed measurement...") | ||||
| 	time.Sleep(2 * time.Second) | ||||
| 	 | ||||
|  | ||||
| 	// Get updated network speed using the manager | ||||
| 	updatedNetSpeed := manager.GetNetworkSpeedResult() | ||||
| 	fmt.Println("\nUpdated Network Speed:") | ||||
| 	fmt.Printf("  Upload: %s\n", updatedNetSpeed.UploadSpeed) | ||||
| 	fmt.Printf("  Download: %s\n", updatedNetSpeed.DownloadSpeed) | ||||
| 	 | ||||
|  | ||||
| 	// CACHE MANAGEMENT | ||||
| 	fmt.Println("\n5. CACHE MANAGEMENT") | ||||
| 	fmt.Println("------------------") | ||||
| 	 | ||||
|  | ||||
| 	// Force update of system stats | ||||
| 	fmt.Println("\nForcing update of system stats...") | ||||
| 	err = manager.ForceUpdate("system") | ||||
| @@ -170,7 +170,7 @@ func main() { | ||||
| 	} else { | ||||
| 		fmt.Println("System stats updated successfully") | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Get updated system info | ||||
| 	updatedSysInfo, err := manager.GetSystemInfo() | ||||
| 	if err != nil { | ||||
| @@ -178,7 +178,7 @@ func main() { | ||||
| 	} else { | ||||
| 		fmt.Println("\nUpdated CPU Usage: " + fmt.Sprintf("%.1f%%", updatedSysInfo.CPU.UsagePercent)) | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Clear cache for disk stats | ||||
| 	fmt.Println("\nClearing cache for disk stats...") | ||||
| 	err = manager.ClearCache("disk") | ||||
| @@ -187,7 +187,7 @@ func main() { | ||||
| 	} else { | ||||
| 		fmt.Println("Disk stats cache cleared successfully") | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	// Toggle debug mode | ||||
| 	fmt.Println("\nToggling debug mode (direct fetching without cache)...") | ||||
| 	manager.Debug = !manager.Debug | ||||
|   | ||||
		Reference in New Issue
	
	Block a user