• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef IO_STATS_H
17 #define IO_STATS_H
18 
19 #include <deque>
20 #include <array>
21 #include <cinttypes>
22 #include <cstdio>
23 #include <fstream>
24 #include <inttypes.h>
25 #include <iostream>
26 #include <memory>
27 #include <string>
28 #include <sys/mman.h>
29 
30 #include "diskio_plugin_config.pb.h"
31 #include "diskio_plugin_result.pb.h"
32 #include "logging.h"
33 
34 constexpr int NUM_TWO = 2;
35 
36 class ProcStats {
37 public:
38     std::string name_;
39     uint64_t user_;
40     uint64_t nice_;
41     uint64_t system_;
42     uint64_t idle_;
43     uint64_t iowait_;
44     uint64_t steal_;
45     uint64_t hardirq_;
46     uint64_t softirq_;
47     uint64_t guest_;
48     uint64_t guestNice_;
49 
ProcStats()50     ProcStats()
51         : name_(""),
52         user_(0),
53         nice_(0),
54         system_(0),
55         idle_(0),
56         iowait_(0),
57         steal_(0),
58         hardirq_(0),
59         softirq_(0),
60         guest_(0),
61         guestNice_(0)
62     {
63     }
64 
~ProcStats()65     ~ProcStats() {}
66 
GetTotalTime()67     uint64_t GetTotalTime()
68     {
69         return user_ + nice_ + system_ + idle_ + iowait_ + steal_ + hardirq_ + softirq_;
70     }
71 };
72 
73 class DiskStats {
74 public:
75     std::string deviceName_;
76     uint64_t major_;
77     uint64_t minor_;
78 
79     uint64_t rSucc_;  // 成功完成读的总次数     rd_ios
80     uint64_t rMerged_; // 合并读次数             rd_merges
81     uint64_t rSectors_;   // 读扇区的次数           rd_sectors
82     uint64_t timeOfRead_; // 读花的时间(ms)         rd_ticks
83 
84     uint64_t wSucc_;  // 成功完成写的总次数    wr_ios
85     uint64_t wMerged_; // 合并写次数            wr_merges
86     uint64_t wSectors_;    // 写扇区的次数          wr_sectors
87     uint64_t timeOfWrite_; // 写花的时间(ms)        wr_ticks
88 
89     uint64_t dSucc_;
90     uint64_t dMerged_;
91     uint64_t dSectors_;
92     uint64_t timeOfd_;
93 
94     uint64_t flushSucc_;
95     uint64_t timeOfFlush_;
96 
97     uint64_t ios_;      // I/O的当前进度            ios_pgr
98     uint64_t timeOfIo_; // I/O操作上的毫秒数        tot_ticks ?
99     uint64_t weighted_; // 输入/输出操作花费的加权毫秒数 rq_ticks ?
100 
DiskStats()101     DiskStats()
102         : deviceName_(""),
103         major_(0),
104         minor_(0),
105         rSucc_(0),
106         rMerged_(0),
107         rSectors_(0),
108         timeOfRead_(0),
109         wSucc_(0),
110         wMerged_(0),
111         wSectors_(0),
112         timeOfWrite_(0),
113         dSucc_(0),
114         dMerged_(0),
115         dSectors_(0),
116         timeOfd_(0),
117         flushSucc_(0),
118         timeOfFlush_(0),
119         ios_(0),
120         timeOfIo_(0),
121         weighted_(0)
122     {
123     }
124 
~DiskStats()125     ~DiskStats() {}
126 };
127 
128 using CpuDatasPtr = std::shared_ptr<ProcStats>;
129 using DiskDatasPtr = std::shared_ptr<DiskStats>;
130 class IoStats {
131 public:
132     IoStats(DiskioConfig::IoReportType type = DiskioConfig::UNSPECIFIED);
~IoStats()133     ~IoStats() {}
134     bool GetIoData();
135 
PutPluginStatsData(T & pluginStatsData)136     template <typename T> bool PutPluginStatsData(T& pluginStatsData)
137     {
138         PutCpuStatsData(pluginStatsData);
139         if (type_ == DiskioConfig::IO_REPORT) {
140             PutIoStatsData(pluginStatsData);
141         } else if (type_ == DiskioConfig::IO_REPORT_EX) {
142             ParseIoStatsEx();
143         }
144         return true;
145     }
146 
147 private:
148     bool ParseCpuStats();
149     bool GetCpuStats(std::string& line);
150     bool ParseIoStats();
151     bool GetIoStats(std::string& line);
152 
PutCpuStatsData(T & pluginStatsData)153     template <typename T> uint32_t PutCpuStatsData(T& pluginStatsData)
154     {
155         std::unique_lock<std::mutex> lock(mutex_);
156         if (cpuDatas_.empty()) {
157             return 0;
158         }
159 
160         uint32_t count = 0;
161         while (cpuDatas_.size() > 0) {
162             auto cpuData = cpuDatas_.front();
163             auto* cpuInfo = pluginStatsData.add_cpuinfo();
164             CalcCpuStats(cpuData, *cpuInfo);
165             cpuDatas_.pop_front();
166             count++;
167         }
168         lock.unlock();
169         return count;
170     }
171 
CalcCpuStats(const CpuDatasPtr & cpuData,T & cpuStatsInfo)172     template <typename T> void CalcCpuStats(const CpuDatasPtr& cpuData, T& cpuStatsInfo)
173     {
174         auto totalTime = cpuData->GetTotalTime();
175         cpuStatsInfo.set_name(cpuData->name_);
176         cpuStatsInfo.set_cpu_user(KeepTowDigits(cpuData->user_, totalTime));
177         cpuStatsInfo.set_cpu_nice(KeepTowDigits(cpuData->nice_, totalTime));
178         cpuStatsInfo.set_cpu_iowait(KeepTowDigits(cpuData->iowait_, totalTime));
179         cpuStatsInfo.set_cpu_steal(KeepTowDigits(cpuData->steal_, totalTime));
180 
181         cpuStatsInfo.set_cpu_sys(KeepTowDigits(cpuData->system_ + cpuData->softirq_ + cpuData->hardirq_, totalTime));
182         cpuStatsInfo.set_cpu_idle(KeepTowDigits(cpuData->idle_, totalTime));
183     }
184 
185     double KeepTowDigits(const uint64_t& data, uint64_t div);
186 
PutIoStatsData(T & pluginStatsData)187     template <typename T> uint32_t PutIoStatsData(T& pluginStatsData)
188     {
189         std::unique_lock<std::mutex> lock(mutex_);
190         if (ioDatas_.empty()) {
191             return 0;
192         }
193 
194         uint32_t count = 0;
195         while (ioDatas_.size() > 0) {
196             auto ioData = ioDatas_.front();
197             auto* ioInfo = pluginStatsData.add_statsinfo();
198             CalcIoStats(ioData, *ioInfo);
199             ioDatas_.pop_front();
200             count++;
201         }
202         lock.unlock();
203         return count;
204     }
205 
CalcIoStats(const DiskDatasPtr & ioData,T & ioStatDataInfo)206     template <typename T> void CalcIoStats(const DiskDatasPtr& ioData, T& ioStatDataInfo)
207     {
208         ioStatDataInfo.set_name(ioData->deviceName_);
209         // (成功完成读的总次数 + 写 + 丢弃) / sysTime_
210         ioStatDataInfo.set_ios_per_sec(KeepTowDigits(ioData->rSucc_ + ioData->wSucc_ + ioData->dSucc_, sysTime_));
211 
212         // 读扇区的次数 / sysTime_
213         ioStatDataInfo.set_rd_per_sec(KeepTowDigits(KeepTowDigits(ioData->rSectors_, sysTime_), NUM_TWO));
214         ioStatDataInfo.set_wr_per_sec(KeepTowDigits(KeepTowDigits(ioData->wSectors_, sysTime_), NUM_TWO));
215         ioStatDataInfo.set_dc_per_sec(KeepTowDigits(KeepTowDigits(ioData->dSectors_, sysTime_), NUM_TWO));
216 
217         // 读扇区的次数
218         ioStatDataInfo.set_rd_kb(KeepTowDigits(ioData->rSectors_, NUM_TWO));
219         ioStatDataInfo.set_wr_kb(KeepTowDigits(ioData->wSectors_, NUM_TWO));
220         ioStatDataInfo.set_dc_kb(KeepTowDigits(ioData->dSectors_, NUM_TWO));
221     }
222     uint32_t OutputCpuData();
223     bool OutputIoData();
224     uint64_t GetSystime();
225     bool ParseIoStatsEx();
226     bool FindFirstNum(char** p);
227     bool RemoveSpaces(char** p);
228     uint32_t ParseLineFields(const std::string& line);
229     uint32_t ParseLineFields(const std::string& line, std::string& name);
230 
231 private:
232     std::mutex mutex_;
233     DiskioConfig::IoReportType type_;
234     uint64_t sysTime_;
235     std::deque<CpuDatasPtr> cpuDatas_;
236     std::deque<DiskDatasPtr> ioDatas_;
237     std::vector<uint64_t> fields_;
238 };
239 
240 #endif // #ifndef IO_STATS_H
241