123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- //go:build linux
- package diagnostic
- import (
- "context"
- "fmt"
- "os/exec"
- "strconv"
- "strings"
- )
- type SystemCollectorImpl struct {
- version string
- }
- func NewSystemCollectorImpl(
- version string,
- ) *SystemCollectorImpl {
- return &SystemCollectorImpl{
- version,
- }
- }
- func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, string, error) {
- memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
- fdInfo, fdInfoRaw, fdInfoErr := collectFileDescriptorInformation(ctx)
- disks, disksRaw, diskErr := collectDiskVolumeInformationUnix(ctx)
- osInfo, osInfoRaw, osInfoErr := collectOSInformationUnix(ctx)
- if memoryInfoErr != nil {
- raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
- return nil, raw, memoryInfoErr
- }
- if fdInfoErr != nil {
- raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
- return nil, raw, fdInfoErr
- }
- if diskErr != nil {
- raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
- return nil, raw, diskErr
- }
- if osInfoErr != nil {
- raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
- return nil, raw, osInfoErr
- }
- return NewSystemInformation(
- memoryInfo.MemoryMaximum,
- memoryInfo.MemoryCurrent,
- fdInfo.FileDescriptorMaximum,
- fdInfo.FileDescriptorCurrent,
- osInfo.OsSystem,
- osInfo.Name,
- osInfo.OsVersion,
- osInfo.OsRelease,
- osInfo.Architecture,
- collector.version,
- disks,
- ), "", nil
- }
- func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
- // This function relies on the output of `cat /proc/meminfo` to retrieve
- // memoryMax and memoryCurrent.
- // The expected output is in the format of `KEY VALUE UNIT`.
- const (
- memTotalPrefix = "MemTotal"
- memAvailablePrefix = "MemAvailable"
- )
- command := exec.CommandContext(ctx, "cat", "/proc/meminfo")
- stdout, err := command.Output()
- if err != nil {
- return nil, "", fmt.Errorf("error retrieving output from command '%s': %w", command.String(), err)
- }
- output := string(stdout)
- mapper := func(field string) (uint64, error) {
- field = strings.TrimRight(field, " kB")
- return strconv.ParseUint(field, 10, 64)
- }
- memoryInfo, err := ParseMemoryInformationFromKV(output, memTotalPrefix, memAvailablePrefix, mapper)
- if err != nil {
- return nil, output, err
- }
- // returning raw output in case other collected information
- // resulted in errors
- return memoryInfo, output, nil
- }
- func collectFileDescriptorInformation(ctx context.Context) (*FileDescriptorInformation, string, error) {
- // Command retrieved from https://docs.kernel.org/admin-guide/sysctl/fs.html#file-max-file-nr.
- // If the sysctl is not available the command with fail.
- command := exec.CommandContext(ctx, "sysctl", "-n", "fs.file-nr")
- stdout, err := command.Output()
- if err != nil {
- return nil, "", fmt.Errorf("error retrieving output from command '%s': %w", command.String(), err)
- }
- output := string(stdout)
- fileDescriptorInfo, err := ParseSysctlFileDescriptorInformation(output)
- if err != nil {
- return nil, output, err
- }
- // returning raw output in case other collected information
- // resulted in errors
- return fileDescriptorInfo, output, nil
- }
|