=item B<GaugeAverage>
-Calculate the average.
+Calculate the average of all values matched during the interval.
=item B<GaugeMin>
-Use the smallest number only.
+Report the smallest value matched during the interval.
=item B<GaugeMax>
-Use the greatest number only.
+Report the greatest value matched during the interval.
=item B<GaugeLast>
-Use the last number found.
+Report the last value matched during the interval.
=item B<GaugePersist>
-Use the last number found. The number is not reset at the end of an interval.
-It is continously reported until another number is matched. This is intended
-for cases in which only state changes are reported, for example a thermometer
-that only reports the temperature when it changes.
+Report the last matching value. The metric is I<not> reset to C<NaN> at the end
+of an interval. It is continuously reported until another value is matched.
+This is intended for cases in which only state changes are reported, for
+example a thermometer that only reports the temperature when it changes.
=item B<CounterSet>
not use the matched subexpression, but simply count the number of matched
lines. Thus, you may use a regular expression without submatch in this case.
+B<GaugeInc> is reset to I<zero> after every read, unlike other B<Gauge*>
+metrics which are reset to C<NaN>.
+
=item B<Distribution>
Type to do calculations based on the distribution of values, primarily
point number, using L<strtod(3)>. The B<Counter*> and B<AbsoluteSet> types
interpret the submatch as an unsigned integer using L<strtoull(3)>. The
B<Derive*> types interpret the submatch as a signed integer using
-L<strtoll(3)>. B<CounterInc> and B<DeriveInc> do not use the submatch at all
-and it may be omitted in this case.
+L<strtoll(3)>. B<CounterInc>, B<DeriveInc> and B<GaugeInc> do not use the
+submatch at all and it may be omitted in this case.
+
+The B<Gauge*> types, unless noted otherwise, are reset to C<NaN> after being
+reported. In other words, B<GaugeAverage> reports the average of all values
+matched since the last metric was reported (or C<NaN> if there was no match).
=item B<Type> I<Type>
"SensorConfigFile", "UseLabels"};
static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+#if SENSORS_API_VERSION < 0x400
+typedef struct featurelist {
+ const sensors_chip_name *chip;
+ const sensors_feature_data *data;
+ int type;
+ struct featurelist *next;
+} featurelist_t;
+
+#ifndef SENSORS_CONF_PATH
+#define SENSORS_CONF_PATH "/etc/sensors.conf"
+#endif
+static char *conffile = SENSORS_CONF_PATH;
+/* #endif SENSORS_API_VERSION < 0x400 */
+
+#elif (SENSORS_API_VERSION >= 0x400)
typedef struct featurelist {
const sensors_chip_name *chip;
const sensors_feature *feature;
static char *conffile;
static bool use_labels;
+#endif
static featurelist_t *first_feature;
static ignorelist_t *sensor_list;
ignorelist_set_invert(sensor_list, 1);
if (IS_TRUE(value))
ignorelist_set_invert(sensor_list, 0);
- } else if (strcasecmp(key, "UseLabels") == 0) {
+ }
+#if (SENSORS_API_VERSION >= 0x400)
+ else if (strcasecmp(key, "UseLabels") == 0) {
use_labels = IS_TRUE(value);
- } else {
+ }
+#endif
+ else {
return -1;
}
return -1;
}
+#if SENSORS_API_VERSION < 0x400
+ chip_num = 0;
+ while ((chip = sensors_get_detected_chips(&chip_num)) != NULL) {
+ int feature_num0 = 0;
+ int feature_num1 = 0;
+
+ while (42) {
+ const sensors_feature_data *feature;
+ int feature_type;
+ featurelist_t *fl;
+
+ feature = sensors_get_all_features(*chip, &feature_num0, &feature_num1);
+
+ /* Check if all features have been read. */
+ if (feature == NULL)
+ break;
+
+ /* "master features" only */
+ if (feature->mapping != SENSORS_NO_MAPPING) {
+ DEBUG("sensors plugin: sensors_load_conf: "
+ "Ignoring subfeature `%s', "
+ "because (feature->mapping "
+ "!= SENSORS_NO_MAPPING).",
+ feature->name);
+ continue;
+ }
+
+ /* skip ignored in sensors.conf */
+ if (sensors_get_ignored(*chip, feature->number) == 0) {
+ DEBUG("sensors plugin: sensors_load_conf: "
+ "Ignoring subfeature `%s', "
+ "because "
+ "`sensors_get_ignored' told "
+ "me so.",
+ feature->name);
+ continue;
+ }
+
+ feature_type = sensors_feature_name_to_type(feature->name);
+ if (feature_type == SENSOR_TYPE_UNKNOWN) {
+ DEBUG("sensors plugin: sensors_load_conf: "
+ "Ignoring subfeature `%s', "
+ "because its type is "
+ "unknown.",
+ feature->name);
+ continue;
+ }
+
+ fl = calloc(1, sizeof(*fl));
+ if (fl == NULL) {
+ ERROR("sensors plugin: calloc failed.");
+ continue;
+ }
+
+ fl->chip = chip;
+ fl->data = feature;
+ fl->type = feature_type;
+
+ if (first_feature == NULL)
+ first_feature = fl;
+ else
+ last_feature->next = fl;
+ last_feature = fl;
+ } /* while sensors_get_all_features */
+ } /* while sensors_get_detected_chips */
+/* #endif SENSORS_API_VERSION < 0x400 */
+
+#elif (SENSORS_API_VERSION >= 0x400)
chip_num = 0;
while ((chip = sensors_get_detected_chips(NULL, &chip_num)) != NULL) {
const sensors_feature *feature;
} /* while (subfeature) */
} /* while (feature) */
} /* while (chip) */
+#endif /* (SENSORS_API_VERSION >= 0x400) */
if (first_feature == NULL) {
sensors_cleanup();
if (sensors_load_conf() != 0)
return -1;
+#if SENSORS_API_VERSION < 0x400
+ for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next) {
+ double value;
+ int status;
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
+
+ status = sensors_get_feature(*fl->chip, fl->data->number, &value);
+ if (status < 0)
+ continue;
+
+ status = sensors_snprintf_chip_name(plugin_instance,
+ sizeof(plugin_instance), fl->chip);
+ if (status < 0)
+ continue;
+
+ sstrncpy(type_instance, fl->data->name, sizeof(type_instance));
+
+ sensors_submit(plugin_instance, sensor_type_name_map[fl->type],
+ type_instance, value);
+ } /* for fl = first_feature .. NULL */
+/* #endif SENSORS_API_VERSION < 0x400 */
+
+#elif (SENSORS_API_VERSION >= 0x400)
for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next) {
double value;
int status;
sensors_submit(plugin_instance, type, type_instance, value);
} /* for fl = first_feature .. NULL */
+#endif /* (SENSORS_API_VERSION >= 0x400) */
return 0;
} /* int sensors_read */