diskstat.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package linux
  2. import (
  3. "io/ioutil"
  4. "strconv"
  5. "strings"
  6. "time"
  7. )
  8. // DiskStat is disk statistics to help measure disk activity.
  9. //
  10. // Note:
  11. // * On a very busy or long-lived system values may wrap.
  12. // * No kernel locks are held while modifying these counters. This implies that
  13. // minor inaccuracies may occur.
  14. //
  15. // More more info see:
  16. // https://www.kernel.org/doc/Documentation/iostats.txt and
  17. // https://www.kernel.org/doc/Documentation/block/stat.txt
  18. type DiskStat struct {
  19. Major int `json:"major"` // major device number
  20. Minor int `json:"minor"` // minor device number
  21. Name string `json:"name"` // device name
  22. ReadIOs uint64 `json:"read_ios"` // number of read I/Os processed
  23. ReadMerges uint64 `json:"read_merges"` // number of read I/Os merged with in-queue I/O
  24. ReadSectors uint64 `json:"read_sectors"` // number of 512 byte sectors read
  25. ReadTicks uint64 `json:"read_ticks"` // total wait time for read requests in milliseconds
  26. WriteIOs uint64 `json:"write_ios"` // number of write I/Os processed
  27. WriteMerges uint64 `json:"write_merges"` // number of write I/Os merged with in-queue I/O
  28. WriteSectors uint64 `json:"write_sectors"` // number of 512 byte sectors written
  29. WriteTicks uint64 `json:"write_ticks"` // total wait time for write requests in milliseconds
  30. InFlight uint64 `json:"in_flight"` // number of I/Os currently in flight
  31. IOTicks uint64 `json:"io_ticks"` // total time this block device has been active in milliseconds
  32. TimeInQueue uint64 `json:"time_in_queue"` // total wait time for all requests in milliseconds
  33. }
  34. // ReadDiskStats reads and parses the file.
  35. //
  36. // Note:
  37. // * Assumes a well formed file and will panic if it isn't.
  38. func ReadDiskStats(path string) ([]DiskStat, error) {
  39. data, err := ioutil.ReadFile(path)
  40. if err != nil {
  41. return nil, err
  42. }
  43. devices := strings.Split(string(data), "\n")
  44. results := make([]DiskStat, len(devices)-1)
  45. for i := range results {
  46. fields := strings.Fields(devices[i])
  47. Major, _ := strconv.ParseInt(fields[0], 10, strconv.IntSize)
  48. results[i].Major = int(Major)
  49. Minor, _ := strconv.ParseInt(fields[1], 10, strconv.IntSize)
  50. results[i].Minor = int(Minor)
  51. results[i].Name = fields[2]
  52. results[i].ReadIOs, _ = strconv.ParseUint(fields[3], 10, 64)
  53. results[i].ReadMerges, _ = strconv.ParseUint(fields[4], 10, 64)
  54. results[i].ReadSectors, _ = strconv.ParseUint(fields[5], 10, 64)
  55. results[i].ReadTicks, _ = strconv.ParseUint(fields[6], 10, 64)
  56. results[i].WriteIOs, _ = strconv.ParseUint(fields[7], 10, 64)
  57. results[i].WriteMerges, _ = strconv.ParseUint(fields[8], 10, 64)
  58. results[i].WriteSectors, _ = strconv.ParseUint(fields[9], 10, 64)
  59. results[i].WriteTicks, _ = strconv.ParseUint(fields[10], 10, 64)
  60. results[i].InFlight, _ = strconv.ParseUint(fields[11], 10, 64)
  61. results[i].IOTicks, _ = strconv.ParseUint(fields[12], 10, 64)
  62. results[i].TimeInQueue, _ = strconv.ParseUint(fields[13], 10, 64)
  63. }
  64. return results, nil
  65. }
  66. // GetReadBytes returns the number of bytes read.
  67. func (ds *DiskStat) GetReadBytes() int64 {
  68. return int64(ds.ReadSectors) * 512
  69. }
  70. // GetReadTicks returns the duration waited for read requests.
  71. func (ds *DiskStat) GetReadTicks() time.Duration {
  72. return time.Duration(ds.ReadTicks) * time.Millisecond
  73. }
  74. // GetWriteBytes returns the number of bytes written.
  75. func (ds *DiskStat) GetWriteBytes() int64 {
  76. return int64(ds.WriteSectors) * 512
  77. }
  78. // GetReadTicks returns the duration waited for write requests.
  79. func (ds *DiskStat) GetWriteTicks() time.Duration {
  80. return time.Duration(ds.WriteTicks) * time.Millisecond
  81. }
  82. // GetIOTicks returns the duration the disk has been active.
  83. func (ds *DiskStat) GetIOTicks() time.Duration {
  84. return time.Duration(ds.IOTicks) * time.Millisecond
  85. }
  86. // GetTimeInQueue returns the duration waited for all requests.
  87. func (ds *DiskStat) GetTimeInQueue() time.Duration {
  88. return time.Duration(ds.TimeInQueue) * time.Millisecond
  89. }