--- /dev/null 2026-04-17 05:15:00.245562212 -0500 +++ ./vendor/github.com/elastic/elastic-agent-system-metrics/metric/system/diskio/diskstat_aix_cgo.go 2026-04-17 04:44:29.000000000 -0500 @@ -0,0 +1,58 @@ +//go:build aix && cgo +// +build aix,cgo + +package diskio + +/* +#cgo CFLAGS: -D_ALL_SOURCE -D_LARGE_FILES -D_THREAD_SAFE +#cgo LDFLAGS: -lperfstat +#include +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +// perfstatDisks returns a map of disk name -> perfstat_disk_t +// This function is AIX + CGO only. +func perfstatDisks() (map[string]C.perfstat_disk_t, error) { + var first C.perfstat_id_t + first.name[0] = 0 + + // First call: get number of disks + count := C.perfstat_disk( + nil, + nil, + C.sizeof_perfstat_disk_t, + 0, + ) + if count <= 0 { + return nil, errors.New("perfstat_disk returned no disks") + } + + // Allocate buffer + disks := make([]C.perfstat_disk_t, count) + + // Second call: fill buffer + ret := C.perfstat_disk( + &first, + (*C.perfstat_disk_t)(unsafe.Pointer(&disks[0])), + C.sizeof_perfstat_disk_t, + count, + ) + if ret <= 0 { + return nil, errors.New("perfstat_disk failed") + } + + // Convert to Go map + out := make(map[string]C.perfstat_disk_t, ret) + for i := 0; i < int(ret); i++ { + d := disks[i] + name := C.GoString(&d.name[0]) + out[name] = d + } + + return out, nil +} --- /dev/null 2026-04-17 05:56:32.436073929 -0500 +++ ./vendor/github.com/elastic/elastic-agent-system-metrics/metric/system/diskio/diskstat_aix.go 2026-04-17 05:56:05.101193182 -0500 @@ -0,0 +1,115 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//go:build aix +// +build aix + +package diskio + +import ( + "errors" + + "github.com/shirou/gopsutil/v4/disk" + "github.com/elastic/elastic-agent-libs/logp" +) + +import "time" +import "slices" + +// IOStat carries disk statistics for all devices +type IOStat struct { + lastDiskIOCounters map[string]disk.IOCountersStat + lastSampleTime time.Time //nolint: ununsed in windows, linux +} + +// NewDiskIOStat :init DiskIOStat object. +func NewDiskIOStat() *IOStat { + return &IOStat{ + lastDiskIOCounters: map[string]disk.IOCountersStat{}, + } +} + +// OpenSampling stub for linux implementation. +func (stat *IOStat) OpenSampling() error { + disks, err := perfstatDisks() + if err != nil { + return err + } + + stat.lastDiskIOCounters = make(map[string]disk.IOCountersStat) + + for name, d := range disks { + stat.lastDiskIOCounters[name] = disk.IOCountersStat{ + ReadBytes: uint64(d.rblks) * uint64(d.bsize), + WriteBytes: uint64(d.wblks) * uint64(d.bsize), + } + } + stat.lastSampleTime = time.Now() + return nil +} + +// CalcIOStatistics stub for linux implementation. +func (stat *IOStat) CalcIOStatistics(counter disk.IOCountersStat) (IOMetric, error) { + + last, ok := stat.lastDiskIOCounters[counter.Name] + if !ok { + return IOMetric{}, errors.New("no previous sample") + } + + now := time.Now() + elapsed := now.Sub(stat.lastSampleTime).Seconds() + if elapsed <= 0 { + return IOMetric{}, errors.New("invalid sample interval") + } + + metric := IOMetric{ + ReadBytesPerSec: float64(counter.ReadBytes-last.ReadBytes) / elapsed, + WriteBytesPerSec: float64(counter.WriteBytes-last.WriteBytes) / elapsed, + } + + // update baseline + stat.lastDiskIOCounters[counter.Name] = counter + stat.lastSampleTime = now + + return metric, nil +} + +// CloseSampling stub for linux implementation. +func (stat *IOStat) CloseSampling() {} + +// IOCounters should map functionality to disk package for linux os. +func IOCounters(_ *logp.Logger, names ...string) (map[string]disk.IOCountersStat, error) { + disks, err := perfstatDisks() + if err != nil { + return nil, err + } + + out := make(map[string]disk.IOCountersStat) + for name, d := range disks { + if len(names) > 0 && slices.Contains(names, name) { + continue + } + + out[name] = disk.IOCountersStat{ + Name: name, + ReadBytes: uint64(d.rblks) * uint64(d.bsize), + WriteBytes: uint64(d.wblks) * uint64(d.bsize), + IoTime: uint64(d.time), + } + } + return out, nil +}