freebsd-ports/net/cloudflared/files/patch-diagnostic_system__co...

174 lines
4.6 KiB
Go

--- /dev/null 2024-01-01 00:00:00 UTC
+++ diagnostic/system_collector_freebsd.go
@@ -0,0 +1,170 @@
+//go:build freebsd
+
+package diagnostic
+
+import (
+ "context"
+ "fmt"
+ "os/exec"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+type SystemCollectorImpl struct {
+ version string
+}
+
+func NewSystemCollectorImpl(
+ version string,
+) *SystemCollectorImpl {
+ return &SystemCollectorImpl{
+ version,
+ }
+}
+
+func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, error) {
+ memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
+ fdInfo, fdInfoRaw, fdInfoErr := collectFileDescriptorInformation(ctx)
+ disks, disksRaw, diskErr := collectDiskVolumeInformationUnix(ctx)
+ osInfo, osInfoRaw, osInfoErr := collectOSInformationUnix(ctx)
+
+ var memoryMaximum, memoryCurrent, fileDescriptorMaximum, fileDescriptorCurrent uint64
+ var osSystem, name, osVersion, osRelease, architecture string
+ gerror := SystemInformationGeneralError{}
+
+ if memoryInfoErr != nil {
+ gerror.MemoryInformationError = SystemInformationError{
+ Err: memoryInfoErr,
+ RawInfo: memoryInfoRaw,
+ }
+ } else {
+ memoryMaximum = memoryInfo.MemoryMaximum
+ memoryCurrent = memoryInfo.MemoryCurrent
+ }
+
+ if fdInfoErr != nil {
+ gerror.FileDescriptorsInformationError = SystemInformationError{
+ Err: fdInfoErr,
+ RawInfo: fdInfoRaw,
+ }
+ } else {
+ fileDescriptorMaximum = fdInfo.FileDescriptorMaximum
+ fileDescriptorCurrent = fdInfo.FileDescriptorCurrent
+ }
+
+ if diskErr != nil {
+ gerror.DiskVolumeInformationError = SystemInformationError{
+ Err: diskErr,
+ RawInfo: disksRaw,
+ }
+ }
+
+ if osInfoErr != nil {
+ gerror.OperatingSystemInformationError = SystemInformationError{
+ Err: osInfoErr,
+ RawInfo: osInfoRaw,
+ }
+ } else {
+ osSystem = osInfo.OsSystem
+ name = osInfo.Name
+ osVersion = osInfo.OsVersion
+ osRelease = osInfo.OsRelease
+ architecture = osInfo.Architecture
+ }
+
+ cloudflaredVersion := collector.version
+ info := NewSystemInformation(
+ memoryMaximum,
+ memoryCurrent,
+ fileDescriptorMaximum,
+ fileDescriptorCurrent,
+ osSystem,
+ name,
+ osVersion,
+ osRelease,
+ architecture,
+ cloudflaredVersion,
+ runtime.Version(),
+ runtime.GOARCH,
+ disks,
+ )
+
+ return info, gerror
+}
+
+func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
+ // Use sysctl to get memory information on FreeBSD
+ command := exec.CommandContext(ctx, "sysctl", "-n", "hw.physmem", "vm.stats.vm.v_free_count", "hw.pagesize")
+
+ stdout, err := command.Output()
+ if err != nil {
+ return nil, "", fmt.Errorf("error retrieving output from command '%s': %w", command.String(), err)
+ }
+
+ output := string(stdout)
+ lines := strings.Split(strings.TrimSpace(output), "\n")
+
+ if len(lines) < 3 {
+ return nil, output, fmt.Errorf("unexpected sysctl output format")
+ }
+
+ physmem, err := strconv.ParseUint(lines[0], 10, 64)
+ if err != nil {
+ return nil, output, fmt.Errorf("error parsing physmem: %w", err)
+ }
+
+ freePages, err := strconv.ParseUint(lines[1], 10, 64)
+ if err != nil {
+ return nil, output, fmt.Errorf("error parsing free pages: %w", err)
+ }
+
+ pageSize, err := strconv.ParseUint(lines[2], 10, 64)
+ if err != nil {
+ return nil, output, fmt.Errorf("error parsing page size: %w", err)
+ }
+
+ memoryMaximum := physmem / 1024 // Convert to KB
+ memoryCurrent := (freePages * pageSize) / 1024 // Convert to KB
+
+ memoryInfo := &MemoryInformation{
+ MemoryMaximum: memoryMaximum,
+ MemoryCurrent: memoryCurrent,
+ }
+
+ return memoryInfo, output, nil
+}
+
+func collectFileDescriptorInformation(ctx context.Context) (*FileDescriptorInformation, string, error) {
+ // Use sysctl to get file descriptor limits on FreeBSD
+ command := exec.CommandContext(ctx, "sysctl", "-n", "kern.maxfiles", "kern.openfiles")
+
+ stdout, err := command.Output()
+ if err != nil {
+ return nil, "", fmt.Errorf("error retrieving output from command '%s': %w", command.String(), err)
+ }
+
+ output := string(stdout)
+ lines := strings.Split(strings.TrimSpace(output), "\n")
+
+ if len(lines) < 2 {
+ return nil, output, fmt.Errorf("unexpected sysctl output format")
+ }
+
+ maxFiles, err := strconv.ParseUint(lines[0], 10, 64)
+ if err != nil {
+ return nil, output, fmt.Errorf("error parsing maxfiles: %w", err)
+ }
+
+ openFiles, err := strconv.ParseUint(lines[1], 10, 64)
+ if err != nil {
+ return nil, output, fmt.Errorf("error parsing openfiles: %w", err)
+ }
+
+ fdInfo := &FileDescriptorInformation{
+ FileDescriptorMaximum: maxFiles,
+ FileDescriptorCurrent: openFiles,
+ }
+
+ return fdInfo, output, nil
+}