| // Copyright The Prometheus Authors |
| // Licensed 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. |
| |
| package xfs_test |
| |
| import ( |
| "strings" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| |
| "github.com/prometheus/procfs/xfs" |
| ) |
| |
| func TestParseStats(t *testing.T) { |
| tests := []struct { |
| name string |
| s string |
| fs bool |
| stats *xfs.Stats |
| invalid bool |
| }{ |
| { |
| name: "empty file OK", |
| }, |
| { |
| name: "short or empty lines and unknown labels ignored", |
| s: "one\n\ntwo 1 2 3\n", |
| stats: &xfs.Stats{}, |
| }, |
| { |
| name: "bad uint32", |
| s: "extent_alloc XXX", |
| invalid: true, |
| }, |
| { |
| name: "bad uint64", |
| s: "xpc XXX", |
| invalid: true, |
| }, |
| { |
| name: "extent_alloc bad", |
| s: "extent_alloc 1", |
| invalid: true, |
| }, |
| { |
| name: "extent_alloc OK", |
| s: "extent_alloc 1 2 3 4", |
| stats: &xfs.Stats{ |
| ExtentAllocation: xfs.ExtentAllocationStats{ |
| ExtentsAllocated: 1, |
| BlocksAllocated: 2, |
| ExtentsFreed: 3, |
| BlocksFreed: 4, |
| }, |
| }, |
| }, |
| { |
| name: "abt bad", |
| s: "abt 1", |
| invalid: true, |
| }, |
| { |
| name: "abt OK", |
| s: "abt 1 2 3 4", |
| stats: &xfs.Stats{ |
| AllocationBTree: xfs.BTreeStats{ |
| Lookups: 1, |
| Compares: 2, |
| RecordsInserted: 3, |
| RecordsDeleted: 4, |
| }, |
| }, |
| }, |
| { |
| name: "blk_map bad", |
| s: "blk_map 1", |
| invalid: true, |
| }, |
| { |
| name: "blk_map OK", |
| s: "blk_map 1 2 3 4 5 6 7", |
| stats: &xfs.Stats{ |
| BlockMapping: xfs.BlockMappingStats{ |
| Reads: 1, |
| Writes: 2, |
| Unmaps: 3, |
| ExtentListInsertions: 4, |
| ExtentListDeletions: 5, |
| ExtentListLookups: 6, |
| ExtentListCompares: 7, |
| }, |
| }, |
| }, |
| { |
| name: "bmbt bad", |
| s: "bmbt 1", |
| invalid: true, |
| }, |
| { |
| name: "bmbt OK", |
| s: "bmbt 1 2 3 4", |
| stats: &xfs.Stats{ |
| BlockMapBTree: xfs.BTreeStats{ |
| Lookups: 1, |
| Compares: 2, |
| RecordsInserted: 3, |
| RecordsDeleted: 4, |
| }, |
| }, |
| }, |
| { |
| name: "dir bad", |
| s: "dir 1", |
| invalid: true, |
| }, |
| { |
| name: "dir OK", |
| s: "dir 1 2 3 4", |
| stats: &xfs.Stats{ |
| DirectoryOperation: xfs.DirectoryOperationStats{ |
| Lookups: 1, |
| Creates: 2, |
| Removes: 3, |
| Getdents: 4, |
| }, |
| }, |
| }, |
| { |
| name: "trans bad", |
| s: "trans 1", |
| invalid: true, |
| }, |
| { |
| name: "trans OK", |
| s: "trans 1 2 3", |
| stats: &xfs.Stats{ |
| Transaction: xfs.TransactionStats{ |
| Sync: 1, |
| Async: 2, |
| Empty: 3, |
| }, |
| }, |
| }, |
| { |
| name: "ig bad", |
| s: "ig 1", |
| invalid: true, |
| }, |
| { |
| name: "ig OK", |
| s: "ig 1 2 3 4 5 6 7", |
| stats: &xfs.Stats{ |
| InodeOperation: xfs.InodeOperationStats{ |
| Attempts: 1, |
| Found: 2, |
| Recycle: 3, |
| Missed: 4, |
| Duplicate: 5, |
| Reclaims: 6, |
| AttributeChange: 7, |
| }, |
| }, |
| }, |
| { |
| name: "log bad", |
| s: "log 1", |
| invalid: true, |
| }, |
| { |
| name: "log OK", |
| s: "log 1 2 3 4 5", |
| stats: &xfs.Stats{ |
| LogOperation: xfs.LogOperationStats{ |
| Writes: 1, |
| Blocks: 2, |
| NoInternalBuffers: 3, |
| Force: 4, |
| ForceSleep: 5, |
| }, |
| }, |
| }, |
| { |
| name: "rw bad", |
| s: "rw 1", |
| invalid: true, |
| }, |
| { |
| name: "rw OK", |
| s: "rw 1 2", |
| stats: &xfs.Stats{ |
| ReadWrite: xfs.ReadWriteStats{ |
| Write: 1, |
| Read: 2, |
| }, |
| }, |
| }, |
| { |
| name: "attr bad", |
| s: "attr 1", |
| invalid: true, |
| }, |
| { |
| name: "attr OK", |
| s: "attr 1 2 3 4", |
| stats: &xfs.Stats{ |
| AttributeOperation: xfs.AttributeOperationStats{ |
| Get: 1, |
| Set: 2, |
| Remove: 3, |
| List: 4, |
| }, |
| }, |
| }, |
| { |
| name: "icluster bad", |
| s: "icluster 1", |
| invalid: true, |
| }, |
| { |
| name: "icluster OK", |
| s: "icluster 1 2 3", |
| stats: &xfs.Stats{ |
| InodeClustering: xfs.InodeClusteringStats{ |
| Iflush: 1, |
| Flush: 2, |
| FlushInode: 3, |
| }, |
| }, |
| }, |
| { |
| name: "vnodes bad", |
| s: "vnodes 1", |
| invalid: true, |
| }, |
| { |
| name: "vnodes (missing free) OK", |
| s: "vnodes 1 2 3 4 5 6 7", |
| stats: &xfs.Stats{ |
| Vnode: xfs.VnodeStats{ |
| Active: 1, |
| Allocate: 2, |
| Get: 3, |
| Hold: 4, |
| Release: 5, |
| Reclaim: 6, |
| Remove: 7, |
| }, |
| }, |
| }, |
| { |
| name: "vnodes (with free) OK", |
| s: "vnodes 1 2 3 4 5 6 7 8", |
| stats: &xfs.Stats{ |
| Vnode: xfs.VnodeStats{ |
| Active: 1, |
| Allocate: 2, |
| Get: 3, |
| Hold: 4, |
| Release: 5, |
| Reclaim: 6, |
| Remove: 7, |
| Free: 8, |
| }, |
| }, |
| }, |
| { |
| name: "buf bad", |
| s: "buf 1", |
| invalid: true, |
| }, |
| { |
| name: "buf OK", |
| s: "buf 1 2 3 4 5 6 7 8 9", |
| stats: &xfs.Stats{ |
| Buffer: xfs.BufferStats{ |
| Get: 1, |
| Create: 2, |
| GetLocked: 3, |
| GetLockedWaited: 4, |
| BusyLocked: 5, |
| MissLocked: 6, |
| PageRetries: 7, |
| PageFound: 8, |
| GetRead: 9, |
| }, |
| }, |
| }, |
| { |
| name: "xpc bad", |
| s: "xpc 1", |
| invalid: true, |
| }, |
| { |
| name: "xpc OK", |
| s: "xpc 1 2 3", |
| stats: &xfs.Stats{ |
| ExtendedPrecision: xfs.ExtendedPrecisionStats{ |
| FlushBytes: 1, |
| WriteBytes: 2, |
| ReadBytes: 3, |
| }, |
| }, |
| }, |
| { |
| name: "xstrat bad", |
| s: "xstrat 1", |
| invalid: true, |
| }, |
| { |
| name: "xstrat OK", |
| s: "xstrat 1 2", |
| stats: &xfs.Stats{ |
| Xstrat: xfs.XstratStats{ |
| Quick: 1, |
| Split: 2, |
| }, |
| }, |
| }, |
| { |
| name: "push_ail bad", |
| s: "push_ail 1 2 3 4 5", |
| invalid: true, |
| }, |
| { |
| name: "push_ail OK", |
| s: "push_ail 1 2 3 4 5 6 7 8 9 10", |
| stats: &xfs.Stats{ |
| PushAil: xfs.PushAilStats{ |
| TryLogspace: 1, |
| SleepLogspace: 2, |
| Pushes: 3, |
| Success: 4, |
| PushBuf: 5, |
| Pinned: 6, |
| Locked: 7, |
| Flushing: 8, |
| Restarts: 9, |
| Flush: 10, |
| }, |
| }, |
| }, |
| { |
| name: "debug bad", |
| s: "debug 1 2", |
| invalid: true, |
| }, |
| { |
| name: "debug OK", |
| s: "debug 1", |
| stats: &xfs.Stats{ |
| Debug: xfs.DebugStats{ |
| Enabled: 1, |
| }, |
| }, |
| }, |
| { |
| name: "qm bad", |
| s: "qm 1 2 3 4 5 6 7", |
| invalid: true, |
| }, |
| { |
| name: "qm bad", |
| s: "qm 1 2 3 4 5 6 7 8 9 10", |
| invalid: true, |
| }, |
| { |
| name: "qm OK", |
| s: "qm 1 2 3 4 5 6 7 8", |
| stats: &xfs.Stats{ |
| QuotaManager: xfs.QuotaManagerStats{ |
| Reclaims: 1, |
| ReclaimMisses: 2, |
| DquoteDups: 3, |
| CacheMisses: 4, |
| CacheHits: 5, |
| Wants: 6, |
| ShakeReclaims: 7, |
| InactReclaims: 8, |
| }, |
| }, |
| }, |
| { |
| name: "qm OK", |
| s: "qm 1 2 3 4 5 6 7 8 9", |
| stats: &xfs.Stats{ |
| QuotaManager: xfs.QuotaManagerStats{ |
| Reclaims: 1, |
| ReclaimMisses: 2, |
| DquoteDups: 3, |
| CacheMisses: 4, |
| CacheHits: 5, |
| Wants: 6, |
| ShakeReclaims: 7, |
| InactReclaims: 8, |
| Unused: 9, |
| }, |
| }, |
| }, |
| { |
| name: "abtb2 bad", |
| s: "abtb2 1 2 3 4 5 6", |
| invalid: true, |
| }, |
| { |
| name: "abtb2 OK", |
| s: "abtb2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15", |
| stats: &xfs.Stats{ |
| BtreeAllocBlocks2: xfs.BtreeAllocBlocks2Stats{ |
| Lookup: 1, |
| Compare: 2, |
| Insrec: 3, |
| Delrec: 4, |
| NewRoot: 5, |
| KillRoot: 6, |
| Increment: 7, |
| Decrement: 8, |
| Lshift: 9, |
| Rshift: 10, |
| Split: 11, |
| Join: 12, |
| Alloc: 13, |
| Free: 14, |
| Moves: 15, |
| }, |
| }, |
| }, |
| { |
| name: "abtc2 bad", |
| s: "abtc2 1 2 3 4 5 6", |
| invalid: true, |
| }, |
| { |
| name: "abtc2 OK", |
| s: "abtc2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15", |
| stats: &xfs.Stats{ |
| BtreeAllocContig2: xfs.BtreeAllocContig2Stats{ |
| Lookup: 1, |
| Compare: 2, |
| Insrec: 3, |
| Delrec: 4, |
| NewRoot: 5, |
| KillRoot: 6, |
| Increment: 7, |
| Decrement: 8, |
| Lshift: 9, |
| Rshift: 10, |
| Split: 11, |
| Join: 12, |
| Alloc: 13, |
| Free: 14, |
| Moves: 15, |
| }, |
| }, |
| }, |
| { |
| name: "bmbt2 bad", |
| s: "bmbt2 1 2 3 4 5 6", |
| invalid: true, |
| }, |
| { |
| name: "bmbt2 OK", |
| s: "bmbt2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15", |
| stats: &xfs.Stats{ |
| BtreeBlockMap2: xfs.BtreeBlockMap2Stats{ |
| Lookup: 1, |
| Compare: 2, |
| Insrec: 3, |
| Delrec: 4, |
| NewRoot: 5, |
| KillRoot: 6, |
| Increment: 7, |
| Decrement: 8, |
| Lshift: 9, |
| Rshift: 10, |
| Split: 11, |
| Join: 12, |
| Alloc: 13, |
| Free: 14, |
| Moves: 15, |
| }, |
| }, |
| }, |
| { |
| name: "ibt2 bad", |
| s: "ibt2 1 2 3 4 5 6", |
| invalid: true, |
| }, |
| { |
| name: "ibt2 OK", |
| s: "ibt2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15", |
| stats: &xfs.Stats{ |
| BtreeInode2: xfs.BtreeInode2Stats{ |
| Lookup: 1, |
| Compare: 2, |
| Insrec: 3, |
| Delrec: 4, |
| NewRoot: 5, |
| KillRoot: 6, |
| Increment: 7, |
| Decrement: 8, |
| Lshift: 9, |
| Rshift: 10, |
| Split: 11, |
| Join: 12, |
| Alloc: 13, |
| Free: 14, |
| Moves: 15, |
| }, |
| }, |
| }, |
| { |
| name: "fixtures OK", |
| fs: true, |
| stats: &xfs.Stats{ |
| ExtentAllocation: xfs.ExtentAllocationStats{ |
| ExtentsAllocated: 92447, |
| BlocksAllocated: 97589, |
| ExtentsFreed: 92448, |
| BlocksFreed: 93751, |
| }, |
| AllocationBTree: xfs.BTreeStats{ |
| Lookups: 0, |
| Compares: 0, |
| RecordsInserted: 0, |
| RecordsDeleted: 0, |
| }, |
| BlockMapping: xfs.BlockMappingStats{ |
| Reads: 1767055, |
| Writes: 188820, |
| Unmaps: 184891, |
| ExtentListInsertions: 92447, |
| ExtentListDeletions: 92448, |
| ExtentListLookups: 2140766, |
| ExtentListCompares: 0, |
| }, |
| BlockMapBTree: xfs.BTreeStats{ |
| Lookups: 0, |
| Compares: 0, |
| RecordsInserted: 0, |
| RecordsDeleted: 0, |
| }, |
| DirectoryOperation: xfs.DirectoryOperationStats{ |
| Lookups: 185039, |
| Creates: 92447, |
| Removes: 92444, |
| Getdents: 136422, |
| }, |
| Transaction: xfs.TransactionStats{ |
| Sync: 706, |
| Async: 944304, |
| Empty: 0, |
| }, |
| InodeOperation: xfs.InodeOperationStats{ |
| Attempts: 185045, |
| Found: 58807, |
| Recycle: 0, |
| Missed: 126238, |
| Duplicate: 0, |
| Reclaims: 33637, |
| AttributeChange: 22, |
| }, |
| LogOperation: xfs.LogOperationStats{ |
| Writes: 2883, |
| Blocks: 113448, |
| NoInternalBuffers: 9, |
| Force: 17360, |
| ForceSleep: 739, |
| }, |
| ReadWrite: xfs.ReadWriteStats{ |
| Write: 107739, |
| Read: 94045, |
| }, |
| AttributeOperation: xfs.AttributeOperationStats{ |
| Get: 4, |
| Set: 0, |
| Remove: 0, |
| List: 0, |
| }, |
| InodeClustering: xfs.InodeClusteringStats{ |
| Iflush: 8677, |
| Flush: 7849, |
| FlushInode: 135802, |
| }, |
| Vnode: xfs.VnodeStats{ |
| Active: 92601, |
| Allocate: 0, |
| Get: 0, |
| Hold: 0, |
| Release: 92444, |
| Reclaim: 92444, |
| Remove: 92444, |
| Free: 0, |
| }, |
| Buffer: xfs.BufferStats{ |
| Get: 2666287, |
| Create: 7122, |
| GetLocked: 2659202, |
| GetLockedWaited: 3599, |
| BusyLocked: 2, |
| MissLocked: 7085, |
| PageRetries: 0, |
| PageFound: 10297, |
| GetRead: 7085, |
| }, |
| ExtendedPrecision: xfs.ExtendedPrecisionStats{ |
| FlushBytes: 399724544, |
| WriteBytes: 92823103, |
| ReadBytes: 86219234, |
| }, |
| PushAil: xfs.PushAilStats{ |
| TryLogspace: 945014, |
| SleepLogspace: 0, |
| Pushes: 134260, |
| Success: 15483, |
| PushBuf: 0, |
| Pinned: 3940, |
| Locked: 464, |
| Flushing: 159985, |
| Restarts: 0, |
| Flush: 40, |
| }, |
| Xstrat: xfs.XstratStats{ |
| Quick: 92447, |
| Split: 0, |
| }, |
| Debug: xfs.DebugStats{ |
| Enabled: 0, |
| }, |
| QuotaManager: xfs.QuotaManagerStats{ |
| Reclaims: 0, |
| ReclaimMisses: 0, |
| DquoteDups: 0, |
| CacheMisses: 0, |
| CacheHits: 0, |
| Wants: 0, |
| ShakeReclaims: 0, |
| InactReclaims: 0, |
| }, |
| BtreeAllocBlocks2: xfs.BtreeAllocBlocks2Stats{ |
| Lookup: 184941, |
| Compare: 1277345, |
| Insrec: 13257, |
| Delrec: 13278, |
| NewRoot: 0, |
| KillRoot: 0, |
| Increment: 0, |
| Decrement: 0, |
| Lshift: 0, |
| Rshift: 0, |
| Split: 0, |
| Join: 0, |
| Alloc: 0, |
| Free: 0, |
| Moves: 2746147, |
| }, |
| |
| BtreeAllocContig2: xfs.BtreeAllocContig2Stats{ |
| Lookup: 345295, |
| Compare: 2416764, |
| Insrec: 172637, |
| Delrec: 172658, |
| NewRoot: 0, |
| KillRoot: 0, |
| Increment: 0, |
| Decrement: 0, |
| Lshift: 0, |
| Rshift: 0, |
| Split: 0, |
| Join: 0, |
| Alloc: 0, |
| Free: 0, |
| Moves: 21406023, |
| }, |
| |
| BtreeBlockMap2: xfs.BtreeBlockMap2Stats{ |
| Lookup: 0, |
| Compare: 0, |
| Insrec: 0, |
| Delrec: 0, |
| NewRoot: 0, |
| KillRoot: 0, |
| Increment: 0, |
| Decrement: 0, |
| Lshift: 0, |
| Rshift: 0, |
| Split: 0, |
| Join: 0, |
| Alloc: 0, |
| Free: 0, |
| Moves: 0, |
| }, |
| |
| BtreeInode2: xfs.BtreeInode2Stats{ |
| Lookup: 343004, |
| Compare: 1358467, |
| Insrec: 0, |
| Delrec: 0, |
| NewRoot: 0, |
| KillRoot: 0, |
| Increment: 0, |
| Decrement: 0, |
| Lshift: 0, |
| Rshift: 0, |
| Split: 0, |
| Join: 0, |
| Alloc: 0, |
| Free: 0, |
| Moves: 0, |
| }, |
| }, |
| }, |
| } |
| |
| for _, tt := range tests { |
| var ( |
| stats *xfs.Stats |
| err error |
| ) |
| |
| if tt.s != "" { |
| stats, err = xfs.ParseStats(strings.NewReader(tt.s)) |
| } |
| if tt.fs { |
| xfs, err := xfs.NewFS("testdata/fixtures/proc", "testdata/fixtures/sys") |
| if err != nil { |
| t.Fatalf("failed to access xfs fs: %v", err) |
| } |
| stats, err = xfs.ProcStat() |
| if err != nil { |
| t.Fatalf("failed to gather xfs stats: %v", err) |
| } |
| } |
| |
| if tt.invalid && err == nil { |
| t.Error("expected an error, but none occurred") |
| } |
| if !tt.invalid && err != nil { |
| t.Errorf("unexpected error: %v", err) |
| } |
| |
| if diff := cmp.Diff(tt.stats, stats); diff != "" { |
| t.Fatalf("unexpected XFS stats (-want +got):\n%s", diff) |
| } |
| } |
| } |