Commit 48ce9d0a authored by Alessio Netti's avatar Alessio Netti

Configurable maximum wrap-around value for delta sensors

parent 0e0ac9a1
......@@ -489,6 +489,8 @@ protected:
sBase.setSkipConstVal(to_bool(val.second.data()));
} else if (boost::iequals(val.first, "delta")) {
sBase.setDelta(to_bool(val.second.data()));
} else if (boost::iequals(val.first, "deltaMax")) {
sBase.setDeltaMaxValue(std::stoull(val.second.data()));
} else if (boost::iequals(val.first, "subSampling")) {
sBase.setSubsampling(std::stoi(val.second.data()));
} else if (boost::iequals(val.first, "publish")) {
......
......@@ -54,6 +54,7 @@ public:
_subsamplingIndex(0),
_cache(nullptr),
_delta(false),
_deltaMax(LLONG_MAX),
_firstReading(true),
_readingQueue(nullptr),
_metadata(nullptr) {
......@@ -80,6 +81,7 @@ public:
_subsamplingIndex(0),
_cache(nullptr),
_delta(other._delta),
_deltaMax(other._deltaMax),
_firstReading(true),
_lastRawUValue(other._lastRawUValue),
_lastRawValue(other._lastRawValue),
......@@ -103,6 +105,7 @@ public:
_subsamplingIndex = 0;
_cache.reset(nullptr);
_delta = other._delta;
_deltaMax = other._deltaMax;
_firstReading = true;
_lastRawUValue.timestamp = other._lastRawUValue.timestamp;
_lastRawUValue.value = other._lastRawUValue.value;
......@@ -121,6 +124,7 @@ public:
}
const bool isDelta() const { return _delta;}
const uint64_t getDeltaMaxValue() const { return _deltaMax; }
const std::string& getName() const { return _name; }
const std::string& getMqtt() const { return _mqtt; }
bool getSkipConstVal() const { return _skipConstVal; }
......@@ -140,6 +144,7 @@ public:
void setSkipConstVal(bool skipConstVal) { _skipConstVal = skipConstVal; }
void setPublish(bool pub) { _publish = pub; }
void setDelta(const bool delta) { _delta = delta; }
void setDeltaMaxValue(const uint64_t maxv) { _deltaMax = maxv; }
void setName(const std::string& name) { _name = name; }
void setMqtt(const std::string& mqtt) { _mqtt = mqtt; }
void setCacheInterval(unsigned cacheInterval) { _cacheInterval = cacheInterval; }
......@@ -173,16 +178,14 @@ public:
*
* @param rawReading Reading struct with value and timestamp to be stored.
* @param factor Scaling factor, which is applied to the reading value (optional)
* @param maxValue Maximum possible value of the reading; required for the
* delta computation to detect an overflow.
* @param storeGlobal Store reading in reading queue, so that it can get pushed.
*/
void storeReading(reading_t rawReading, double factor=1.0, long long maxValue=LLONG_MAX, bool storeGlobal=true) {
void storeReading(reading_t rawReading, double factor=1.0, bool storeGlobal=true) {
reading_t reading = rawReading;
if( _delta ) {
if (!_firstReading) {
if (rawReading.value < _lastRawValue.value)
reading.value = (rawReading.value + (maxValue - _lastRawValue.value)) * factor;
reading.value = (rawReading.value + ((int64_t)_deltaMax - _lastRawValue.value)) * factor;
else
reading.value = (rawReading.value - _lastRawValue.value) * factor;
} else {
......@@ -215,17 +218,15 @@ public:
*
* @param rawReading Reading struct with (usigned) value and timestamp to be stored.
* @param factor Scaling factor, which is applied to the reading value (optional)
* @param maxValue Maximum possible value of the reading; required for the
* delta computation to detect an overflow.
* @param storeGlobal Store reading in reading queue, so that it can get pushed.
*/
void storeReading(ureading_t rawReading, double factor=1.0, unsigned long long maxValue=ULLONG_MAX, bool storeGlobal=true) {
void storeReading(ureading_t rawReading, double factor=1.0, bool storeGlobal=true) {
reading_t reading;
reading.timestamp = rawReading.timestamp;
if( _delta ) {
if (!_firstReading) {
if (rawReading.value < _lastRawUValue.value)
reading.value = (rawReading.value + (maxValue - _lastRawUValue.value)) * factor;
reading.value = (rawReading.value + (_deltaMax - _lastRawUValue.value)) * factor;
else
reading.value = (rawReading.value - _lastRawUValue.value) * factor;
} else {
......@@ -278,14 +279,17 @@ public:
}
virtual void printConfig(LOG_LEVEL ll, LOGGER& lg, unsigned leadingSpaces=16) {
std::string leading(leadingSpaces, ' ');
LOG_VAR(ll) << leading << _name;
if (getSubsampling() != 1) {
LOG_VAR(ll) << leading << " SubSampling: " << getSubsampling();
}
LOG_VAR(ll) << leading << " Skip const values: " << (_skipConstVal ? "true" : "false");
LOG_VAR(ll) << leading << " Store delta only: " << (_delta ? "true" : "false");
LOG_VAR(ll) << leading << " Publish: " << (_publish ? "true" : "false");
std::string leading(leadingSpaces, ' ');
LOG_VAR(ll) << leading << _name;
if (getSubsampling() != 1) {
LOG_VAR(ll) << leading << " SubSampling: " << getSubsampling();
}
LOG_VAR(ll) << leading << " Skip const values: " << (_skipConstVal ? "true" : "false");
LOG_VAR(ll) << leading << " Store delta only: " << (_delta ? "true" : "false");
if(_delta) {
LOG_VAR(ll) << leading << " Maximum value: " << _deltaMax;
}
LOG_VAR(ll) << leading << " Publish: " << (_publish ? "true" : "false");
}
protected:
......@@ -299,6 +303,7 @@ protected:
unsigned int _subsamplingIndex;
std::unique_ptr<CacheEntry> _cache;
bool _delta;
uint64_t _deltaMax;
bool _firstReading;
ureading_t _lastRawUValue;
reading_t _lastRawValue;
......
......@@ -324,6 +324,7 @@ All the different plugins share some same general principles in common regarding
3. Sensors hold only those attributes which are necessary to uniquely identify the target sensor. Common base attributes:
* __mqttsuffix__ (to make its [mqtt-topic](#mqttTopic) unique)
* __delta__ (identifies a monotonic sensor. If set to "true", differences between successive readings are collected)
* __deltaMax__ (used only for monotonic sensors. Establishes the maximum wrap-around value for the accumulator. Default is LLONG_MAX.)
* __subSampling__ (subsampling factor S. If S>=1, only one reading every S is sent over MQTT, and the others are kept locally. If S<1, readings are never sent out and only kept locally)
* __publish__ (if set to "true", the sensor will be published when the auto-publish feature is enabled. Otherwise it is omitted. Default is "true".)
5. Be aware that naming of sensor/group/entity is not fixed. A plugin developer can name them as he likes, e.g. counter/multicounter/host.
......
......@@ -304,6 +304,8 @@ class ConfiguratorTemplate : public ConfiguratorInterface {
sBase.setSkipConstVal(to_bool(val.second.data()));
} else if (boost::iequals(val.first, "delta")) {
sBase.setDelta(to_bool(val.second.data()));
} else if (boost::iequals(val.first, "deltaMax")) {
sBase.setDeltaMaxValue(std::stoull(val.second.data()));
} else if (boost::iequals(val.first, "subSampling")) {
sBase.setSubsampling(std::stoi(val.second.data()));
} else if (boost::iequals(val.first, "publish")) {
......
......@@ -62,6 +62,7 @@ class GpfsmonSensorBase : public SensorBase {
GpfsmonSensorBase(const std::string &name)
: SensorBase(name), _metric_type(GPFS_METRIC::SIZE) {
setDelta(true);
setDeltaMaxValue(ULLONG_MAX);
}
virtual ~GpfsmonSensorBase() {
......
......@@ -44,10 +44,14 @@
*/
class MSRSensorBase : public SensorBase {
public:
static constexpr uint64_t MSR_MAXIMUM_SIZE = 281474976710656; //2^48
MSRSensorBase(const std::string &name)
: SensorBase(name), _cpu(0), _metric(0) {
//default delta to true, as msr has only monotonic sensors usually
_delta = true;
_deltaMax = MSR_MAXIMUM_SIZE;
}
MSRSensorBase(const MSRSensorBase &other) = default;
......
......@@ -47,7 +47,7 @@
#include <sstream>
#include <thread>
const uint64_t MSR_MAXIMUM_SIZE = 281474976710656; //2^48
MSRSensorGroup::MSRSensorGroup(const std::string &name)
: SensorGroupTemplate(name), _htAggregation(0) {
_total_number_cpus = std::thread::hardware_concurrency();
......@@ -133,7 +133,7 @@ void MSRSensorGroup::read() {
for (auto s : _sensors) {
auto ret_val = msr_read(s->getMetric(), &reading.value, s->getCpu());
if (ret_val != -1) {
s->storeReading(reading, 1, MSR_MAXIMUM_SIZE, !_htAggregation); //1 is no correction...
s->storeReading(reading, 1, !_htAggregation); //1 is no correction...
#ifdef DEBUG
LOG(debug) << _groupName << "::" << s->getName() << " raw reading: \"" << reading.value << "\"";
#endif
......
......@@ -79,6 +79,7 @@ class OpaSensorBase : public SensorBase {
_counterData(static_cast<PORT_COUNTER_DATA>(999)) {
//default delta to true, as opa has only monotonic sensors usually
_delta = true;
_deltaMax = ULLONG_MAX;
}
OpaSensorBase(const OpaSensorBase &other)
......
......@@ -45,7 +45,7 @@
*/
class PerfSensorBase : public SensorBase {
public:
static constexpr int64_t MAXCOUNTERVALUE = LLONG_MAX; //ToDo check if it is not LLONG_MAX, or make it configurable!
static constexpr uint64_t MAXCOUNTERVALUE = LLONG_MAX; //ToDo check if it is not LLONG_MAX, or make it configurable!
PerfSensorBase(const std::string &name)
: SensorBase(name),
......@@ -56,6 +56,7 @@ class PerfSensorBase : public SensorBase {
_id(0) {
//default delta to true, as perfevent has only monotonic sensors usually
_delta = true;
_deltaMax = MAXCOUNTERVALUE;
}
PerfSensorBase(const PerfSensorBase &other)
......
......@@ -314,7 +314,7 @@ void PerfSensorGroup::read() {
#endif
if (bin.lastValid) {
//storeReading takes care of delta computation and applies correction value on the result
s->storeReading(reading, correction, PerfSensorBase::MAXCOUNTERVALUE, !_htAggregation);
s->storeReading(reading, correction, !_htAggregation);
bin.latestValueValid = true;
} else {
//Before we can compute correct values again after an invalid reading we have to update the lastRawValue first
......
......@@ -53,6 +53,7 @@ class ProcfsSensorBase : public SensorBase {
_metric = "";
_perCPU = false;
_cpuId = -1;
_deltaMax = ULLONG_MAX;
}
ProcfsSensorBase(const std::string &name, const std::string &metric, bool percpu = false, int cpuid = -1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment