in lib/model/CMetricBucketGatherer.cc [1119:1264]
bool CMetricBucketGatherer::processFields(const TStrCPtrVec& fieldValues,
CEventData& result,
CResourceMonitor& resourceMonitor) {
using TOptionalStr = std::optional<std::string>;
if (fieldValues.size() != m_FieldNames.size()) {
LOG_ERROR(<< "Unexpected field values: " << fieldValues
<< ", for field names: " << m_FieldNames);
return false;
}
const std::string* person = (fieldValues[0] == nullptr && m_DataGatherer.useNull())
? &EMPTY_STRING
: fieldValues[0];
if (person == nullptr) {
// Just ignore: the "person" field wasn't present in the
// record. Since all models in an aggregate share this
// field we can't process this record further. Note that
// we don't warn here since we'll permit a small fraction
// of records to having missing field values.
return false;
}
// The code below just ignores missing/invalid values. This
// doesn't necessarily stop us processing the record by other
// models, so we don't return false.
std::size_t i = m_BeginInfluencingFields;
for (/**/; i < m_BeginValueFields; ++i) {
result.addInfluence(fieldValues[i] ? TOptionalStr(*fieldValues[i]) : std::nullopt);
}
if (m_DataGatherer.summaryMode() != model_t::E_None) {
CEventData::TDouble1VecArraySizePr statistics;
statistics.first.fill(TDouble1Vec(1, 0.0));
if (m_DataGatherer.extractCountFromField(m_FieldNames[i], fieldValues[i],
statistics.second) == false) {
result.addValue();
return true;
}
++i;
bool allOk = true;
if (m_FieldNames.size() > statistics.first.size() + i) {
LOG_ERROR(<< "Inconsistency - more statistic field names than allowed "
<< m_FieldNames.size() - i << " > " << statistics.first.size());
allOk = false;
}
if (m_FieldNames.size() > m_FieldMetricCategories.size() + i) {
LOG_ERROR(<< "Inconsistency - more statistic field names than metric categories "
<< m_FieldNames.size() - i << " > "
<< m_FieldMetricCategories.size());
allOk = false;
}
for (std::size_t j = 0; allOk && i < m_FieldNames.size(); ++i, ++j) {
model_t::EMetricCategory category = m_FieldMetricCategories[j];
if (fieldValues[i] == nullptr ||
m_DataGatherer.extractMetricFromField(
m_FieldNames[i], *fieldValues[i], statistics.first[category]) == false) {
allOk = false;
}
}
if (allOk) {
if (statistics.second == CDataGatherer::EXPLICIT_NULL_SUMMARY_COUNT) {
result.setExplicitNull();
} else {
result.addStatistics(statistics);
}
} else {
result.addValue();
}
} else {
TDouble1Vec value;
if (fieldValues[i] != nullptr &&
m_DataGatherer.extractMetricFromField(m_FieldNames[i], *fieldValues[i],
value) == true) {
result.addValue(value);
} else {
result.addValue();
}
}
bool addedPerson = false;
std::size_t pid = CDynamicStringIdRegistry::INVALID_ID;
if (result.isExplicitNull()) {
m_DataGatherer.personId(*person, pid);
} else {
pid = m_DataGatherer.addPerson(*person, resourceMonitor, addedPerson);
}
if (pid == CDynamicStringIdRegistry::INVALID_ID) {
if (!result.isExplicitNull()) {
LOG_TRACE(<< "Couldn't create a person, over memory limit");
}
return false;
}
if (addedPerson) {
resourceMonitor.addExtraMemory(m_DataGatherer.isPopulation()
? CDataGatherer::ESTIMATED_MEM_USAGE_PER_OVER_FIELD
: CDataGatherer::ESTIMATED_MEM_USAGE_PER_BY_FIELD);
++(m_DataGatherer.isPopulation()
? core::CProgramCounters::counter(counter_t::E_TSADNumberOverFields)
: core::CProgramCounters::counter(counter_t::E_TSADNumberByFields));
}
if (!result.person(pid)) {
LOG_ERROR(<< "Bad by field value: " << *person);
return false;
}
const std::string* attribute =
(fieldValues[1] == nullptr && m_DataGatherer.useNull()) ? &EMPTY_STRING
: fieldValues[1];
if (m_DataGatherer.isPopulation()) {
if (attribute == nullptr) {
// Just ignore: the "by" field wasn't present in the
// record. This doesn't necessarily stop us processing
// the record by other models so we don't return false.
// Note that we don't warn here since we'll permit a
// small fraction of records to having missing field
// values.
result.addAttribute();
result.addValue();
return true;
}
bool addedAttribute = false;
std::size_t cid = CDynamicStringIdRegistry::INVALID_ID;
if (result.isExplicitNull()) {
m_DataGatherer.attributeId(*attribute, cid);
} else {
cid = m_DataGatherer.addAttribute(*attribute, resourceMonitor, addedAttribute);
}
result.addAttribute(cid);
if (addedAttribute) {
resourceMonitor.addExtraMemory(CDataGatherer::ESTIMATED_MEM_USAGE_PER_BY_FIELD);
++core::CProgramCounters::counter(counter_t::E_TSADNumberByFields);
}
} else {
// Add the unique attribute.
result.addAttribute(std::size_t(0));
}
return true;
}