MetroCollect  2.3.4
SourceProcStat.cc
Go to the documentation of this file.
1 //
2 // SourceProcStat.cc
3 //
4 // Created on July 13th 2018
5 //
6 // Copyright 2018 CFM (www.cfm.fr)
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 //
20 
21 #include <algorithm>
22 #include <cstring>
23 #include <numeric>
24 
25 #include "SourceProcStat.h"
26 
27 
31  this->parseFields();
32  }
33 
34 
36  bool read = readFile(this->file_, this->buffer_, SourceProcStat::filePath);
37  if (!read)
38  return;
39 
40  const char* buffer = this->buffer_.data();
41 
42  this->cpuCount_ = 0;
43  while (std::strncmp(buffer, SourceProcStat::cpuField.data(), SourceProcStat::cpuField.size()) == 0) {
44  this->cpuCount_++;
45  buffer = std::strchr(buffer, '\n') + 1;
46  }
47  this->cpuCount_--;
48 
49  this->otherFieldNames_.clear();
50  while (buffer[0] != '\0') {
51  size_t length = 0;
52  while (buffer[length] != ' ')
53  length++;
54  this->otherFieldNames_.emplace_back(buffer, length);
55  buffer += length;
56  while (buffer[0] != '\n')
57  buffer++;
58  buffer++;
59  }
60  }
61 
62 
63  size_t SourceProcStat::fieldCount() const noexcept {
65  }
66 
67  const std::vector<size_t> SourceProcStat::indexesOfFieldName(const FieldName& fieldName, Interests* interests) const noexcept {
68  if (fieldName.front() != SourceProcStat::sourcePrefix)
69  return {};
70 
71  if (fieldName[1] == SourceProcStat::fieldNameOtherPrefix) {
72  auto itr = std::find(this->otherFieldNames_.begin(), this->otherFieldNames_.end(), fieldName[2]);
73  if (itr != this->otherFieldNames_.end()) {
74  if (interests)
75  interests->set(0);
76  return {static_cast<size_t>(std::distance(this->otherFieldNames_.begin(), itr))};
77  } else
78  return {};
79  }
80  else if (fieldName[1] == SourceProcStat::fieldNameAllCoresPrefix) {
81  auto itr = std::find(SourceProcStat::cpuFieldNames.begin(), SourceProcStat::cpuFieldNames.end(), fieldName[2]);
82  if (itr != SourceProcStat::cpuFieldNames.end()) {
83  if (interests)
84  interests->set(1);
85  return {this->otherFieldNames_.size() + std::distance(SourceProcStat::cpuFieldNames.begin(), itr)};
86  } else
87  return {};
88  }
89  else if (fieldName[1] == SourceProcStat::fieldNameCorePrefix) {
90  auto itr = std::find(SourceProcStat::cpuFieldNames.begin(), SourceProcStat::cpuFieldNames.end(), fieldName[3]);
91  if (itr == SourceProcStat::cpuFieldNames.end())
92  return {};
93  size_t baseIndex = this->otherFieldNames_.size() + SourceProcStat::cpuFieldCount + std::distance(SourceProcStat::cpuFieldNames.begin(), itr) ;
94  if (fieldName[2] == SourceProcStat::fieldNameCoreAll) {
95  std::vector<size_t> indexes;
96  for (size_t cpuIndex = 0; cpuIndex < this->cpuCount_; cpuIndex++)
97  indexes.push_back(baseIndex + SourceProcStat::cpuFieldCount * cpuIndex);
98  if (interests)
99  interests->set(1);
100  return indexes;
101  }
102  else {
103  size_t cpuIndex = 0;
104  try {
105  cpuIndex = std::stoll(fieldName[2]);
106  } catch (...) {
107  return {};
108  }
109  if (cpuIndex < this->cpuCount_) {
110  if (interests)
111  interests->set(1);
112  return {baseIndex + SourceProcStat::cpuFieldCount * cpuIndex};
113  }
114  return {};
115  }
116  }
117  return {};
118  }
119 
120  const std::string SourceProcStat::fieldNameSourcePrefix() const noexcept {
121  return std::string(SourceProcStat::sourcePrefix);
122  }
123 
124  const FieldInfo SourceProcStat::fieldInfoAtIndex(size_t index) const noexcept {
125  if (index < this->otherFieldNames_.size()) {
126  FieldName name = {std::string(SourceProcStat::sourcePrefix), std::string(SourceProcStat::fieldNameOtherPrefix), this->otherFieldNames_[index]};
127  return {name, "CPU metric augmentation: " + this->otherFieldNames_[index], std::string(SourceProcStat::defaultUnit)};
128  } else if (index < this->otherFieldNames_.size() + SourceProcStat::cpuFieldCount) {
129  FieldName name = {std::string(SourceProcStat::sourcePrefix), std::string(SourceProcStat::fieldNameAllCoresPrefix), std::string(SourceProcStat::cpuFieldNames[index - this->otherFieldNames_.size()])};
130  return {name, "CPU aggregated metric: " + std::string(SourceProcStat::cpuFieldNames[index - this->otherFieldNames_.size()]), std::string(SourceProcStat::percentUnit)};
131  } else {
132  size_t cpuIndex = (index - this->otherFieldNames_.size()) / SourceProcStat::cpuFieldCount - 1;
133  size_t fieldIndex = (index - this->otherFieldNames_.size()) % SourceProcStat::cpuFieldCount;
134  FieldName name = {std::string(SourceProcStat::sourcePrefix), std::string(SourceProcStat::fieldNameCorePrefix), std::to_string(cpuIndex), std::string(SourceProcStat::cpuFieldNames[fieldIndex])};
135  return {name, "CPU core metric: " + std::string(SourceProcStat::cpuFieldNames[fieldIndex]), std::string(SourceProcStat::percentUnit), 2, std::string(SourceProcStat::fieldNameCoreDescription)};
136  }
137  }
138 
139  const std::vector<FieldInfo> SourceProcStat::allFieldsInfo() const noexcept {
140  std::vector<FieldInfo> info;
141  for (size_t i = 0; i < this->otherFieldNames_.size() + SourceProcStat::cpuFieldCount; i++)
142  info.push_back(this->fieldInfoAtIndex(i));
143  for (size_t i = 0; i < SourceProcStat::cpuFieldCount; i++) {
144  info.push_back(this->fieldInfoAtIndex(this->otherFieldNames_.size() + SourceProcStat::cpuFieldCount + i));
145  info.back().name[info.back().dynamicIndexes[0].index] = SourceProcStat::fieldNameCoreAll;
146  }
147  return info;
148  }
149 
150 
151  void SourceProcStat::fetchData(const Interests& interests, DataArray::Iterator current) {
152  bool read = false;
153  if (interests.none() || !(read = readFile(this->file_, this->buffer_, SourceProcStat::filePath))) {
154  std::fill_n(current, this->fieldCount(), 0);
155  return;
156  }
157 
158  const char* buffer = this->buffer_.data();
159 
160  if (interests.isSet(1)) {
161  size_t index = 0;
162  size_t remainingCPUs = this->cpuCount_ + 1;
163  while (remainingCPUs > 0 && std::strncmp(buffer, SourceProcStat::cpuField.data(), SourceProcStat::cpuField.size()) == 0) {
164  buffer += SourceProcStat::cpuField.size();
165  while (buffer[0] != ' ')
166  buffer++;
167  while(buffer[0] != '\n') {
168  buffer++;
169  current[index + this->otherFieldNames_.size()] = static_cast<DataValueType>(parseUint(buffer));
170  index++;
171  }
172  buffer++;
173  while (index % SourceProcStat::cpuFieldCount != 0) {
174  current[index + this->otherFieldNames_.size()] = static_cast<DataValueType>(0);
175  index++;
176  }
177  remainingCPUs--;
178  }
179  }
180 
181  if (interests.isSet(0)) {
182  while (std::strncmp(buffer, SourceProcStat::cpuField.data(), SourceProcStat::cpuField.size()) == 0) {
183  while (buffer[0] != '\n')
184  buffer++;
185  buffer++;
186  }
187 
188  size_t remainingFields = this->otherFieldNames_.size();
189  while (remainingFields > 0 && buffer[0] != '\0') {
190  while (buffer[0] != ' ')
191  buffer++;
192  *current = static_cast<DataValueType>(parseUint(buffer));
193  current++;
194  while (buffer[0] != '\n')
195  buffer++;
196  buffer++;
197  remainingFields--;
198  }
199  }
200  }
201 
202  void SourceProcStat::computeDiff(const Interests& interests, DiffArray::Iterator diff, DataArray::ConstIterator current, DataArray::ConstIterator previous, double factor) noexcept {
203  if (interests.isSet(0)) {
204  for (size_t i = 0; i < this->otherFieldNames_.size(); i++) {
205  if (i == 4 || i == 5) // procs_running and procs_blocked
206  *diff = static_cast<DiffValueType>(*current);
207  else
208  *diff = static_cast<DiffValueType>((*current - *previous) * factor);
209  diff++;
210  current++;
211  previous++;
212  }
213  }
214 
215  if (interests.isSet(1)) {
216  for (size_t cpuIndex = 0; cpuIndex < this->cpuCount_ + 1; cpuIndex++) {
217  auto currentSum = std::accumulate(current, current + SourceProcStat::cpuFieldCount, static_cast<DiffValueType>(0));
218  auto previousSum = std::accumulate(previous, previous + SourceProcStat::cpuFieldCount, static_cast<DiffValueType>(0));
219 
220  if (currentSum == previousSum) {
221  for (size_t i = 0; i < SourceProcStat::cpuFieldCount; i++)
222  diff[i] = static_cast<DiffValueType>(0);
223  diff[3] = static_cast<DiffValueType>(100);
226  previous += SourceProcStat::cpuFieldCount;
227  } else {
228  double invSumDiff = 100.0 / (currentSum - previousSum);
229  if (cpuIndex == 0)
230  invSumDiff *= this->cpuCount_;
231  for (size_t i = 0; i < SourceProcStat::cpuFieldCount; i++) {
232  *diff = static_cast<DiffValueType>((*current - *previous) * invSumDiff);
233  diff++;
234  current++;
235  previous++;
236  }
237  }
238  }
239  }
240  }
241 }
Object used to describe a field (or metric)
Definition: SourceField.h:37
static constexpr std::string_view fieldNameAllCoresPrefix
Metrics name category.
static constexpr std::string_view cpuField
Metrics name category.
std::vector< std::string > FieldName
Type used for field names (an array of strings)
Definition: SourceField.h:31
bool readFile(std::ifstream &file, std::vector< char > &buffer, const std::string_view &path)
Attempts to read file into buffer.
Definition: SourceTools.cc:55
static constexpr std::array< std::string_view, cpuFieldCount > cpuFieldNames
CPU states names.
const FieldInfo fieldInfoAtIndex(size_t index) const noexcept override final
Get details about a specific field.
Namespace for sources of metrics objects and operations.
static constexpr std::string_view percentUnit
Metric unit.
std::vector< DataValueType >::const_iterator ConstIterator
Const iterator type of MetricsDataArray.
Definition: MetricTypes.h:37
uint64_t parseUint(const char *&buffer) noexcept
Fast and unsafe unsigned integer parser.
Definition: SourceTools.h:40
const std::string fieldNameSourcePrefix() const noexcept override final
Get the prefix by which all field names should begin with.
void computeDiff(const Interests &interests, DiffArray::Iterator diff, DataArray::ConstIterator current, DataArray::ConstIterator previous, double factor=1) noexcept override final
Compute the variation (in appropriate unit) of metrics.
void fetchData(const Interests &interests, DataArray::Iterator current) override final
Fetch the latest metrics.
static constexpr std::string_view fieldNameCorePrefix
Metrics name category.
static constexpr std::string_view filePath
CPU metrics file path.
void parseFields()
File parser function.
static constexpr std::string_view sourcePrefix
Metrics name source prefix.
const std::vector< FieldInfo > allFieldsInfo() const noexcept override final
Get all fields details, field which share a common name should appear only once.
int64_t DataValueType
Type of fetched raw metrics.
Definition: MetricTypes.h:28
bool none() const
Checks wether all bit are false.
Boolean array to keep track of which fields a source has to fetch metrics for.
static constexpr size_t cpuFieldCount
Number of fields for each CPU.
static constexpr std::string_view fieldNameOtherPrefix
Metrics name category.
std::vector< char > buffer_
Buffer to put file contents into.
std::vector< DiffValueType >::iterator Iterator
Iterator type of MetricsDiffArray.
Definition: MetricTypes.h:44
static constexpr std::string_view defaultUnit
Metric unit.
static constexpr std::string_view fieldNameCoreDescription
Metrics name category description.
bool resetFile(std::ifstream &file, std::vector< char > &buffer, const std::string_view &path)
Attempts to open a file and set buffer size accordingly.
Definition: SourceTools.cc:25
const std::vector< size_t > indexesOfFieldName(const FieldName &fieldName, Interests *interests=nullptr) const noexcept override final
Search for fields associated to a specific name.
static constexpr std::string_view fieldNameCoreAll
Metrics name wildcard.
std::vector< std::string > otherFieldNames_
Names of other CPU metrics.
std::vector< DataValueType >::iterator Iterator
Iterator type of MetricsDataArray.
Definition: MetricTypes.h:36
SourceProcStat()
Private default constructor.
bool isSet(T index) const
Checks if a specific bit is true.
size_t fieldCount() const noexcept override final
Get the number of field the source has.
std::ifstream file_
File descriptor.
double DiffValueType
Type of metric variation.
Definition: MetricTypes.h:29