1) add-bpf-capability 2) Not so clean but for now it's okay to start with Co-authored-by: Harshavardhan Musanalli <harshavmb@gmail.com> Reviewed-on: #1
202 lines
5.4 KiB
Go
202 lines
5.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// SystemInfo represents basic system information
|
|
type SystemInfo struct {
|
|
Hostname string `json:"hostname"`
|
|
OS string `json:"os"`
|
|
Kernel string `json:"kernel"`
|
|
Architecture string `json:"architecture"`
|
|
CPUCores string `json:"cpu_cores"`
|
|
Memory string `json:"memory"`
|
|
Uptime string `json:"uptime"`
|
|
PrivateIPs string `json:"private_ips"`
|
|
LoadAverage string `json:"load_average"`
|
|
DiskUsage string `json:"disk_usage"`
|
|
}
|
|
|
|
// GatherSystemInfo collects basic system information
|
|
func GatherSystemInfo() *SystemInfo {
|
|
info := &SystemInfo{}
|
|
executor := NewCommandExecutor(5 * time.Second)
|
|
|
|
// Basic system info
|
|
if result := executor.Execute(Command{ID: "hostname", Command: "hostname"}); result.ExitCode == 0 {
|
|
info.Hostname = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "os", Command: "lsb_release -d 2>/dev/null | cut -f2 || cat /etc/os-release | grep PRETTY_NAME | cut -d'=' -f2 | tr -d '\"'"}); result.ExitCode == 0 {
|
|
info.OS = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "kernel", Command: "uname -r"}); result.ExitCode == 0 {
|
|
info.Kernel = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "arch", Command: "uname -m"}); result.ExitCode == 0 {
|
|
info.Architecture = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "cores", Command: "nproc"}); result.ExitCode == 0 {
|
|
info.CPUCores = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "memory", Command: "free -h | grep Mem | awk '{print $2}'"}); result.ExitCode == 0 {
|
|
info.Memory = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "uptime", Command: "uptime -p"}); result.ExitCode == 0 {
|
|
info.Uptime = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "load", Command: "uptime | awk -F'load average:' '{print $2}' | xargs"}); result.ExitCode == 0 {
|
|
info.LoadAverage = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
if result := executor.Execute(Command{ID: "disk", Command: "df -h / | tail -1 | awk '{print \"Root: \" $3 \"/\" $2 \" (\" $5 \" used)\"}'"}); result.ExitCode == 0 {
|
|
info.DiskUsage = strings.TrimSpace(result.Output)
|
|
}
|
|
|
|
// Get private IP addresses
|
|
info.PrivateIPs = getPrivateIPs()
|
|
|
|
return info
|
|
}
|
|
|
|
// getPrivateIPs returns private IP addresses
|
|
func getPrivateIPs() string {
|
|
var privateIPs []string
|
|
|
|
interfaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return "Unable to determine"
|
|
}
|
|
|
|
for _, iface := range interfaces {
|
|
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
|
continue // Skip down or loopback interfaces
|
|
}
|
|
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
|
if isPrivateIP(ipnet.IP) {
|
|
privateIPs = append(privateIPs, fmt.Sprintf("%s (%s)", ipnet.IP.String(), iface.Name))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(privateIPs) == 0 {
|
|
return "No private IPs found"
|
|
}
|
|
|
|
return strings.Join(privateIPs, ", ")
|
|
}
|
|
|
|
// isPrivateIP checks if an IP address is private
|
|
func isPrivateIP(ip net.IP) bool {
|
|
// RFC 1918 private address ranges
|
|
private := []string{
|
|
"10.0.0.0/8",
|
|
"172.16.0.0/12",
|
|
"192.168.0.0/16",
|
|
}
|
|
|
|
for _, cidr := range private {
|
|
_, subnet, _ := net.ParseCIDR(cidr)
|
|
if subnet.Contains(ip) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// FormatSystemInfoForPrompt formats system information for inclusion in diagnostic prompts
|
|
func FormatSystemInfoForPrompt(info *SystemInfo) string {
|
|
return fmt.Sprintf(`SYSTEM INFORMATION:
|
|
- Hostname: %s
|
|
- Operating System: %s
|
|
- Kernel Version: %s
|
|
- Architecture: %s
|
|
- CPU Cores: %s
|
|
- Total Memory: %s
|
|
- System Uptime: %s
|
|
- Current Load Average: %s
|
|
- Root Disk Usage: %s
|
|
- Private IP Addresses: %s
|
|
- Go Runtime: %s
|
|
|
|
ISSUE DESCRIPTION:`,
|
|
info.Hostname,
|
|
info.OS,
|
|
info.Kernel,
|
|
info.Architecture,
|
|
info.CPUCores,
|
|
info.Memory,
|
|
info.Uptime,
|
|
info.LoadAverage,
|
|
info.DiskUsage,
|
|
info.PrivateIPs,
|
|
runtime.Version())
|
|
}
|
|
|
|
// FormatSystemInfoWithEBPFForPrompt formats system information including eBPF capabilities
|
|
func FormatSystemInfoWithEBPFForPrompt(info *SystemInfo, ebpfManager EBPFManagerInterface) string {
|
|
baseInfo := FormatSystemInfoForPrompt(info)
|
|
|
|
if ebpfManager == nil {
|
|
return baseInfo + "\neBPF CAPABILITIES: Not available\n"
|
|
}
|
|
|
|
capabilities := ebpfManager.GetCapabilities()
|
|
summary := ebpfManager.GetSummary()
|
|
|
|
ebpfInfo := fmt.Sprintf(`
|
|
eBPF MONITORING CAPABILITIES:
|
|
- System Call Tracing: %v
|
|
- Network Activity Tracing: %v
|
|
- Process Monitoring: %v
|
|
- File System Monitoring: %v
|
|
- Performance Monitoring: %v
|
|
- Security Event Monitoring: %v
|
|
|
|
eBPF INTEGRATION GUIDE:
|
|
To request eBPF monitoring during diagnosis, include these fields in your JSON response:
|
|
{
|
|
"response_type": "diagnostic",
|
|
"reasoning": "explanation of why eBPF monitoring is needed",
|
|
"commands": [regular diagnostic commands],
|
|
"ebpf_capabilities": ["syscall_trace", "network_trace", "process_trace"],
|
|
"ebpf_duration_seconds": 15,
|
|
"ebpf_filters": {"pid": "process_id", "comm": "process_name", "path": "/specific/path"}
|
|
}
|
|
|
|
Available eBPF capabilities: %v
|
|
eBPF Status: %v
|
|
|
|
`,
|
|
capabilities["tracepoint"],
|
|
capabilities["kprobe"],
|
|
capabilities["kernel_support"],
|
|
capabilities["tracepoint"],
|
|
capabilities["kernel_support"],
|
|
capabilities["bpftrace_available"],
|
|
capabilities,
|
|
summary)
|
|
|
|
return baseInfo + ebpfInfo
|
|
}
|