Skip to content

Commit 2839784

Browse files
Add disk.pending_operations metric
1 parent d4053cc commit 2839784

File tree

7 files changed

+123
-10
lines changed

7 files changed

+123
-10
lines changed

receiver/hostmetricsreceiver/hostmetrics_receiver_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ var standardMetrics = []string{
4747
"system.memory.usage",
4848
"system.disk.io",
4949
"system.disk.ops",
50+
"system.disk.pending_operations",
5051
"system.disk.time",
5152
"system.filesystem.usage",
5253
"system.cpu.load_average.1m",

receiver/hostmetricsreceiver/internal/scraper/diskscraper/disk_metadata.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ var diskTimeDescriptor = func() pdata.MetricDescriptor {
6464
return descriptor
6565
}()
6666

67+
var diskPendingOperationsDescriptor = func() pdata.MetricDescriptor {
68+
descriptor := pdata.NewMetricDescriptor()
69+
descriptor.InitEmpty()
70+
descriptor.SetName("system.disk.pending_operations")
71+
descriptor.SetDescription("The queue size of pending I/O operations.")
72+
descriptor.SetUnit("1")
73+
descriptor.SetType(pdata.MetricTypeInt64)
74+
return descriptor
75+
}()
76+
6777
var diskMergedDescriptor = func() pdata.MetricDescriptor {
6878
descriptor := pdata.NewMetricDescriptor()
6979
descriptor.InitEmpty()

receiver/hostmetricsreceiver/internal/scraper/diskscraper/disk_scraper_others.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,12 @@ func (s *scraper) ScrapeMetrics(_ context.Context) (pdata.MetricSlice, error) {
9292
ioCounters = s.filterByDevice(ioCounters)
9393

9494
if len(ioCounters) > 0 {
95-
metrics.Resize(3 + systemSpecificMetricsLen)
95+
metrics.Resize(4 + systemSpecificMetricsLen)
9696
initializeDiskIOMetric(metrics.At(0), s.startTime, ioCounters)
9797
initializeDiskOpsMetric(metrics.At(1), s.startTime, ioCounters)
9898
initializeDiskTimeMetric(metrics.At(2), s.startTime, ioCounters)
99-
appendSystemSpecificMetrics(metrics, 3, s.startTime, ioCounters)
99+
initializeDiskPendingOperationsMetric(metrics.At(3), ioCounters)
100+
appendSystemSpecificMetrics(metrics, 4, s.startTime, ioCounters)
100101
}
101102

102103
return metrics, nil
@@ -144,6 +145,19 @@ func initializeDiskTimeMetric(metric pdata.Metric, startTime pdata.TimestampUnix
144145
}
145146
}
146147

148+
func initializeDiskPendingOperationsMetric(metric pdata.Metric, ioCounters map[string]disk.IOCountersStat) {
149+
diskPendingOperationsDescriptor.CopyTo(metric.MetricDescriptor())
150+
151+
idps := metric.Int64DataPoints()
152+
idps.Resize(len(ioCounters))
153+
154+
idx := 0
155+
for device, ioCounter := range ioCounters {
156+
initializeDiskPendingDataPoint(idps.At(idx), device, int64(ioCounter.IopsInProgress))
157+
idx++
158+
}
159+
}
160+
147161
func initializeInt64DataPoint(dataPoint pdata.Int64DataPoint, startTime pdata.TimestampUnixNano, deviceLabel string, directionLabel string, value int64) {
148162
labelsMap := dataPoint.LabelsMap()
149163
labelsMap.Insert(deviceLabelName, deviceLabel)
@@ -162,6 +176,13 @@ func initializeDoubleDataPoint(dataPoint pdata.DoubleDataPoint, startTime pdata.
162176
dataPoint.SetValue(value)
163177
}
164178

179+
func initializeDiskPendingDataPoint(dataPoint pdata.Int64DataPoint, deviceLabel string, value int64) {
180+
labelsMap := dataPoint.LabelsMap()
181+
labelsMap.Insert(deviceLabelName, deviceLabel)
182+
dataPoint.SetTimestamp(pdata.TimestampUnixNano(uint64(time.Now().UnixNano())))
183+
dataPoint.SetValue(value)
184+
}
185+
165186
func (s *scraper) filterByDevice(ioCounters map[string]disk.IOCountersStat) map[string]disk.IOCountersStat {
166187
if s.includeFS == nil && s.excludeFS == nil {
167188
return ioCounters

receiver/hostmetricsreceiver/internal/scraper/diskscraper/disk_scraper_others_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@ func TestScrapeMetrics_Others(t *testing.T) {
8888
assertInt64DiskMetricValid(t, metrics.At(0), diskIODescriptor, test.expectedStartTime)
8989
assertInt64DiskMetricValid(t, metrics.At(1), diskOpsDescriptor, test.expectedStartTime)
9090
assertDoubleDiskMetricValid(t, metrics.At(2), diskTimeDescriptor, test.expectedStartTime)
91+
assertDiskPendingOperationsMetricValid(t, metrics.At(3))
9192

9293
if runtime.GOOS == "linux" {
93-
assertInt64DiskMetricValid(t, metrics.At(3), diskMergedDescriptor, test.expectedStartTime)
94+
assertInt64DiskMetricValid(t, metrics.At(4), diskMergedDescriptor, test.expectedStartTime)
9495
}
9596
})
9697
}

receiver/hostmetricsreceiver/internal/scraper/diskscraper/disk_scraper_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,15 @@ func TestScrapeMetrics(t *testing.T) {
7979
return
8080
}
8181

82-
assert.GreaterOrEqual(t, metrics.Len(), 3)
82+
assert.GreaterOrEqual(t, metrics.Len(), 4)
8383

8484
assertInt64DiskMetricValid(t, metrics.At(0), diskIODescriptor, 0)
8585
assertInt64DiskMetricValid(t, metrics.At(1), diskOpsDescriptor, 0)
8686
assertDoubleDiskMetricValid(t, metrics.At(2), diskTimeDescriptor, 0)
87+
assertDiskPendingOperationsMetricValid(t, metrics.At(3))
8788

8889
if runtime.GOOS == "linux" {
89-
assertInt64DiskMetricValid(t, metrics.At(3), diskMergedDescriptor, 0)
90+
assertInt64DiskMetricValid(t, metrics.At(4), diskMergedDescriptor, 0)
9091
}
9192
})
9293
}
@@ -98,6 +99,7 @@ func assertInt64DiskMetricValid(t *testing.T, metric pdata.Metric, expectedDescr
9899
internal.AssertInt64MetricStartTimeEquals(t, metric, startTime)
99100
}
100101
assert.GreaterOrEqual(t, metric.Int64DataPoints().Len(), 2)
102+
internal.AssertInt64MetricLabelExists(t, metric, 0, deviceLabelName)
101103
internal.AssertInt64MetricLabelHasValue(t, metric, 0, directionLabelName, readDirectionLabelValue)
102104
internal.AssertInt64MetricLabelHasValue(t, metric, 1, directionLabelName, writeDirectionLabelValue)
103105
}
@@ -108,6 +110,13 @@ func assertDoubleDiskMetricValid(t *testing.T, metric pdata.Metric, expectedDesc
108110
internal.AssertInt64MetricStartTimeEquals(t, metric, startTime)
109111
}
110112
assert.GreaterOrEqual(t, metric.DoubleDataPoints().Len(), 2)
113+
internal.AssertDoubleMetricLabelExists(t, metric, 0, deviceLabelName)
111114
internal.AssertDoubleMetricLabelHasValue(t, metric, 0, directionLabelName, readDirectionLabelValue)
112115
internal.AssertDoubleMetricLabelHasValue(t, metric, metric.DoubleDataPoints().Len()-1, directionLabelName, writeDirectionLabelValue)
113116
}
117+
118+
func assertDiskPendingOperationsMetricValid(t *testing.T, metric pdata.Metric) {
119+
internal.AssertDescriptorEqual(t, diskPendingOperationsDescriptor, metric.MetricDescriptor())
120+
assert.GreaterOrEqual(t, metric.Int64DataPoints().Len(), 1)
121+
internal.AssertInt64MetricLabelExists(t, metric, 0, deviceLabelName)
122+
}

receiver/hostmetricsreceiver/internal/scraper/diskscraper/disk_scraper_windows.go

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ const (
3737
logicalAvgDiskSecsPerReadPath = `\LogicalDisk(*)\Avg. Disk sec/Read`
3838
logicalAvgDiskSecsPerWritePath = `\LogicalDisk(*)\Avg. Disk sec/Write`
3939

40-
// TODO
41-
// logicalAvgDiskQueueLengthPath = `\LogicalDisk(*)\Avg. Disk Queue Length`
40+
logicalDiskQueueLengthPath = `\LogicalDisk(*)\Current Disk Queue Length`
4241
)
4342

4443
// scraper for Disk Metrics
@@ -53,9 +52,9 @@ type scraper struct {
5352
diskWriteBytesPerSecCounter pdh.PerfCounterScraper
5453
diskReadsPerSecCounter pdh.PerfCounterScraper
5554
diskWritesPerSecCounter pdh.PerfCounterScraper
56-
57-
avgDiskSecsPerReadCounter pdh.PerfCounterScraper
58-
avgDiskSecsPerWriteCounter pdh.PerfCounterScraper
55+
avgDiskSecsPerReadCounter pdh.PerfCounterScraper
56+
avgDiskSecsPerWriteCounter pdh.PerfCounterScraper
57+
diskQueueLengthCounter pdh.PerfCounterScraper
5958

6059
cumulativeDiskIO cumulativeDiskValues
6160
cumulativeDiskOps cumulativeDiskValues
@@ -144,6 +143,11 @@ func (s *scraper) Initialize(_ context.Context) error {
144143
return err
145144
}
146145

146+
s.diskQueueLengthCounter, err = pdh.NewPerfCounter(logicalDiskQueueLengthPath, true)
147+
if err != nil {
148+
return err
149+
}
150+
147151
return nil
148152
}
149153

@@ -187,6 +191,12 @@ func (s *scraper) Close(_ context.Context) error {
187191
}
188192
}
189193

194+
if s.diskQueueLengthCounter != nil && !reflect.ValueOf(s.diskQueueLengthCounter).IsNil() {
195+
if err := s.diskQueueLengthCounter.Close(); err != nil {
196+
errors = append(errors, err)
197+
}
198+
}
199+
190200
return componenterror.CombineErrors(errors)
191201
}
192202

@@ -210,6 +220,11 @@ func (s *scraper) ScrapeMetrics(_ context.Context) (pdata.MetricSlice, error) {
210220
errors = append(errors, err)
211221
}
212222

223+
err = s.scrapeAndAppendDiskPendingOperationsMetric(metrics)
224+
if err != nil {
225+
errors = append(errors, err)
226+
}
227+
213228
if len(errors) > 0 {
214229
return metrics, componenterror.CombineErrors(errors)
215230
}
@@ -316,6 +331,23 @@ func (s *scraper) scrapeAndAppendDiskOpsMetric(metrics pdata.MetricSlice, durati
316331
return nil
317332
}
318333

334+
func (s *scraper) scrapeAndAppendDiskPendingOperationsMetric(metrics pdata.MetricSlice) error {
335+
diskQueueLengthValues, err := s.diskQueueLengthCounter.ScrapeData()
336+
if err != nil {
337+
return err
338+
}
339+
340+
filteredDiskQueueLengthValues := s.filterByDevice(diskQueueLengthValues)
341+
if len(filteredDiskQueueLengthValues) == 0 {
342+
return nil
343+
}
344+
345+
idx := metrics.Len()
346+
metrics.Resize(idx + 1)
347+
initializeDiskPendingOperationsMetric(metrics.At(idx), filteredDiskQueueLengthValues)
348+
return nil
349+
}
350+
319351
func initializeDiskInt64Metric(metric pdata.Metric, descriptor pdata.MetricDescriptor, startTime pdata.TimestampUnixNano, ops cumulativeDiskValues) {
320352
descriptor.CopyTo(metric.MetricDescriptor())
321353

@@ -344,6 +376,17 @@ func initializeDiskDoubleMetric(metric pdata.Metric, descriptor pdata.MetricDesc
344376
}
345377
}
346378

379+
func initializeDiskPendingOperationsMetric(metric pdata.Metric, avgDiskQueueLengthValues []win_perf_counters.CounterValue) {
380+
diskPendingOperationsDescriptor.CopyTo(metric.MetricDescriptor())
381+
382+
idps := metric.Int64DataPoints()
383+
idps.Resize(len(avgDiskQueueLengthValues))
384+
385+
for idx, avgDiskQueueLengthValue := range avgDiskQueueLengthValues {
386+
initializeDiskPendingDataPoint(idps.At(idx), avgDiskQueueLengthValue.InstanceName, int64(avgDiskQueueLengthValue.Value))
387+
}
388+
}
389+
347390
func initializeInt64DataPoint(dataPoint pdata.Int64DataPoint, startTime pdata.TimestampUnixNano, deviceLabel string, directionLabel string, value int64) {
348391
labelsMap := dataPoint.LabelsMap()
349392
labelsMap.Insert(deviceLabelName, deviceLabel)
@@ -362,6 +405,27 @@ func initializeDoubleDataPoint(dataPoint pdata.DoubleDataPoint, startTime pdata.
362405
dataPoint.SetValue(value)
363406
}
364407

408+
func initializeDiskPendingDataPoint(dataPoint pdata.Int64DataPoint, deviceLabel string, value int64) {
409+
labelsMap := dataPoint.LabelsMap()
410+
labelsMap.Insert(deviceLabelName, deviceLabel)
411+
dataPoint.SetTimestamp(pdata.TimestampUnixNano(uint64(time.Now().UnixNano())))
412+
dataPoint.SetValue(value)
413+
}
414+
415+
func (s *scraper) filterByDevice(values []win_perf_counters.CounterValue) []win_perf_counters.CounterValue {
416+
if s.includeFS == nil && s.excludeFS == nil {
417+
return values
418+
}
419+
420+
filteredValues := make([]win_perf_counters.CounterValue, 0, len(values))
421+
for _, value := range values {
422+
if s.includeDevice(value.InstanceName) {
423+
filteredValues = append(filteredValues, value)
424+
}
425+
}
426+
return filteredValues
427+
}
428+
365429
func (s *scraper) includeDevice(deviceName string) bool {
366430
return (s.includeFS == nil || s.includeFS.Matches(deviceName)) &&
367431
(s.excludeFS == nil || !s.excludeFS.Matches(deviceName))

receiver/hostmetricsreceiver/internal/scraper/diskscraper/disk_scraper_windows_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func TestScrapeMetrics_Error(t *testing.T) {
3636
diskWritesPerSecCounterReturnValue interface{}
3737
avgDiskSecsPerReadCounterReturnValue interface{}
3838
avgDiskSecsPerWriteCounterReturnValue interface{}
39+
diskQueueLengthCounterReturnValue interface{}
3940
expectedErr string
4041
}
4142

@@ -70,6 +71,11 @@ func TestScrapeMetrics_Error(t *testing.T) {
7071
avgDiskSecsPerWriteCounterReturnValue: errors.New("err1"),
7172
expectedErr: "err1",
7273
},
74+
{
75+
name: "avgDiskQueueLengthError",
76+
diskQueueLengthCounterReturnValue: errors.New("err1"),
77+
expectedErr: "err1",
78+
},
7379
}
7480

7581
for _, test := range testCases {
@@ -87,6 +93,7 @@ func TestScrapeMetrics_Error(t *testing.T) {
8793
scraper.diskWritesPerSecCounter = pdh.NewMockPerfCounter(test.diskWritesPerSecCounterReturnValue)
8894
scraper.avgDiskSecsPerReadCounter = pdh.NewMockPerfCounter(test.avgDiskSecsPerReadCounterReturnValue)
8995
scraper.avgDiskSecsPerWriteCounter = pdh.NewMockPerfCounter(test.avgDiskSecsPerWriteCounterReturnValue)
96+
scraper.diskQueueLengthCounter = pdh.NewMockPerfCounter(test.diskQueueLengthCounterReturnValue)
9097

9198
_, err = scraper.ScrapeMetrics(context.Background())
9299
assert.EqualError(t, err, test.expectedErr)

0 commit comments

Comments
 (0)