#FilterValues "1", "2"
Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
</Data>
+ <Data "lancom_stations_total">
+ Type "counter"
+ PluginInstance "stations_total"
+ Table true
+ Count true
+ Values "SNMPv2-SMI::enterprises.2356.11.1.3.32.1.10" # SNMPv2-SMI::enterprises.lancom-systems.lcos.lcsStatus.lcsStatusWlan.lcsStatusWlanStationTableTable.lcsStatusWlanStationTableEntry.lcsStatusWlanStationTableEntryState
+ </Data>
+ <Data "lancom_stations_connected">
+ Type "counter"
+ PluginInstance "stations_connected"
+ Table true
+ Count true
+ Values "SNMPv2-SMI::enterprises.2356.11.1.3.32.1.10" # SNMPv2-SMI::enterprises.lancom-systems.lcos.lcsStatus.lcsStatusWlan.lcsStatusWlanStationTableTable.lcsStatusWlanStationTableEntry.lcsStatusWlanStationTableEntryState
+ FilterOID "SNMPv2-SMI::enterprises.2356.11.1.3.32.1.10"
+ FilterValues "3" # eConnected
+ </Data>
<Host "some.switch.mydomain.org">
Address "192.168.0.2"
When B<Table> is set to B<true>, the OIDs given to B<Values>, B<TypeInstanceOID>,
B<PluginInstanceOID>, B<HostOID> and B<FilterOID> (see below) are queried using
-the C<GETNEXT> SNMP command until the subtree is left. After all
-the lists (think: all columns of the table) have been read B<several> values
-sets will be dispatches and, eventually, several files will be written. If you
+the C<GETNEXT> SNMP command until the subtree is left. After all the lists
+(think: all columns of the table) have been read, either (B<Count> set to B<false>)
+B<several> value sets will be dispatched and, eventually, several files will be
+written, or (B<Count> set to B<true>) one single value will be dispatched. If you
configure a B<Type> (see above) which needs more than one data source (for
example C<if_octets> which needs C<rx> and C<tx>) you will need to specify more
-than one (two, in the example case) OIDs with the B<Values> option. This has
-nothing to do with the B<Table> setting.
+than one (two, in the example case) OIDs with the B<Values> option and can't use
+the B<Count> option. This has nothing to do with the B<Table> setting.
For example, if you want to query the number of users on a system, you can use
C<HOST-RESOURCES-MIB::hrSystemNumUsers.0>. This is one value and belongs to one
Prefix may be set for values with use of appropriate B<TypeInstancePrefix>,
B<PluginInstancePrefix> and B<HostPrefix> options.
-When B<Table> is set to I<false> these options has no effect.
+When B<Table> is set to I<false> or B<Count> is set to I<true>, these options
+have no effect.
Defaults: When no one of these options is configured explicitly,
B<TypeInstanceOID> defaults to an empty string.
If set, I<String> is preprended to values received by querying the agent.
-When B<Table> is set to I<false> these options has no effect.
+When B<Table> is set to I<false> or B<Count> is set to I<true>, these options
+have no effect.
The C<UPS-MIB> is an example where you need this setting: It has voltages of
the inlets, outlets and the battery of an UPS. However, it doesn't provide a
value, e.E<nbsp>g. C<IF-MIB::ifInOctets.3> for the third counter of incoming
traffic.
+=item B<Count> I<true|false>
+
+Instead of dispatching one or multiple values per Table entry containing the
+I<OID>(s) given in the B<Values> option, just dispatch a single count giving the
+number of entries that would have been dispatched. This is especially useful when
+combined with the filtering options (see below) to count the number of entries in
+a Table matching certain criteria.
+
+When B<Table> is set to I<false>, this option has no effect.
+
=item B<Scale> I<Value>
The gauge-values returned by the SNMP-agent are multiplied by I<Value>. This
char **ignores;
size_t ignores_len;
bool invert_match;
+ bool count;
};
typedef struct data_definition_s data_definition_t;
status = cf_util_get_boolean(option, &t);
if (status == 0)
ignorelist_set_invert(dd->ignorelist, /* invert = */ !t);
- } else {
+ } else if (strcasecmp("Count", option->key) == 0)
+ status = cf_util_get_boolean(option, &dd->count);
+ else {
WARNING("snmp plugin: data %s: Option `%s' not allowed here.", dd->name,
option->key);
status = -1;
dd->name);
}
} else {
+ if (dd->count) {
+ WARNING("snmp plugin: data %s: Option `Count' is ignored when `Table' "
+ "set to `false'.",
+ dd->name);
+ }
+ }
+ if (!dd->is_table || dd->count) {
if (dd->plugin_instance.oid.oid_len > 0) {
WARNING("snmp plugin: data %s: Option `PluginInstanceOID' will be "
"ignored.",
}
if (dd->type_instance.prefix) {
WARNING("snmp plugin: data %s: Option `TypeInstancePrefix' is ignored "
- "when `Table' "
- "set to `false'.",
+ "when `Table' set to `false' or `Count' set to `true'.",
dd->name);
}
if (dd->plugin_instance.prefix) {
WARNING("snmp plugin: data %s: Option `PluginInstancePrefix' is "
- "ignored when "
- "`Table' set to `false'.",
+ "ignored when `Table' set to `false' or `Count' set to `true'.",
dd->name);
}
if (dd->host.prefix) {
WARNING(
"snmp plugin: data %s: Option `HostPrefix' is ignored when `Table' "
- "set to `false'.",
+ "set to `false' or `Count' set to `true'.",
dd->name);
}
}
csnmp_cell_char_t *plugin_instance_cells,
csnmp_cell_char_t *hostname_cells,
csnmp_cell_char_t *filter_cells,
- csnmp_cell_value_t **value_cells) {
+ csnmp_cell_value_t **value_cells,
+ bool count_values) {
const data_set_t *ds;
value_list_t vl = VALUE_LIST_INIT;
size_t i;
bool have_more;
oid_t current_suffix;
+ size_t count;
ds = plugin_get_ds(data->type);
if (!ds) {
ERROR("snmp plugin: DataSet `%s' not defined.", data->type);
return -1;
}
+ if (count_values) {
+ assert(ds->ds_num == 1);
+ count = 0;
+ } else
assert(ds->ds_num == data->values_len);
assert(data->values_len > 0);
continue;
}
+ if (count_values) {
+ count++;
+ } else {
/* set vl.host */
if (data->host.configured) {
char temp[DATA_MAX_NAME_LEN];
/* prevent leakage of pointer to local variable. */
vl.values_len = 0;
vl.values = NULL;
+ }
if (type_instance_cells != NULL)
type_instance_cell_ptr = type_instance_cell_ptr->next;
value_cell_ptr[0] = value_cell_ptr[0]->next;
} /* while (have_more) */
+ if (count_values) {
+ sstrncpy(vl.host, host->name, sizeof(vl.host));
+ sstrncpy(vl.plugin, data->plugin_name, sizeof(vl.plugin));
+ sstrncpy(vl.type, data->type, sizeof(vl.type));
+ if (data->type_instance.value)
+ sstrncpy(vl.type_instance, data->type_instance.value,
+ sizeof(vl.type_instance));
+ if (data->plugin_instance.value)
+ sstrncpy(vl.plugin_instance, data->plugin_instance.value,
+ sizeof(vl.plugin_instance));
+ vl.values_len = 1;
+ vl.values = malloc(sizeof(*vl.values));
+ if (vl.values == NULL)
+ return -1;
+ vl.values[0].counter = count;
+ plugin_dispatch_values(&vl);
+ sfree(vl.values);
+ }
+
return 0;
} /* int csnmp_dispatch_table */
return -1;
}
+ if (data->count) {
+ if (ds->ds_num != 1) {
+ ERROR("snmp plugin: DataSet `%s' requires %" PRIsz
+ " values, but `Count' option only delivers one",
+ data->type, ds->ds_num);
+ return -1;
+ }
+ /* the first `ds' means `data set', the second means `data source' */
+ if (ds->ds->type != DS_TYPE_COUNTER) {
+ ERROR("snmp plugin: DataSet `%s' needs to be of COUNTER"
+ " type for `Count' option",
+ data->type);
+ return -1;
+ }
+ } else {
if (ds->ds_num != data->values_len) {
ERROR("snmp plugin: DataSet `%s' requires %" PRIsz
" values, but config talks "
data->type, ds->ds_num, data->values_len);
return -1;
}
+ }
assert(data->values_len > 0);
for (i = 0; i < data->values_len; i++)
if (status == 0)
csnmp_dispatch_table(host, data, type_instance_cells_head,
plugin_instance_cells_head, hostname_cells_head,
- filter_cells_head, value_cells_head);
+ filter_cells_head, value_cells_head, data->count);
/* Free all allocated variables here */
while (type_instance_cells_head != NULL) {