snmp_la_SOURCES = src/snmp.c
snmp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBNETSNMP_CPPFLAGS)
snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBNETSNMP_LDFLAGS)
-snmp_la_LIBADD = $(BUILD_WITH_LIBNETSNMP_LIBS)
+snmp_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBNETSNMP_LIBS)
endif
if BUILD_PLUGIN_SNMP_AGENT
SAVE_CFLAGS="$CFLAGS"
CFLAGS="-Wall -Werror"
+SAVE_LDFAGS="$LDFLAGS"
+LDFLAGS=""
AC_CACHE_CHECK([for strtok_r],
[c_cv_have_strtok_r_default],
fi
CFLAGS="$SAVE_CFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
if test "x$c_cv_have_strtok_r_reentrant" = "xyes"; then
CFLAGS="$CFLAGS -D_REENTRANT=1"
fi
struct cb_view_s {
char *name;
- int qtypes;
- int resolver_stats;
- int cacherrsets;
+ _Bool qtypes;
+ _Bool resolver_stats;
+ _Bool cacherrsets;
char **zones;
size_t zones_num;
static bool config_parse_time = true;
static char *url;
-static int global_opcodes = 1;
-static int global_qtypes = 1;
-static int global_server_stats = 1;
-static int global_zone_maint_stats = 1;
-static int global_resolver_stats;
-static int global_memory_stats = 1;
+static _Bool global_opcodes = 1;
+static _Bool global_qtypes = 1;
+static _Bool global_server_stats = 1;
+static _Bool global_zone_maint_stats = 1;
+static _Bool global_resolver_stats;
+static _Bool global_memory_stats = 1;
static int timeout = -1;
static cb_view_t *views;
return ret;
} /* }}} int bind_xml */
-static int bind_config_set_bool(const char *name, int *var, /* {{{ */
- oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) {
- WARNING("bind plugin: The `%s' option needs "
- "exactly one boolean argument.",
- name);
- return -1;
- }
-
- if (ci->values[0].value.boolean)
- *var = 1;
- else
- *var = 0;
- return 0;
-} /* }}} int bind_config_set_bool */
-
static int bind_config_add_view_zone(cb_view_t *view, /* {{{ */
oconfig_item_t *ci) {
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
oconfig_item_t *child = ci->children + i;
if (strcasecmp("QTypes", child->key) == 0)
- bind_config_set_bool("QTypes", &tmp->qtypes, child);
+ cf_util_get_boolean(child, &tmp->qtypes);
else if (strcasecmp("ResolverStats", child->key) == 0)
- bind_config_set_bool("ResolverStats", &tmp->resolver_stats, child);
+ cf_util_get_boolean(child, &tmp->resolver_stats);
else if (strcasecmp("CacheRRSets", child->key) == 0)
- bind_config_set_bool("CacheRRSets", &tmp->cacherrsets, child);
+ cf_util_get_boolean(child, &tmp->cacherrsets);
else if (strcasecmp("Zone", child->key) == 0)
bind_config_add_view_zone(tmp, child);
else {
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Url", child->key) == 0) {
- if ((child->values_num != 1) ||
- (child->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("bind plugin: The `Url' option needs "
- "exactly one string argument.");
- return -1;
- }
-
- sfree(url);
- url = strdup(child->values[0].value.string);
+ cf_util_get_string(child, &url);
} else if (strcasecmp("OpCodes", child->key) == 0)
- bind_config_set_bool("OpCodes", &global_opcodes, child);
+ cf_util_get_boolean(child, &global_opcodes);
else if (strcasecmp("QTypes", child->key) == 0)
- bind_config_set_bool("QTypes", &global_qtypes, child);
+ cf_util_get_boolean(child, &global_qtypes);
else if (strcasecmp("ServerStats", child->key) == 0)
- bind_config_set_bool("ServerStats", &global_server_stats, child);
+ cf_util_get_boolean(child, &global_server_stats);
else if (strcasecmp("ZoneMaintStats", child->key) == 0)
- bind_config_set_bool("ZoneMaintStats", &global_zone_maint_stats, child);
+ cf_util_get_boolean(child, &global_zone_maint_stats);
else if (strcasecmp("ResolverStats", child->key) == 0)
- bind_config_set_bool("ResolverStats", &global_resolver_stats, child);
+ cf_util_get_boolean(child, &global_resolver_stats);
else if (strcasecmp("MemoryStats", child->key) == 0)
- bind_config_set_bool("MemoryStats", &global_memory_stats, child);
+ cf_util_get_boolean(child, &global_memory_stats);
else if (strcasecmp("View", child->key) == 0)
bind_config_add_view(child);
else if (strcasecmp("ParseTime", child->key) == 0)
Table true
Type "if_octets"
TypeInstanceOID "IF-MIB::ifDescr"
+ #FilterOID "IF-MIB::ifOperStatus"
+ #FilterValues "1", "2"
Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
</Data>
collectd. B<One> value list is dispatched and, eventually, one file will be
written.
-When B<Table> is set to B<true>, the OIDs given to B<Values> (see below) are
-queried using the C<GETNEXT> SNMP command until the subtree is left. After all
+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
configure a B<Type> (see above) which needs more than one data source (for
=item B<PluginInstanceOID> I<OID>
+=item B<HostOID> I<OID>
+
If B<Table> is set to I<true>, I<OID> is interpreted as an SNMP-prefix that will
-return a list of values. Those values are then used as the actual type-instance
-or plugin-instance of dispatched metrics. An example would be the
+return a list of values. Those values are then used as the actual type-instance,
+plugin-instance or host of dispatched metrics. An example would be the
C<IF-MIB::ifDescr> subtree. L<variables(5)> from the SNMP distribution describes
-the format of OIDs. When set to empty string, then "SUBID" will be used as the
-instance.
+the format of OIDs. When option is set to empty string, then "SUBID" will be used
+as the value.
-Prefix may be set for values with use of B<InstancePrefix> option.
+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.
-Only one of these options may be used in the same B<Data> block.
-
-Defaults:
+Defaults: When no one of these options is configured explicitly,
B<TypeInstanceOID> defaults to an empty string.
-B<PluginInstanceOID> is not configured.
+=item B<TypeInstancePrefix>
+
+=item B<PluginInstancePrefix>
+
+=item B<HostPrefix>
+
+These options are intented to be used together with B<TypeInstanceOID>,
+B<PluginInstanceOID> and B<HostOID> respectively.
+
+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.
+
+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
+descriptive column for these voltages. In this case having 1, 2,E<nbsp>... as
+instances is not enough, because the inlet voltages and outlet voltages may
+both have the subids 1, 2,E<nbsp>... You can use this setting to distinguish
+between the different voltages.
=item B<Instance> I<Instance>
=item B<InstancePrefix> I<String>
-If B<Table> is set to I<true>, you may feel the need to add something to the
-instance of the files. If set, I<String> is prepended to the instance as
-determined by querying the agent. When B<Table> is set to I<false> this option
-has 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
-descriptive column for these voltages. In this case having 1, 2,E<nbsp>... as
-instances is not enough, because the inlet voltages and outlet voltages may
-both have the subids 1, 2,E<nbsp>... You can use this setting to distinguish
-between the different voltages.
+Attention: this option exists for backwards compatibility only and will be
+removed in next major release. Please use B<TypeInstancePrefix> instead.
=item B<Values> I<OID> [I<OID> ...]
=item B<Ignore> I<Value> [, I<Value> ...]
-The ignore values allows one to ignore Instances based on their name and the
-patterns specified by the various values you've entered. The match is a
+The ignore values allows one to ignore TypeInstances based on their name and
+the patterns specified by the various values you've entered. The match is a
glob-type shell matching.
+When B<Table> is set to I<false> then this option has no effect.
+
=item B<InvertMatch> I<true|false(default)>
The invertmatch value should be use in combination of the Ignore option.
It changes the behaviour of the Ignore option, from a blacklist behaviour
when InvertMatch is set to false, to a whitelist when specified to true.
+=item B<FilterOID> I<OID>
+
+=item B<FilterValues> I<Value> [, I<Value> ...]
+
+=item B<FilterIgnoreSelected> I<true|false(default)>
+
+When B<Table> is set to I<true>, these options allow to configure filtering
+based on MIB values.
+
+The B<FilterOID> declares I<OID> to fill table column with values.
+The B<FilterValues> declares values list to do match. Whether table row will be
+collected or ignored depends on the B<FilterIgnoreSelected> setting.
+As with other plugins that use the daemon's ignorelist functionality, a string
+that starts and ends with a slash is interpreted as a regular expression.
+
+If no selection is configured at all, B<all> table rows are selected.
+
+When B<Table> is set to I<false> then these options has no effect.
+
+See B<Table> and F</"IGNORELISTS"> for details.
+
=back
=head2 The Host block
{
struct timespec ts = {0};
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
+ if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
perror("clock_gettime");
return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
# Table true
# Type "if_octets"
# TypeInstanceOID "IF-MIB::ifDescr"
-# #InstancePrefix "port"
+# #TypeInstancePrefix "port"
# Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
+# #FilterOID "IF-MIB::ifOperStatus"
+# #FilterValues "1", "2"
# </Data>
# <Data "interface_traffic">
# Table true
=head2 Plugin C<redis>
-The I<Redis plugin> connects to one or more Redis servers and gathers
-information about each server's state. For each server there is a I<Node> block
-which configures the connection parameters for this node.
+The I<Redis plugin> connects to one or more Redis servers, gathers
+information about each server's state and executes user-defined queries.
+For each server there is a I<Node> block which configures the connection
+parameters and set of user-defined queries for this node.
<Plugin redis>
<Node "example">
Host "localhost"
Port "6379"
Timeout 2000
+ ReportCommandStats false
+ ReportCpuUsage true
<Query "LLEN myqueue">
#Database 0
Type "queue_length"
Instance "myqueue"
- <Query>
+ </Query>
</Node>
</Plugin>
-The information shown in the synopsis above is the I<default configuration>
-which is used by the plugin if no configuration is present.
-
=over 4
=item B<Node> I<Nodename>
The B<Node> block identifies a new Redis node, that is a new Redis instance
running in an specified host and port. The name for node is a canonical
identifier which is used as I<plugin instance>. It is limited to
-64E<nbsp>characters in length.
+128E<nbsp>characters in length.
+
+When no B<Node> is configured explicitly, plugin connects to "localhost:6379".
=item B<Host> I<Hostname>
=item B<Timeout> I<Milliseconds>
The B<Timeout> option set the socket timeout for node response. Since the Redis
-read function is blocking, you should keep this value as low as possible. Keep
-in mind that the sum of all B<Timeout> values for all B<Nodes> should be lower
-than B<Interval> defined globally.
+read function is blocking, you should keep this value as low as possible.
+It is expected what B<Timeout> values should be lower than B<Interval> defined
+globally.
-=item B<Query> I<Querystring>
+Defaults to 2000 (2 seconds).
-The B<Query> block identifies a query to execute against the redis server.
-There may be an arbitrary number of queries to execute.
+=item B<ReportCommandStats> B<false>|B<true>
-=item B<Database> I<Index>
+Enables or disables reporting of statistics based on the command type, including
+rate of command calls and average CPU time consumed by command processing.
+Defaults to B<false>.
-This index selects the Redis logical database to use for query. Defaults
-to C<0>.
+=item B<ReportCpuUsage> B<true>|B<false>
+
+Enables or disables reporting of CPU consumption statistics.
+Defaults to B<true>.
+
+=item B<Query> I<Querystring>
+
+The B<Query> block identifies a query to execute against the redis server.
+There may be an arbitrary number of queries to execute. Each query should
+return single string or integer.
=item B<Type> I<Collectd type>
-Within a query definition, a valid collectd type to use as when submitting
+Within a query definition, a valid I<collectd type> to use as when submitting
the result of the query. When not supplied, will default to B<gauge>.
+Currently only types with one datasource are supported.
+See L<types.db(5)> for more details on types and their configuration.
+
=item B<Instance> I<Type instance>
Within a query definition, an optional type instance to use when submitting
the result of the query. When not supplied will default to the escaped
-command, up to 64 chars.
+command, up to 128 chars.
+
+=item B<Database> I<Index>
+
+This index selects the Redis logical database to use for query. Defaults
+to C<0>.
=back
continue;
if (((i + 1) >= buf_len) || (buf[i + 1] == 0)) {
- ERROR("string unescape: backslash found at end of string.");
+ P_ERROR("string unescape: backslash found at end of string.");
/* Ensure null-byte at the end of the buffer. */
buf[i] = 0;
return -1;
* behavior.
*/
if (fields[i][0] == '.') {
- ERROR("Cowardly refusing to create a directory that "
- "begins with a `.' (dot): `%s'",
- file_orig);
+ P_ERROR("Cowardly refusing to create a directory that "
+ "begins with a `.' (dot): `%s'",
+ file_orig);
return -2;
}
if (strjoin(dir + path_is_absolute,
(size_t)(sizeof(dir) - path_is_absolute), fields,
(size_t)(i + 1), "/") < 0) {
- ERROR("strjoin failed: `%s', component #%i", file_orig, i);
+ P_ERROR("strjoin failed: `%s', component #%i", file_orig, i);
return -1;
}
if (EEXIST == errno)
continue;
- ERROR("check_create_dir: mkdir (%s): %s", dir, STRERRNO);
+ P_ERROR("check_create_dir: mkdir (%s): %s", dir, STRERRNO);
return -1;
} else {
- ERROR("check_create_dir: stat (%s): %s", dir, STRERRNO);
+ P_ERROR("check_create_dir: stat (%s): %s", dir, STRERRNO);
return -1;
}
} else if (!S_ISDIR(statbuf.st_mode)) {
- ERROR("check_create_dir: `%s' exists but is not "
- "a directory!",
- dir);
+ P_ERROR("check_create_dir: `%s' exists but is not "
+ "a directory!",
+ dir);
return -1;
}
break;
*ksp_ptr = kstat_lookup(kc, module, instance, name);
if (*ksp_ptr == NULL) {
- ERROR("get_kstat: Cound not find kstat %s", ident);
+ P_ERROR("get_kstat: Cound not find kstat %s", ident);
return -1;
}
if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) {
- ERROR("get_kstat: kstat %s has wrong type", ident);
+ P_ERROR("get_kstat: kstat %s has wrong type", ident);
*ksp_ptr = NULL;
return -1;
}
#endif
if (kstat_read(kc, *ksp_ptr, NULL) == -1) {
- ERROR("get_kstat: kstat %s could not be read", ident);
+ P_ERROR("get_kstat: kstat %s could not be read", ident);
return -1;
}
if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) {
- ERROR("get_kstat: kstat %s has wrong type", ident);
+ P_ERROR("get_kstat: kstat %s has wrong type", ident);
return -1;
}
long long retval = -1LL;
if (ksp == NULL) {
- ERROR("get_kstat_value (\"%s\"): ksp is NULL.", name);
+ P_ERROR("get_kstat_value (\"%s\"): ksp is NULL.", name);
return -1LL;
} else if (ksp->ks_type != KSTAT_TYPE_NAMED) {
- ERROR("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
- "is not KSTAT_TYPE_NAMED (%#x).",
- name, (unsigned int)ksp->ks_type, (unsigned int)KSTAT_TYPE_NAMED);
+ P_ERROR("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
+ "is not KSTAT_TYPE_NAMED (%#x).",
+ name, (unsigned int)ksp->ks_type, (unsigned int)KSTAT_TYPE_NAMED);
return -1LL;
}
else if (kn->data_type == KSTAT_DATA_UINT64)
retval = (long long)kn->value.ui64; /* XXX: Might overflow! */
else
- WARNING("get_kstat_value: Not a numeric value: %s", name);
+ P_WARNING("get_kstat_value: Not a numeric value: %s", name);
return retval;
}
default:
sfree(value);
- ERROR("parse_value: Invalid data source type: %i.", ds_type);
+ P_ERROR("parse_value: Invalid data source type: %i.", ds_type);
return -1;
}
if (value == endptr) {
- ERROR("parse_value: Failed to parse string as %s: \"%s\".",
- DS_TYPE_TO_STRING(ds_type), value);
+ P_ERROR("parse_value: Failed to parse string as %s: \"%s\".",
+ DS_TYPE_TO_STRING(ds_type), value);
sfree(value);
return -1;
} else if ((NULL != endptr) && ('\0' != *endptr))
- INFO("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
- "Input string was \"%s\".",
- endptr, DS_TYPE_TO_STRING(ds_type), value_orig);
+ P_INFO("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
+ "Input string was \"%s\".",
+ endptr, DS_TYPE_TO_STRING(ds_type), value_orig);
sfree(value);
return 0;
failure = 0;
if ((dh = opendir(dir)) == NULL) {
- ERROR("walk_directory: Cannot open '%s': %s", dir, STRERRNO);
+ P_ERROR("walk_directory: Cannot open '%s': %s", dir, STRERRNO);
return -1;
}
ret = (ssize_t)fread(buf, 1, bufsize, fh);
if ((ret == 0) && (ferror(fh) != 0)) {
- ERROR("read_file_contents: Reading file \"%s\" failed.", filename);
+ P_ERROR("read_file_contents: Reading file \"%s\" failed.", filename);
ret = -1;
}
status = getaddrinfo(/* node = */ NULL, service_name, &ai_hints, &ai_list);
if (status != 0) {
- ERROR("service_name_to_port_number: getaddrinfo failed: %s",
- gai_strerror(status));
+ P_ERROR("service_name_to_port_number: getaddrinfo failed: %s",
+ gai_strerror(status));
return -1;
}
status = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype,
&(socklen_t){sizeof(socktype)});
if (status != 0) {
- WARNING("set_sock_opts: failed to determine socket type");
+ P_WARNING("set_sock_opts: failed to determine socket type");
return;
}
status =
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &(int){1}, sizeof(int));
if (status != 0)
- WARNING("set_sock_opts: failed to set socket keepalive flag");
+ P_WARNING("set_sock_opts: failed to set socket keepalive flag");
#ifdef TCP_KEEPIDLE
int tcp_keepidle = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 100 + 1);
status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepidle,
sizeof(tcp_keepidle));
if (status != 0)
- WARNING("set_sock_opts: failed to set socket tcp keepalive time");
+ P_WARNING("set_sock_opts: failed to set socket tcp keepalive time");
#endif
#ifdef TCP_KEEPINTVL
status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepintvl,
sizeof(tcp_keepintvl));
if (status != 0)
- WARNING("set_sock_opts: failed to set socket tcp keepalive interval");
+ P_WARNING("set_sock_opts: failed to set socket tcp keepalive interval");
#endif
}
} /* }}} void set_sock_opts */
return -1;
if (!(cap = cap_get_proc())) {
- ERROR("check_capability: cap_get_proc failed.");
+ P_ERROR("check_capability: cap_get_proc failed.");
return -1;
}
if (cap_get_flag(cap, cap_value, CAP_EFFECTIVE, &cap_flag_value) < 0) {
- ERROR("check_capability: cap_get_flag failed.");
+ P_ERROR("check_capability: cap_get_flag failed.");
cap_free(cap);
return -1;
}
#else
int check_capability(__attribute__((unused)) int arg) /* {{{ */
{
- WARNING("check_capability: unsupported capability implementation. "
- "Some plugin(s) may require elevated privileges to work properly.");
+ P_WARNING("check_capability: unsupported capability implementation. "
+ "Some plugin(s) may require elevated privileges to work properly.");
return 0;
} /* }}} int check_capability */
#endif /* HAVE_CAPABILITY */
}
static int dispatch_loadplugin(oconfig_item_t *ci) {
- const char *name;
bool global = false;
- plugin_ctx_t ctx = {0};
- plugin_ctx_t old_ctx;
- int ret_val;
assert(strcasecmp(ci->key, "LoadPlugin") == 0);
return -1;
}
- name = ci->values[0].value.string;
+ const char *name = ci->values[0].value.string;
if (strcmp("libvirt", name) == 0)
name = "virt";
/* default to the global interval set before loading this plugin */
- ctx.interval = cf_get_default_interval();
- ctx.flush_interval = 0;
- ctx.flush_timeout = 0;
+ plugin_ctx_t ctx = {
+ .interval = cf_get_default_interval(), .name = strdup(name),
+ };
+ if (ctx.name == NULL)
+ return ENOMEM;
for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *child = ci->children + i;
else {
WARNING("Ignoring unknown LoadPlugin option \"%s\" "
"for plugin \"%s\"",
- child->key, ci->values[0].value.string);
+ child->key, name);
}
}
- old_ctx = plugin_set_ctx(ctx);
- ret_val = plugin_load(name, global);
+ plugin_ctx_t old_ctx = plugin_set_ctx(ctx);
+ int ret_val = plugin_load(name, global);
/* reset to the "global" context */
plugin_set_ctx(old_ctx);
* success. */
int cf_util_get_string(const oconfig_item_t *ci, char **ret_string) /* {{{ */
{
- char *string;
-
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- ERROR("cf_util_get_string: The %s option requires "
- "exactly one string argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one string argument.", ci->key);
return -1;
}
- string = strdup(ci->values[0].value.string);
+ char *string = strdup(ci->values[0].value.string);
if (string == NULL)
return -1;
return EINVAL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- ERROR("cf_util_get_string_buffer: The %s option requires "
- "exactly one string argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one string argument.", ci->key);
return -1;
}
return EINVAL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- ERROR("cf_util_get_int: The %s option requires "
- "exactly one numeric argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key);
return -1;
}
return EINVAL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- ERROR("cf_util_get_double: The %s option requires "
- "exactly one numeric argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key);
return -1;
}
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN) &&
(ci->values[0].type != OCONFIG_TYPE_STRING))) {
- ERROR("cf_util_get_boolean: The %s option requires "
- "exactly one boolean argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one boolean argument.", ci->key);
return -1;
}
*ret_bool = ci->values[0].value.boolean ? true : false;
break;
case OCONFIG_TYPE_STRING:
- WARNING("cf_util_get_boolean: Using string value `%s' for boolean option "
- "`%s' is deprecated and will be removed in future releases. "
- "Use unquoted true or false instead.",
- ci->values[0].value.string, ci->key);
+ P_WARNING("Using string value `%s' for boolean option `%s' is deprecated "
+ "and will be removed in future releases. Use unquoted true or "
+ "false instead.",
+ ci->values[0].value.string, ci->key);
if (IS_TRUE(ci->values[0].value.string))
*ret_bool = true;
else if (IS_FALSE(ci->values[0].value.string))
*ret_bool = false;
else {
- ERROR("cf_util_get_boolean: Cannot parse string value `%s' of the `%s' "
- "option as a boolean value.",
- ci->values[0].value.string, ci->key);
+ P_ERROR("Cannot parse string value `%s' of the `%s' option as a boolean "
+ "value.",
+ ci->values[0].value.string, ci->key);
return -1;
}
break;
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
(ci->values[0].type != OCONFIG_TYPE_NUMBER))) {
- ERROR("cf_util_get_port_number: The \"%s\" option requires "
- "exactly one string argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one string argument.", ci->key);
return -1;
}
assert(ci->values[0].type == OCONFIG_TYPE_NUMBER);
tmp = (int)(ci->values[0].value.number + 0.5);
if ((tmp < 1) || (tmp > 65535)) {
- ERROR("cf_util_get_port_number: The \"%s\" option requires "
- "a service name or a port number. The number "
- "you specified, %i, is not in the valid "
- "range of 1-65535.",
- ci->key, tmp);
+ P_ERROR("The `%s' option requires a service name or a port number. The "
+ "number you specified, %i, is not in the valid range of 1-65535.",
+ ci->key, tmp);
return -1;
}
int status;
if (ci->values_num != 1) {
- ERROR("cf_util_get_service: The %s option requires exactly "
- "one argument.",
- ci->key);
+ P_ERROR("The `%s` option requires exactly one argument.", ci->key);
return -1;
}
if (ci->values[0].type == OCONFIG_TYPE_STRING)
return cf_util_get_string(ci, ret_string);
if (ci->values[0].type != OCONFIG_TYPE_NUMBER) {
- ERROR("cf_util_get_service: The %s option requires "
- "exactly one string or numeric argument.",
- ci->key);
+ P_ERROR("The `%s` option requires exactly one string or numeric argument.",
+ ci->key);
}
port = 0;
if (status != 0)
return status;
else if ((port < 1) || (port > 65535)) {
- ERROR("cf_util_get_service: The port number given "
- "for the %s option is out of "
- "range (%i).",
- ci->key, port);
+ P_ERROR("The port number given for the `%s` option is out of range (%i).",
+ ci->key, port);
return -1;
}
service = malloc(6);
if (service == NULL) {
- ERROR("cf_util_get_service: Out of memory.");
+ P_ERROR("cf_util_get_service: Out of memory.");
return -1;
}
snprintf(service, 6, "%i", port);
return EINVAL;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- ERROR("cf_util_get_cdtime: The %s option requires "
- "exactly one numeric argument.",
- ci->key);
+ P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key);
return -1;
}
if (ci->values[0].value.number < 0.0) {
- ERROR("cf_util_get_cdtime: The numeric argument of the %s "
- "option must not be negative.",
- ci->key);
+ P_ERROR("The numeric argument of the `%s' option must not be negative.",
+ ci->key);
return -1;
}
static int create_register_callback(llist_t **list, /* {{{ */
const char *name, void *callback,
user_data_t const *ud) {
- callback_func_t *cf;
- cf = calloc(1, sizeof(*cf));
+ if (name == NULL || callback == NULL)
+ return EINVAL;
+
+ callback_func_t *cf = calloc(1, sizeof(*cf));
if (cf == NULL) {
free_userdata(ud);
ERROR("plugin: create_register_callback: calloc failed.");
- return -1;
+ return ENOMEM;
}
cf->cf_callback = callback;
if (ud == NULL) {
- cf->cf_udata.data = NULL;
- cf->cf_udata.free_func = NULL;
+ cf->cf_udata = (user_data_t){
+ .data = NULL, .free_func = NULL,
+ };
} else {
cf->cf_udata = *ud;
}
callback_func_t *cf = le->value;
plugin_write_cb callback;
- /* do not switch plugin context; rather keep the context (interval)
- * information of the calling read plugin */
+ /* Keep the read plugin's interval and flush information but update the
+ * plugin name. */
+ plugin_ctx_t old_ctx = plugin_get_ctx();
+ plugin_ctx_t ctx = old_ctx;
+ ctx.name = cf->cf_ctx.name;
+ plugin_set_ctx(ctx);
DEBUG("plugin: plugin_write: Writing values via %s.", le->key);
callback = cf->cf_callback;
else
success++;
+ plugin_set_ctx(old_ctx);
le = le->next;
}
}
} /* void plugin_log */
+void daemon_log(int level, const char *format, ...) {
+ char msg[1024] = ""; // Size inherits from plugin_log()
+
+ char const *name = plugin_get_ctx().name;
+ if (name == NULL)
+ name = "UNKNOWN";
+
+ va_list ap;
+ va_start(ap, format);
+ vsnprintf(msg, sizeof(msg), format, ap);
+ va_end(ap);
+
+ plugin_log(level, "%s plugin: %s", name, msg);
+} /* void daemon_log */
+
int parse_log_severity(const char *severity) {
int log_level = -1;
typedef struct user_data_s user_data_t;
struct plugin_ctx_s {
+ char *name;
cdtime_t interval;
cdtime_t flush_interval;
cdtime_t flush_timeout;
#define DEBUG(...) /* noop */
#endif /* ! COLLECT_DEBUG */
+/* This will log messages, prefixed by plugin name */
+void daemon_log(int level, const char *format, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#define P_ERROR(...) daemon_log(LOG_ERR, __VA_ARGS__)
+#define P_WARNING(...) daemon_log(LOG_WARNING, __VA_ARGS__)
+#define P_NOTICE(...) daemon_log(LOG_NOTICE, __VA_ARGS__)
+#define P_INFO(...) daemon_log(LOG_INFO, __VA_ARGS__)
+
const data_set_t *plugin_get_ds(const char *name);
int plugin_notification_meta_add_string(notification_t *n, const char *name,
printf("plugin_log (%i, \"%s\");\n", level, buffer);
}
+void daemon_log(int level, char const *format, ...) {
+ char buffer[1024];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+
+ printf("daemon_log (%i, \"%s\");\n", level, buffer);
+}
+
void plugin_init_ctx(void) { /* nop */
}
return fc_config_set_instance(dir, ci->values[0].value.string);
} /* int fc_config_add_dir_instance */
-static int fc_config_add_dir_name(fc_directory_conf_t *dir,
- oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("filecount plugin: The `Name' config option needs exactly one "
- "string argument.");
- return -1;
- }
-
- char *temp = strdup(ci->values[0].value.string);
- if (temp == NULL) {
- ERROR("filecount plugin: strdup failed.");
- return -1;
- }
-
- sfree(dir->name);
- dir->name = temp;
-
- return 0;
-} /* int fc_config_add_dir_name */
-
static int fc_config_add_dir_mtime(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
else if (strcasecmp("Instance", option->key) == 0)
status = fc_config_add_dir_instance(dir, option);
else if (strcasecmp("Name", option->key) == 0)
- status = fc_config_add_dir_name(dir, option);
+ status = cf_util_get_string(option, &dir->name);
else if (strcasecmp("MTime", option->key) == 0)
status = fc_config_add_dir_mtime(dir, option);
else if (strcasecmp("Size", option->key) == 0)
* </Metric>
* </Plugin>
*/
-static int gmond_config_set_string(oconfig_item_t *ci, char **str) /* {{{ */
-{
- char *tmp;
-
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("gmond plugin: The `%s' option needs "
- "exactly one string argument.",
- ci->key);
- return -1;
- }
-
- tmp = strdup(ci->values[0].value.string);
- if (tmp == NULL) {
- ERROR("gmond plugin: strdup failed.");
- return -1;
- }
-
- sfree(*str);
- *str = tmp;
- return 0;
-} /* }}} int gmond_config_set_string */
-
static int gmond_config_add_metric(oconfig_item_t *ci) /* {{{ */
{
metric_map_t *map;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Type", child->key) == 0)
- gmond_config_set_string(child, &map->type);
+ cf_util_get_string(child, &map->type);
else if (strcasecmp("TypeInstance", child->key) == 0)
- gmond_config_set_string(child, &map->type_instance);
+ cf_util_get_string(child, &map->type_instance);
else if (strcasecmp("DataSource", child->key) == 0)
- gmond_config_set_string(child, &map->ds_name);
+ cf_util_get_string(child, &map->ds_name);
else {
WARNING("gmond plugin: Unknown configuration option `%s' ignored.",
child->key);
return 0;
} /* }}} int cmc_page_init_memc */
-static int cmc_config_add_string(const char *name, char **dest, /* {{{ */
- oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("memcachec plugin: `%s' needs exactly one string argument.", name);
- return -1;
- }
-
- sfree(*dest);
- *dest = strdup(ci->values[0].value.string);
- if (*dest == NULL)
- return -1;
-
- return 0;
-} /* }}} int cmc_config_add_string */
-
static int cmc_config_add_match_dstype(int *dstype_ret, /* {{{ */
oconfig_item_t *ci) {
int dstype;
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Regex", child->key) == 0)
- status = cmc_config_add_string("Regex", &match->regex, child);
+ status = cf_util_get_string(child, &match->regex);
else if (strcasecmp("ExcludeRegex", child->key) == 0)
- status =
- cmc_config_add_string("ExcludeRegex", &match->exclude_regex, child);
+ status = cf_util_get_string(child, &match->exclude_regex);
else if (strcasecmp("DSType", child->key) == 0)
status = cmc_config_add_match_dstype(&match->dstype, child);
else if (strcasecmp("Type", child->key) == 0)
- status = cmc_config_add_string("Type", &match->type, child);
+ status = cf_util_get_string(child, &match->type);
else if (strcasecmp("Instance", child->key) == 0)
- status = cmc_config_add_string("Instance", &match->instance, child);
+ status = cf_util_get_string(child, &match->instance);
else {
WARNING("memcachec plugin: Option `%s' not allowed here.", child->key);
status = -1;
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Server", child->key) == 0)
- status = cmc_config_add_string("Server", &page->server, child);
+ status = cf_util_get_string(child, &page->server);
else if (strcasecmp("Key", child->key) == 0)
- status = cmc_config_add_string("Key", &page->key, child);
+ status = cf_util_get_string(child, &page->key);
else if (strcasecmp("Plugin", child->key) == 0)
- status = cmc_config_add_string("Plugin", &page->plugin_name, child);
+ status = cf_util_get_string(child, &page->plugin_name);
else if (strcasecmp("Match", child->key) == 0)
/* Be liberal with failing matches => don't set `status'. */
cmc_config_add_match(page, child);
/*
* Configuration handling
*/
-/* Sets a given flag if the boolean argument is true and unsets the flag if it
- * is false. On error, the flag-field is not changed. */
-static int cna_config_bool_to_flag(const oconfig_item_t *ci, /* {{{ */
- uint32_t *flags, uint32_t flag) {
- if ((ci == NULL) || (flags == NULL))
- return EINVAL;
-
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) {
- WARNING("netapp plugin: The %s option needs exactly one boolean argument.",
- ci->key);
- return -1;
- }
-
- if (ci->values[0].value.boolean)
- *flags |= flag;
- else
- *flags &= ~flag;
-
- return 0;
-} /* }}} int cna_config_bool_to_flag */
-
-/* Handling of the "Interval" option which is allowed in every block. */
-static int cna_config_get_interval(const oconfig_item_t *ci, /* {{{ */
- cna_interval_t *out_interval) {
- cdtime_t tmp = 0;
- int status;
-
- status = cf_util_get_cdtime(ci, &tmp);
- if (status != 0)
- return status;
-
- out_interval->interval = tmp;
- out_interval->last_read = 0;
-
- return 0;
-} /* }}} int cna_config_get_interval */
/* Handling of the "GetIO", "GetOps" and "GetLatency" options within a
* <VolumePerf /> block. */
/* if (!item || !item->key || !*item->key) continue; */
if (strcasecmp(item->key, "Interval") == 0)
- cna_config_get_interval(item, &cfg_volume_perf->interval);
+ cf_util_get_cdtime(item, &cfg_volume_perf->interval.interval);
else if (!strcasecmp(item->key, "GetIO"))
cna_config_volume_perf_option(cfg_volume_perf, item);
else if (!strcasecmp(item->key, "GetOps"))
oconfig_item_t *item = ci->children + i;
if (strcasecmp(item->key, "Interval") == 0)
- cna_config_get_interval(item, &cfg_quota->interval);
+ cf_util_get_cdtime(item, &cfg_quota->interval.interval);
else
WARNING("netapp plugin: The option %s is not allowed within "
"`Quota' blocks.",
/* if (!item || !item->key || !*item->key) continue; */
if (strcasecmp(item->key, "Interval") == 0)
- cna_config_get_interval(item, &cfg_disk->interval);
+ cf_util_get_cdtime(item, &cfg_disk->interval.interval);
else if (strcasecmp(item->key, "GetBusy") == 0)
- cna_config_bool_to_flag(item, &cfg_disk->flags, CFG_DISK_BUSIEST);
+ cf_util_get_flag(item, &cfg_disk->flags, CFG_DISK_BUSIEST);
}
if ((cfg_disk->flags & CFG_DISK_ALL) == 0) {
oconfig_item_t *item = ci->children + i;
if (strcasecmp(item->key, "Interval") == 0)
- cna_config_get_interval(item, &cfg_wafl->interval);
+ cf_util_get_cdtime(item, &cfg_wafl->interval.interval);
else if (!strcasecmp(item->key, "GetNameCache"))
- cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_NAME_CACHE);
+ cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_NAME_CACHE);
else if (!strcasecmp(item->key, "GetDirCache"))
- cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_DIR_CACHE);
+ cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_DIR_CACHE);
else if (!strcasecmp(item->key, "GetBufferCache"))
- cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_BUF_CACHE);
+ cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_BUF_CACHE);
else if (!strcasecmp(item->key, "GetInodeCache"))
- cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_INODE_CACHE);
+ cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_INODE_CACHE);
else
WARNING("netapp plugin: The %s config option is not allowed within "
"`WAFL' blocks.",
/* if (!item || !item->key || !*item->key) continue; */
if (strcasecmp(item->key, "Interval") == 0)
- cna_config_get_interval(item, &cfg_volume_usage->interval);
+ cf_util_get_cdtime(item, &cfg_volume_usage->interval.interval);
else if (!strcasecmp(item->key, "GetCapacity"))
cna_config_volume_usage_option(cfg_volume_usage, item);
else if (!strcasecmp(item->key, "GetSnapshot"))
oconfig_item_t *item = ci->children + i;
if (strcasecmp(item->key, "Interval") == 0)
- cna_config_get_interval(item, &cfg_snapvault->interval);
+ cf_util_get_cdtime(item, &cfg_snapvault->interval.interval);
else
WARNING("netapp plugin: The option %s is not allowed within "
"`SnapVault' blocks.",
oconfig_item_t *item = ci->children + i;
if (strcasecmp(item->key, "Interval") == 0) {
- cna_config_get_interval(item, &cfg_system->interval);
+ cf_util_get_cdtime(item, &cfg_system->interval.interval);
} else if (!strcasecmp(item->key, "GetCPULoad")) {
- cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_CPU);
+ cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_CPU);
} else if (!strcasecmp(item->key, "GetInterfaces")) {
- cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_NET);
+ cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_NET);
} else if (!strcasecmp(item->key, "GetDiskOps")) {
- cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_OPS);
+ cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_OPS);
} else if (!strcasecmp(item->key, "GetDiskIO")) {
- cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_DISK);
+ cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_DISK);
} else {
WARNING("netapp plugin: The %s config option is not allowed within "
"`System' blocks.",
char subject[MAXSTRING];
char buf[4096] = "";
+ char *buf_ptr = buf;
int buf_len = sizeof(buf);
- int i;
snprintf(severity, sizeof(severity), "%s",
(n->severity == NOTIF_FAILURE)
timestamp_str[sizeof(timestamp_str) - 1] = '\0';
/* Let's make RFC822 message text with \r\n EOLs */
- snprintf(buf, buf_len, "MIME-Version: 1.0\r\n"
- "Content-Type: text/plain; charset=\"US-ASCII\"\r\n"
- "Content-Transfer-Encoding: 8bit\r\n"
- "Subject: %s\r\n"
- "\r\n"
- "%s - %s@%s\r\n"
- "\r\n"
- "Message: %s",
- subject, timestamp_str, severity, n->host, n->message);
+ int status = snprintf(buf, buf_len,
+ "MIME-Version: 1.0\r\n"
+ "Content-Type: text/plain; charset=\"US-ASCII\"\r\n"
+ "Content-Transfer-Encoding: 8bit\r\n"
+ "Subject: %s\r\n"
+ "\r\n"
+ "%s - %s@%s\r\n"
+ "\r\n",
+ subject, timestamp_str, severity, n->host);
+
+ if (status > 0) {
+ buf_ptr += status;
+ buf_len -= status;
+ }
+
+#define APPEND(format, value) \
+ if ((buf_len > 0) && (strlen(value) > 0)) { \
+ status = snprintf(buf_ptr, buf_len, format "\r\n", value); \
+ if (status > 0) { \
+ buf_ptr += status; \
+ buf_len -= status; \
+ } \
+ }
+
+ APPEND("Host: %s", n->host);
+ APPEND("Plugin: %s", n->plugin);
+ APPEND("Plugin instance: %s", n->plugin_instance);
+ APPEND("Type: %s", n->type);
+ APPEND("Type instance: %s", n->type_instance);
+ APPEND("\r\nMessage: %s", n->message);
pthread_mutex_lock(&session_lock);
smtp_set_header(message, "To", NULL, NULL);
smtp_set_message_str(message, buf);
- for (i = 0; i < recipients_len; i++)
+ for (int i = 0; i < recipients_len; i++)
smtp_add_recipient(message, recipients[i]);
/* Initiate a connection to the SMTP server and transfer the message. */
#include <hiredis/hiredis.h>
#include <sys/time.h>
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
-#endif
-
#define REDIS_DEF_HOST "localhost"
#define REDIS_DEF_PASSWD ""
#define REDIS_DEF_PORT 6379
-#define REDIS_DEF_TIMEOUT 2000
+#define REDIS_DEF_TIMEOUT_SEC 2
#define REDIS_DEF_DB_COUNT 256
-#define MAX_REDIS_NODE_NAME 64
-#define MAX_REDIS_PASSWD_LENGTH 512
#define MAX_REDIS_VAL_SIZE 256
#define MAX_REDIS_QUERY 2048
struct redis_node_s;
typedef struct redis_node_s redis_node_t;
struct redis_node_s {
- char name[MAX_REDIS_NODE_NAME];
- char host[HOST_NAME_MAX];
- char passwd[MAX_REDIS_PASSWD_LENGTH];
+ char *name;
+ char *host;
+ char *passwd;
int port;
struct timeval timeout;
+ bool report_command_stats;
+ bool report_cpu_usage;
+ redisContext *redisContext;
redis_query_t *queries;
redis_node_t *next;
};
-static redis_node_t *nodes_head;
+static bool redis_have_instances;
+static int redis_read(user_data_t *user_data);
-static int redis_node_add(const redis_node_t *rn) /* {{{ */
-{
- redis_node_t *rn_copy;
- redis_node_t *rn_ptr;
+static void redis_node_free(void *arg) {
+ redis_node_t *rn = arg;
+ if (rn == NULL)
+ return;
- /* Check for duplicates first */
- for (rn_ptr = nodes_head; rn_ptr != NULL; rn_ptr = rn_ptr->next)
- if (strcmp(rn->name, rn_ptr->name) == 0)
- break;
-
- if (rn_ptr != NULL) {
- ERROR("redis plugin: A node with the name `%s' already exists.", rn->name);
- return -1;
+ redis_query_t *rq = rn->queries;
+ while (rq != NULL) {
+ redis_query_t *next = rq->next;
+ sfree(rq);
+ rq = next;
}
- rn_copy = malloc(sizeof(*rn_copy));
- if (rn_copy == NULL) {
- ERROR("redis plugin: malloc failed adding redis_node to the tree.");
- return -1;
- }
-
- memcpy(rn_copy, rn, sizeof(*rn_copy));
- rn_copy->next = NULL;
+ redisFree(rn->redisContext);
+ sfree(rn->name);
+ sfree(rn->host);
+ sfree(rn->passwd);
+ sfree(rn);
+} /* void redis_node_free */
+static int redis_node_add(redis_node_t *rn) /* {{{ */
+{
DEBUG("redis plugin: Adding node \"%s\".", rn->name);
- if (nodes_head == NULL)
- nodes_head = rn_copy;
- else {
- rn_ptr = nodes_head;
- while (rn_ptr->next != NULL)
- rn_ptr = rn_ptr->next;
- rn_ptr->next = rn_copy;
- }
+ /* Disable automatic generation of default instance in the init callback. */
+ redis_have_instances = true;
- return 0;
+ char cb_name[sizeof("redis/") + DATA_MAX_NAME_LEN];
+ snprintf(cb_name, sizeof(cb_name), "redis/%s", rn->name);
+
+ return plugin_register_complex_read(
+ /* group = */ "redis",
+ /* name = */ cb_name,
+ /* callback = */ redis_read,
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = rn, .free_func = redis_node_free,
+ });
} /* }}} */
static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */
static int redis_config_node(oconfig_item_t *ci) /* {{{ */
{
- redis_query_t *rq;
- int status;
- int timeout;
+ redis_node_t *rn = calloc(1, sizeof(*rn));
+ if (rn == NULL) {
+ ERROR("redis plugin: calloc failed adding node.");
+ return ENOMEM;
+ }
- redis_node_t rn = {.port = REDIS_DEF_PORT,
- .timeout.tv_usec = REDIS_DEF_TIMEOUT};
+ rn->port = REDIS_DEF_PORT;
+ rn->timeout.tv_sec = REDIS_DEF_TIMEOUT_SEC;
+ rn->report_cpu_usage = true;
- sstrncpy(rn.host, REDIS_DEF_HOST, sizeof(rn.host));
+ rn->host = strdup(REDIS_DEF_HOST);
+ if (rn->host == NULL) {
+ ERROR("redis plugin: strdup failed adding node.");
+ sfree(rn);
+ return ENOMEM;
+ }
- status = cf_util_get_string_buffer(ci, rn.name, sizeof(rn.name));
- if (status != 0)
+ int status = cf_util_get_string(ci, &rn->name);
+ if (status != 0) {
+ sfree(rn->host);
+ sfree(rn);
return status;
+ }
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
if (strcasecmp("Host", option->key) == 0)
- status = cf_util_get_string_buffer(option, rn.host, sizeof(rn.host));
+ status = cf_util_get_string(option, &rn->host);
else if (strcasecmp("Port", option->key) == 0) {
status = cf_util_get_port_number(option);
if (status > 0) {
- rn.port = status;
+ rn->port = status;
status = 0;
}
} else if (strcasecmp("Query", option->key) == 0) {
- rq = redis_config_query(option);
+ redis_query_t *rq = redis_config_query(option);
if (rq == NULL) {
status = 1;
} else {
- rq->next = rn.queries;
- rn.queries = rq;
+ rq->next = rn->queries;
+ rn->queries = rq;
}
} else if (strcasecmp("Timeout", option->key) == 0) {
+ int timeout;
status = cf_util_get_int(option, &timeout);
- if (status == 0)
- rn.timeout.tv_usec = timeout;
+ if (status == 0) {
+ rn->timeout.tv_usec = timeout * 1000;
+ rn->timeout.tv_sec = rn->timeout.tv_usec / 1000000L;
+ rn->timeout.tv_usec %= 1000000L;
+ }
} else if (strcasecmp("Password", option->key) == 0)
- status = cf_util_get_string_buffer(option, rn.passwd, sizeof(rn.passwd));
+ status = cf_util_get_string(option, &rn->passwd);
+ else if (strcasecmp("ReportCommandStats", option->key) == 0)
+ status = cf_util_get_boolean(option, &rn->report_command_stats);
+ else if (strcasecmp("ReportCpuUsage", option->key) == 0)
+ status = cf_util_get_boolean(option, &rn->report_cpu_usage);
else
WARNING("redis plugin: Option `%s' not allowed inside a `Node' "
"block. I'll ignore this option.",
break;
}
- if (status != 0)
+ if (status != 0) {
+ redis_node_free(rn);
return status;
+ }
- return redis_node_add(&rn);
+ return redis_node_add(rn);
} /* }}} int redis_config_node */
static int redis_config(oconfig_item_t *ci) /* {{{ */
option->key);
}
- if (nodes_head == NULL) {
- ERROR("redis plugin: No valid node configuration could be found.");
- return ENOENT;
- }
-
return 0;
} /* }}} */
__attribute__((nonnull(2))) static void
-redis_submit(char *plugin_instance, const char *type, const char *type_instance,
- value_t value) /* {{{ */
+redis_submit(const char *plugin_instance, const char *type,
+ const char *type_instance, value_t value) /* {{{ */
{
value_list_t vl = VALUE_LIST_INIT;
plugin_dispatch_values(&vl);
} /* }}} */
+__attribute__((nonnull(2))) static void
+redis_submit2(const char *plugin_instance, const char *type,
+ const char *type_instance, value_t value0,
+ value_t value1) /* {{{ */
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ value_t values[] = {value0, value1};
+
+ vl.values = values;
+ vl.values_len = STATIC_ARRAY_SIZE(values);
+
+ sstrncpy(vl.plugin, "redis", sizeof(vl.plugin));
+ sstrncpy(vl.type, type, sizeof(vl.type));
+
+ if (plugin_instance != NULL)
+ sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
+
+ if (type_instance != NULL)
+ sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
+
+ plugin_dispatch_values(&vl);
+} /* }}} */
+
static int redis_init(void) /* {{{ */
{
- redis_node_t rn = {.name = "default",
- .host = REDIS_DEF_HOST,
- .port = REDIS_DEF_PORT,
- .timeout.tv_sec = 0,
- .timeout.tv_usec = REDIS_DEF_TIMEOUT,
- .next = NULL};
+ if (redis_have_instances)
+ return 0;
- if (nodes_head == NULL)
- redis_node_add(&rn);
+ redis_node_t *rn = calloc(1, sizeof(*rn));
+ if (rn == NULL)
+ return ENOMEM;
- return 0;
+ rn->port = REDIS_DEF_PORT;
+ rn->timeout.tv_sec = REDIS_DEF_TIMEOUT_SEC;
+
+ rn->name = strdup("default");
+ rn->host = strdup(REDIS_DEF_HOST);
+
+ if (rn->name == NULL || rn->host == NULL) {
+ sfree(rn->name);
+ sfree(rn->host);
+ sfree(rn);
+ return ENOMEM;
+ }
+
+ return redis_node_add(rn);
} /* }}} int redis_init */
-static int redis_handle_info(char *node, char const *info_line,
- char const *type, char const *type_instance,
- char const *field_name, int ds_type) /* {{{ */
-{
+static void *c_redisCommand(redis_node_t *rn, const char *format, ...) {
+ redisContext *c = rn->redisContext;
+
+ if (c == NULL)
+ return NULL;
+
+ va_list ap;
+ va_start(ap, format);
+ void *reply = redisvCommand(c, format, ap);
+ va_end(ap);
+
+ if (reply == NULL) {
+ ERROR("redis plugin: Connection error: %s", c->errstr);
+ redisFree(rn->redisContext);
+ rn->redisContext = NULL;
+ }
+
+ return reply;
+} /* void c_redisCommand */
+
+static int redis_get_info_value(char const *info_line, char const *field_name,
+ int ds_type, value_t *val) {
char *str = strstr(info_line, field_name);
static char buf[MAX_REDIS_VAL_SIZE];
- value_t val;
if (str) {
int i;
buf[i] = *str;
buf[i] = '\0';
- if (parse_value(buf, &val, ds_type) == -1) {
+ if (parse_value(buf, val, ds_type) == -1) {
WARNING("redis plugin: Unable to parse field `%s'.", field_name);
return -1;
}
- redis_submit(node, type, type_instance, val);
return 0;
}
return -1;
+} /* int redis_get_info_value */
+static int redis_handle_info(char *node, char const *info_line,
+ char const *type, char const *type_instance,
+ char const *field_name, int ds_type) /* {{{ */
+{
+ value_t val;
+ if (redis_get_info_value(info_line, field_name, ds_type, &val) != 0)
+ return -1;
+
+ redis_submit(node, type, type_instance, val);
+ return 0;
} /* }}} int redis_handle_info */
-static int redis_handle_query(redisContext *rh, redis_node_t *rn,
- redis_query_t *rq) /* {{{ */
+static int redis_handle_query(redis_node_t *rn, redis_query_t *rq) /* {{{ */
{
redisReply *rr;
const data_set_t *ds;
ds = plugin_get_ds(rq->type);
if (!ds) {
- ERROR("redis plugin: DataSet `%s' not defined.", rq->type);
+ ERROR("redis plugin: DS type `%s' not defined.", rq->type);
return -1;
}
if (ds->ds_num != 1) {
- ERROR("redis plugin: DS `%s' has too many types.", rq->type);
+ ERROR("redis plugin: DS type `%s' has too many datasources. This is not "
+ "supported currently.",
+ rq->type);
return -1;
}
- if ((rr = redisCommand(rh, "SELECT %d", rq->database)) == NULL) {
+ if ((rr = c_redisCommand(rn, "SELECT %d", rq->database)) == NULL) {
WARNING("redis plugin: unable to switch to database `%d' on node `%s'.",
rq->database, rn->name);
return -1;
}
- if ((rr = redisCommand(rh, rq->query)) == NULL) {
+ if ((rr = c_redisCommand(rn, rq->query)) == NULL) {
WARNING("redis plugin: unable to carry out query `%s'.", rq->query);
return -1;
}
break;
case REDIS_REPLY_STRING:
if (parse_value(rr->str, &val, ds->ds[0].type) == -1) {
- WARNING("redis plugin: Unable to parse field `%s'.", rq->type);
+ WARNING("redis plugin: Query `%s': Unable to parse value.", rq->query);
freeReplyObject(rr);
return -1;
}
break;
+ case REDIS_REPLY_ERROR:
+ WARNING("redis plugin: Query `%s' failed: %s.", rq->query, rr->str);
+ freeReplyObject(rr);
+ return -1;
+ case REDIS_REPLY_ARRAY:
+ WARNING("redis plugin: Query `%s' should return string or integer. Arrays "
+ "are not supported.",
+ rq->query);
+ freeReplyObject(rr);
+ return -1;
default:
- WARNING("redis plugin: Cannot coerce redis type.");
+ WARNING("redis plugin: Query `%s': Cannot coerce redis type (%i).",
+ rq->query, rr->type);
freeReplyObject(rr);
return -1;
}
return 0;
} /* }}} int redis_handle_query */
-static int redis_db_stats(char *node, char const *info_line) /* {{{ */
+static int redis_db_stats(const char *node, char const *info_line) /* {{{ */
{
/* redis_db_stats parses and dispatches Redis database statistics,
* currently the number of keys for each database.
} /* }}} int redis_db_stats */
-static int redis_read(void) /* {{{ */
-{
- for (redis_node_t *rn = nodes_head; rn != NULL; rn = rn->next) {
- redisContext *rh;
+static void redis_cpu_usage(const char *node, char const *info_line) {
+ while (42) {
+ value_t rusage_user;
+ value_t rusage_syst;
+
+ if (redis_get_info_value(info_line, "used_cpu_user", DS_TYPE_GAUGE,
+ &rusage_user) != 0)
+ break;
+
+ if (redis_get_info_value(info_line, "used_cpu_sys", DS_TYPE_GAUGE,
+ &rusage_syst) != 0)
+ break;
+
+ redis_submit2(node, "ps_cputime", "daemon",
+ (value_t){.derive = rusage_user.gauge * 1000000},
+ (value_t){.derive = rusage_syst.gauge * 1000000});
+ break;
+ }
+
+ while (42) {
+ value_t rusage_user;
+ value_t rusage_syst;
+
+ if (redis_get_info_value(info_line, "used_cpu_user_children", DS_TYPE_GAUGE,
+ &rusage_user) != 0)
+ break;
+
+ if (redis_get_info_value(info_line, "used_cpu_sys_children", DS_TYPE_GAUGE,
+ &rusage_syst) != 0)
+ break;
+
+ redis_submit2(node, "ps_cputime", "children",
+ (value_t){.derive = rusage_user.gauge * 1000000},
+ (value_t){.derive = rusage_syst.gauge * 1000000});
+ break;
+ }
+} /* void redis_cpu_usage */
+
+static void redis_check_connection(redis_node_t *rn) {
+ if (rn->redisContext)
+ return;
+
+ redisContext *rh = redisConnectWithTimeout(rn->host, rn->port, rn->timeout);
+
+ if (rh == NULL) {
+ ERROR("redis plugin: can't allocate redis context");
+ return;
+ }
+ if (rh->err) {
+ ERROR("redis plugin: unable to connect to node `%s' (%s:%d): %s.", rn->name,
+ rn->host, rn->port, rh->errstr);
+ redisFree(rh);
+ return;
+ }
+
+ rn->redisContext = rh;
+
+ if (rn->passwd) {
redisReply *rr;
- DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name,
- rn->host, rn->port);
+ DEBUG("redis plugin: authenticating node `%s' passwd(%s).", rn->name,
+ rn->passwd);
- rh = redisConnectWithTimeout((char *)rn->host, rn->port, rn->timeout);
- if (rh == NULL) {
- ERROR("redis plugin: unable to connect to node `%s' (%s:%d).", rn->name,
- rn->host, rn->port);
- continue;
+ if ((rr = c_redisCommand(rn, "AUTH %s", rn->passwd)) == NULL) {
+ WARNING("redis plugin: unable to authenticate on node `%s'.", rn->name);
+ return;
}
- if (strlen(rn->passwd) > 0) {
- DEBUG("redis plugin: authenticating node `%s' passwd(%s).", rn->name,
- rn->passwd);
+ if (rr->type != REDIS_REPLY_STATUS) {
+ WARNING("redis plugin: invalid authentication on node `%s'.", rn->name);
+ freeReplyObject(rr);
+ redisFree(rn->redisContext);
+ rn->redisContext = NULL;
+ return;
+ }
- if ((rr = redisCommand(rh, "AUTH %s", rn->passwd)) == NULL) {
- WARNING("redis plugin: unable to authenticate on node `%s'.", rn->name);
- goto redis_fail;
- }
+ freeReplyObject(rr);
+ }
+ return;
+} /* void redis_check_connection */
- if (rr->type != REDIS_REPLY_STATUS) {
- WARNING("redis plugin: invalid authentication on node `%s'.", rn->name);
- goto redis_fail;
- }
+static void redis_read_server_info(redis_node_t *rn) {
+ redisReply *rr;
- freeReplyObject(rr);
+ if ((rr = c_redisCommand(rn, "INFO")) == NULL) {
+ WARNING("redis plugin: unable to get INFO from node `%s'.", rn->name);
+ return;
+ }
+
+ redis_handle_info(rn->name, rr->str, "uptime", NULL, "uptime_in_seconds",
+ DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "current_connections", "clients",
+ "connected_clients", DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "blocked_clients", NULL,
+ "blocked_clients", DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "memory", NULL, "used_memory",
+ DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "memory_lua", NULL, "used_memory_lua",
+ DS_TYPE_GAUGE);
+ /* changes_since_last_save: Deprecated in redis version 2.6 and above */
+ redis_handle_info(rn->name, rr->str, "volatile_changes", NULL,
+ "changes_since_last_save", DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "total_connections", NULL,
+ "total_connections_received", DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "total_operations", NULL,
+ "total_commands_processed", DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "operations_per_second", NULL,
+ "instantaneous_ops_per_sec", DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "expired_keys", NULL, "expired_keys",
+ DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "evicted_keys", NULL, "evicted_keys",
+ DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "pubsub", "channels", "pubsub_channels",
+ DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "pubsub", "patterns", "pubsub_patterns",
+ DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "current_connections", "slaves",
+ "connected_slaves", DS_TYPE_GAUGE);
+ redis_handle_info(rn->name, rr->str, "cache_result", "hits", "keyspace_hits",
+ DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "cache_result", "misses",
+ "keyspace_misses", DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "total_bytes", "input",
+ "total_net_input_bytes", DS_TYPE_DERIVE);
+ redis_handle_info(rn->name, rr->str, "total_bytes", "output",
+ "total_net_output_bytes", DS_TYPE_DERIVE);
+
+ redis_db_stats(rn->name, rr->str);
+
+ if (rn->report_cpu_usage)
+ redis_cpu_usage(rn->name, rr->str);
+
+ freeReplyObject(rr);
+} /* void redis_read_server_info */
+
+static void redis_read_command_stats(redis_node_t *rn) {
+ redisReply *rr;
+
+ if ((rr = c_redisCommand(rn, "INFO commandstats")) == NULL) {
+ WARNING("redis plugin: node `%s': unable to get `INFO commandstats'.",
+ rn->name);
+ return;
+ }
+
+ if (rr->type != REDIS_REPLY_STRING) {
+ WARNING("redis plugin: node `%s' `INFO commandstats' returned unsupported "
+ "redis type %i.",
+ rn->name, rr->type);
+ freeReplyObject(rr);
+ return;
+ }
+
+ char *command;
+ char *line;
+ char *ptr = rr->str;
+ char *saveptr = NULL;
+ while ((line = strtok_r(ptr, "\n\r", &saveptr)) != NULL) {
+ ptr = NULL;
+
+ if (line[0] == '#')
+ continue;
+
+ /* command name */
+ if (strstr(line, "cmdstat_") != line) {
+ ERROR("redis plugin: not found 'cmdstat_' prefix in line '%s'", line);
+ continue;
}
- if ((rr = redisCommand(rh, "INFO")) == NULL) {
- WARNING("redis plugin: unable to get info from node `%s'.", rn->name);
- goto redis_fail;
+ char *values = strstr(line, ":");
+ if (values == NULL) {
+ ERROR("redis plugin: not found ':' separator in line '%s'", line);
+ continue;
}
- redis_handle_info(rn->name, rr->str, "uptime", NULL, "uptime_in_seconds",
- DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "current_connections", "clients",
- "connected_clients", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "blocked_clients", NULL,
- "blocked_clients", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "memory", NULL, "used_memory",
- DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "memory_lua", NULL, "used_memory_lua",
- DS_TYPE_GAUGE);
- /* changes_since_last_save: Deprecated in redis version 2.6 and above */
- redis_handle_info(rn->name, rr->str, "volatile_changes", NULL,
- "changes_since_last_save", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "total_connections", NULL,
- "total_connections_received", DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "total_operations", NULL,
- "total_commands_processed", DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "operations_per_second", NULL,
- "instantaneous_ops_per_sec", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "expired_keys", NULL, "expired_keys",
- DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "evicted_keys", NULL, "evicted_keys",
- DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "pubsub", "channels",
- "pubsub_channels", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "pubsub", "patterns",
- "pubsub_patterns", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "current_connections", "slaves",
- "connected_slaves", DS_TYPE_GAUGE);
- redis_handle_info(rn->name, rr->str, "cache_result", "hits",
- "keyspace_hits", DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "cache_result", "misses",
- "keyspace_misses", DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "total_bytes", "input",
- "total_net_input_bytes", DS_TYPE_DERIVE);
- redis_handle_info(rn->name, rr->str, "total_bytes", "output",
- "total_net_output_bytes", DS_TYPE_DERIVE);
-
- redis_db_stats(rn->name, rr->str);
-
- for (redis_query_t *rq = rn->queries; rq != NULL; rq = rq->next)
- redis_handle_query(rh, rn, rq);
-
- redis_fail:
- if (rr != NULL)
- freeReplyObject(rr);
- redisFree(rh);
+ /* Null-terminate command token */
+ values[0] = '\0';
+ command = line + strlen("cmdstat_");
+ values++;
+
+ /* parse values */
+ /* cmdstat_publish:calls=20795774,usec=111039258,usec_per_call=5.34 */
+ char *field;
+ char *saveptr_field = NULL;
+ while ((field = strtok_r(values, "=", &saveptr_field)) != NULL) {
+ values = NULL;
+
+ const char *type;
+ /* only these are supported */
+ if (strcmp(field, "calls") == 0)
+ type = "commands";
+ else if (strcmp(field, "usec") == 0)
+ type = "redis_command_cputime";
+ else
+ continue;
+
+ if ((field = strtok_r(NULL, ",", &saveptr_field)) == NULL)
+ continue;
+
+ char *endptr = NULL;
+ errno = 0;
+ derive_t value = strtoll(field, &endptr, 0);
+
+ if ((endptr == field) || (errno != 0))
+ continue;
+
+ redis_submit(rn->name, type, command, (value_t){.derive = value});
+ }
+ }
+ freeReplyObject(rr);
+} /* void redis_read_command_stats */
+
+static int redis_read(user_data_t *user_data) /* {{{ */
+{
+ redis_node_t *rn = user_data->data;
+
+ DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name,
+ rn->host, rn->port);
+
+ redis_check_connection(rn);
+
+ if (!rn->redisContext) /* no connection */
+ return -1;
+
+ redis_read_server_info(rn);
+
+ if (!rn->redisContext) /* connection lost */
+ return -1;
+
+ if (rn->report_command_stats) {
+ redis_read_command_stats(rn);
+
+ if (!rn->redisContext) /* connection lost */
+ return -1;
+ }
+
+ for (redis_query_t *rq = rn->queries; rq != NULL; rq = rq->next) {
+ redis_handle_query(rn, rq);
+ if (!rn->redisContext) /* connection lost */
+ return -1;
}
return 0;
{
plugin_register_complex_config("redis", redis_config);
plugin_register_init("redis", redis_init);
- plugin_register_read("redis", redis_read);
- /* TODO: plugin_register_write: one redis list per value id with
- * X elements */
}
/* }}} */
#include "common.h"
#include "plugin.h"
#include "utils_complain.h"
+#include "utils_ignorelist.h"
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
struct instance_s {
bool configured;
- bool is_plugin;
oid_t oid;
+ char *prefix;
+ char *value;
};
typedef struct instance_s instance_t;
char *name; /* used to reference this from the `Collect' option */
char *type; /* used to find the data_set */
bool is_table;
- instance_t instance;
+ instance_t type_instance;
+ instance_t plugin_instance;
+ instance_t host;
+ oid_t filter_oid;
+ ignorelist_t *ignorelist;
char *plugin_name;
- char *plugin_instance;
- char *type_instance;
- char *instance_prefix;
oid_t *values;
size_t values_len;
double scale;
/* These two types are used to cache values in `csnmp_read_table' to handle
* gaps in tables. */
-struct csnmp_list_instances_s {
+struct csnmp_cell_char_s {
oid_t suffix;
- char instance[DATA_MAX_NAME_LEN];
- struct csnmp_list_instances_s *next;
+ char value[DATA_MAX_NAME_LEN];
+ struct csnmp_cell_char_s *next;
};
-typedef struct csnmp_list_instances_s csnmp_list_instances_t;
+typedef struct csnmp_cell_char_s csnmp_cell_char_t;
-struct csnmp_table_values_s {
+struct csnmp_cell_value_s {
oid_t suffix;
value_t value;
- struct csnmp_table_values_s *next;
+ struct csnmp_cell_value_s *next;
};
-typedef struct csnmp_table_values_s csnmp_table_values_t;
+typedef struct csnmp_cell_value_s csnmp_cell_value_t;
+
+typedef enum {
+ OID_TYPE_SKIP = 0,
+ OID_TYPE_VARIABLE,
+ OID_TYPE_TYPEINSTANCE,
+ OID_TYPE_PLUGININSTANCE,
+ OID_TYPE_HOST,
+ OID_TYPE_FILTER,
+} csnmp_oid_type_t;
/*
* Private variables
sfree(hd);
} /* }}} void csnmp_host_definition_destroy */
+static void csnmp_data_definition_destroy(data_definition_t *dd) {
+ sfree(dd->name);
+ sfree(dd->type);
+ sfree(dd->plugin_name);
+ sfree(dd->plugin_instance.prefix);
+ sfree(dd->plugin_instance.value);
+ sfree(dd->type_instance.prefix);
+ sfree(dd->type_instance.value);
+ sfree(dd->host.prefix);
+ sfree(dd->host.value);
+ sfree(dd->values);
+ sfree(dd->ignores);
+ ignorelist_free(dd->ignorelist);
+ sfree(dd);
+} /* void csnmp_data_definition_destroy */
+
/* Many functions to handle the configuration. {{{ */
/* First there are many functions which do configuration stuff. It's a big
* bloated and messy, I'm afraid. */
* csnmp_config
* +-> call_snmp_init_once
* +-> csnmp_config_add_data
- * ! +-> csnmp_config_add_data_instance
+ * ! +-> csnmp_config_configure_data_instance
* ! +-> csnmp_config_add_data_values
* +-> csnmp_config_add_host
* +-> csnmp_config_add_host_version
have_init = 1;
} /* void call_snmp_init_once */
-static int csnmp_config_add_data_instance_oid(data_definition_t *dd,
- oconfig_item_t *ci,
- bool is_plugin) {
+static int csnmp_config_configure_data_instance(instance_t *instance,
+ oconfig_item_t *ci) {
char buffer[DATA_MAX_NAME_LEN];
- int status;
- status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ int status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
if (status != 0)
return status;
- if (dd->instance.configured) {
- ERROR("snmp plugin: Only one of options `TypeInstanceOID', "
- "`PluginInstanceOID' or `Instance' can be used in `Data' block.");
- return -1;
- }
-
- dd->instance.is_plugin = is_plugin;
- dd->instance.configured = true;
+ instance->configured = true;
if (strlen(buffer) == 0) {
return 0;
}
- dd->instance.oid.oid_len = MAX_OID_LEN;
+ instance->oid.oid_len = MAX_OID_LEN;
- if (!read_objid(buffer, dd->instance.oid.oid, &dd->instance.oid.oid_len)) {
+ if (!read_objid(buffer, instance->oid.oid, &instance->oid.oid_len)) {
ERROR("snmp plugin: read_objid (%s) failed.", buffer);
return -1;
}
return 0;
-} /* int csnmp_config_add_data_instance_oid */
+} /* int csnmp_config_configure_data_instance */
static int csnmp_config_add_data_values(data_definition_t *dd,
oconfig_item_t *ci) {
}
return 0;
-} /* int csnmp_config_add_data_instance */
+} /* int csnmp_config_configure_data_instance */
static int csnmp_config_add_data_blacklist(data_definition_t *dd,
oconfig_item_t *ci) {
return 0;
} /* int csnmp_config_add_data_blacklist */
+static int csnmp_config_add_data_filter_values(data_definition_t *data,
+ oconfig_item_t *ci) {
+ if (ci->values_num < 1) {
+ WARNING("snmp plugin: `FilterValues' needs at least one argument.");
+ return -1;
+ }
+
+ for (int i = 0; i < ci->values_num; i++) {
+ if (ci->values[i].type != OCONFIG_TYPE_STRING) {
+ WARNING("snmp plugin: All arguments to `FilterValues' must be strings.");
+ return -1;
+ }
+ ignorelist_add(data->ignorelist, ci->values[i].value.string);
+ }
+
+ return 0;
+} /* int csnmp_config_add_data_filter_values */
+
+static int csnmp_config_add_data_filter_oid(data_definition_t *data,
+ oconfig_item_t *ci) {
+
+ char buffer[DATA_MAX_NAME_LEN];
+ int status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ data->filter_oid.oid_len = MAX_OID_LEN;
+
+ if (!read_objid(buffer, data->filter_oid.oid, &data->filter_oid.oid_len)) {
+ ERROR("snmp plugin: read_objid (%s) failed.", buffer);
+ return -1;
+ }
+ return 0;
+} /* int csnmp_config_add_data_filter_oid */
+
static int csnmp_config_add_data(oconfig_item_t *ci) {
data_definition_t *dd = calloc(1, sizeof(*dd));
if (dd == NULL)
dd->ignores_len = 0;
dd->ignores = NULL;
+ dd->ignorelist = ignorelist_create(/* invert = */ 1);
+ if (dd->ignorelist == NULL) {
+ sfree(dd->name);
+ sfree(dd);
+ ERROR("snmp plugin: ignorelist_create() failed.");
+ return ENOMEM;
+ }
+
dd->plugin_name = strdup("snmp");
if (dd->plugin_name == NULL) {
ERROR("snmp plugin: Can't allocate memory");
else if (strcasecmp("Instance", option->key) == 0) {
if (dd->is_table) {
/* Instance is OID */
- WARNING("snmp plugin: Option `Instance' is deprecated, please update "
- "Data \"%s\" block to use option `TypeInstanceOID'.",
- dd->name);
- status = csnmp_config_add_data_instance_oid(dd, option,
- false /* type instance */);
+ WARNING(
+ "snmp plugin: data %s: Option `Instance' is deprecated, please use "
+ "option `TypeInstanceOID'.",
+ dd->name);
+ status =
+ csnmp_config_configure_data_instance(&dd->type_instance, option);
} else {
/* Instance is a simple string */
- WARNING("snmp plugin: Option `Instance' is deprecated, please update "
- "Data \"%s\" block to use option `TypeInstance'.",
- dd->name);
- status = cf_util_get_string(option, &dd->type_instance);
+ WARNING(
+ "snmp plugin: data %s: Option `Instance' is deprecated, please use "
+ "option `TypeInstance'.",
+ dd->name);
+ status = cf_util_get_string(option, &dd->type_instance.value);
}
+ } else if (strcasecmp("InstancePrefix", option->key) == 0) {
+ WARNING("snmp plugin: data %s: Option `InstancePrefix' is deprecated, "
+ "please use option `TypeInstancePrefix'.",
+ dd->name);
+ status = cf_util_get_string(option, &dd->type_instance.prefix);
} else if (strcasecmp("PluginInstance", option->key) == 0)
- status = cf_util_get_string(option, &dd->plugin_instance);
+ status = cf_util_get_string(option, &dd->plugin_instance.value);
else if (strcasecmp("TypeInstance", option->key) == 0)
- status = cf_util_get_string(option, &dd->type_instance);
+ status = cf_util_get_string(option, &dd->type_instance.value);
else if (strcasecmp("PluginInstanceOID", option->key) == 0)
- status = csnmp_config_add_data_instance_oid(dd, option,
- true /* plugin instance */);
+ status =
+ csnmp_config_configure_data_instance(&dd->plugin_instance, option);
+ else if (strcasecmp("PluginInstancePrefix", option->key) == 0)
+ status = cf_util_get_string(option, &dd->plugin_instance.prefix);
else if (strcasecmp("TypeInstanceOID", option->key) == 0)
- status = csnmp_config_add_data_instance_oid(dd, option,
- false /* type instance */);
- else if (strcasecmp("InstancePrefix", option->key) == 0)
- status = cf_util_get_string(option, &dd->instance_prefix);
+ status = csnmp_config_configure_data_instance(&dd->type_instance, option);
+ else if (strcasecmp("TypeInstancePrefix", option->key) == 0)
+ status = cf_util_get_string(option, &dd->type_instance.prefix);
+ else if (strcasecmp("HostOID", option->key) == 0)
+ status = csnmp_config_configure_data_instance(&dd->host, option);
+ else if (strcasecmp("HostPrefix", option->key) == 0)
+ status = cf_util_get_string(option, &dd->host.prefix);
else if (strcasecmp("Values", option->key) == 0)
status = csnmp_config_add_data_values(dd, option);
else if (strcasecmp("Shift", option->key) == 0)
status = csnmp_config_add_data_blacklist(dd, option);
else if (strcasecmp("InvertMatch", option->key) == 0)
status = cf_util_get_boolean(option, &dd->invert_match);
- else {
- WARNING("snmp plugin: Option `%s' not allowed here.", option->key);
+ else if (strcasecmp("FilterOID", option->key) == 0) {
+ status = csnmp_config_add_data_filter_oid(dd, option);
+ } else if (strcasecmp("FilterValues", option->key) == 0) {
+ status = csnmp_config_add_data_filter_values(dd, option);
+ } else if (strcasecmp("FilterIgnoreSelected", option->key) == 0) {
+ bool t;
+ status = cf_util_get_boolean(option, &t);
+ if (status == 0)
+ ignorelist_set_invert(dd->ignorelist, /* invert = */ !t);
+ } else {
+ WARNING("snmp plugin: data %s: Option `%s' not allowed here.", dd->name,
+ option->key);
status = -1;
}
while (status == 0) {
if (dd->is_table) {
- if (dd->plugin_instance && dd->instance.is_plugin) {
- WARNING("snmp plugin: Option `PluginInstance' will be ignored for "
- "Data `%s'",
+ /* Set type_instance to SUBID by default */
+ if (!dd->plugin_instance.configured && !dd->host.configured)
+ dd->type_instance.configured = true;
+
+ if (dd->plugin_instance.value && dd->plugin_instance.configured) {
+ WARNING(
+ "snmp plugin: data %s: Option `PluginInstance' will be ignored.",
+ dd->name);
+ }
+ if (dd->type_instance.value && dd->type_instance.configured) {
+ WARNING("snmp plugin: data %s: Option `TypeInstance' will be ignored.",
+ dd->name);
+ }
+ if (dd->type_instance.prefix && !dd->type_instance.configured) {
+ WARNING("snmp plugin: data %s: Option `TypeInstancePrefix' will be "
+ "ignored.",
+ dd->name);
+ }
+ if (dd->plugin_instance.prefix && !dd->plugin_instance.configured) {
+ WARNING("snmp plugin: data %s: Option `PluginInstancePrefix' will be "
+ "ignored.",
dd->name);
}
- if (dd->type_instance && !dd->instance.is_plugin) {
- WARNING("snmp plugin: Option `TypeInstance' will be ignored for Data "
- "`%s'",
+ if (dd->host.prefix && !dd->host.configured) {
+ WARNING("snmp plugin: data %s: Option `HostPrefix' will be ignored.",
dd->name);
}
} else {
- if (dd->instance.configured) {
- if (dd->instance.is_plugin) {
- WARNING("snmp plugin: Option `PluginInstanceOID' will be ignored for "
- "Data `%s'",
- dd->name);
- } else {
- WARNING("snmp plugin: Option `TypeInstanceOID' will be ignored for "
- "Data `%s'",
- dd->name);
- }
+ if (dd->plugin_instance.oid.oid_len > 0) {
+ WARNING("snmp plugin: data %s: Option `PluginInstanceOID' will be "
+ "ignored.",
+ dd->name);
}
-
- if (dd->instance_prefix) {
- WARNING("snmp plugin: data %s: InstancePrefix is ignored when `Table' "
- "is set to `false'.",
+ if (dd->type_instance.oid.oid_len > 0) {
+ WARNING(
+ "snmp plugin: data %s: Option `TypeInstanceOID' will be ignored.",
+ dd->name);
+ }
+ if (dd->type_instance.prefix) {
+ WARNING("snmp plugin: data %s: Option `TypeInstancePrefix' is ignored "
+ "when `Table' "
+ "set to `false'.",
dd->name);
}
+ if (dd->plugin_instance.prefix) {
+ WARNING("snmp plugin: data %s: Option `PluginInstancePrefix' is "
+ "ignored when "
+ "`Table' set to `false'.",
+ dd->name);
+ }
+ if (dd->host.prefix) {
+ WARNING(
+ "snmp plugin: data %s: Option `HostPrefix' is ignored when `Table' "
+ "set to `false'.",
+ dd->name);
+ }
}
if (dd->type == NULL) {
} /* while (status == 0) */
if (status != 0) {
- sfree(dd->name);
- sfree(dd->type);
- sfree(dd->plugin_name);
- sfree(dd->plugin_instance);
- sfree(dd->type_instance);
- sfree(dd->instance_prefix);
- sfree(dd->values);
- sfree(dd->ignores);
- sfree(dd);
+ csnmp_data_definition_destroy(dd);
return -1;
}
dd->name, dd->type, (dd->is_table) ? "true" : "false", dd->values_len);
DEBUG("snmp plugin: plugin_instance = %s, type_instance = %s,",
- dd->plugin_instance, dd->type_instance);
+ dd->plugin_instance.value, dd->type_instance.value);
- DEBUG("snmp plugin: instance_by_oid = %s, to_plugin_instance = %s }",
- (dd->instance.oid.oid_len > 0) ? "true" : "SUBID",
- (dd->instance.is_plugin) ? "true" : "false");
+ DEBUG("snmp plugin: type_instance_by_oid = %s, plugin_instance_by_oid "
+ "= %s }",
+ (dd->type_instance.oid.oid_len > 0)
+ ? "true"
+ : ((dd->type_instance.configured) ? "SUBID" : "false"),
+ (dd->plugin_instance.oid.oid_len > 0)
+ ? "true"
+ : ((dd->plugin_instance.configured) ? "SUBID" : "false"));
if (data_head == NULL)
data_head = dd;
hd->version = version;
return 0;
-} /* int csnmp_config_add_host_address */
+} /* int csnmp_config_add_host_version */
static int csnmp_config_add_host_collect(host_definition_t *host,
oconfig_item_t *ci) {
/* TODO: Check if negative values wrap around. Problem: negative temperatures.
*/
-static value_t csnmp_value_list_to_value(struct variable_list *vl, int type,
- double scale, double shift,
+static value_t csnmp_value_list_to_value(const struct variable_list *vl,
+ int type, double scale, double shift,
const char *host_name,
const char *data_name) {
value_t ret;
return 0;
} /* }}} int csnmp_strvbcopy */
-static int csnmp_instance_list_add(csnmp_list_instances_t **head,
- csnmp_list_instances_t **tail,
- const struct snmp_pdu *res,
- const host_definition_t *hd,
- const data_definition_t *dd) {
- csnmp_list_instances_t *il;
- struct variable_list *vb;
- oid_t vb_name;
- int status;
+static csnmp_cell_char_t *csnmp_get_char_cell(const struct variable_list *vb,
+ const oid_t *root_oid,
+ const host_definition_t *hd,
+ const data_definition_t *dd) {
- /* Set vb on the last variable */
- for (vb = res->variables; (vb != NULL) && (vb->next_variable != NULL);
- vb = vb->next_variable)
- /* do nothing */;
if (vb == NULL)
- return -1;
-
- csnmp_oid_init(&vb_name, vb->name, vb->name_length);
+ return NULL;
- il = calloc(1, sizeof(*il));
+ csnmp_cell_char_t *il = calloc(1, sizeof(*il));
if (il == NULL) {
ERROR("snmp plugin: calloc failed.");
- return -1;
+ return NULL;
}
il->next = NULL;
- status = csnmp_oid_suffix(&il->suffix, &vb_name, &dd->instance.oid);
- if (status != 0) {
+ oid_t vb_name;
+ csnmp_oid_init(&vb_name, vb->name, vb->name_length);
+
+ if (csnmp_oid_suffix(&il->suffix, &vb_name, root_oid) != 0) {
sfree(il);
- return status;
+ return NULL;
}
- /* Get instance name */
+ /* Get value */
if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR) ||
(vb->type == ASN_IPADDRESS)) {
- char *ptr;
-
- csnmp_strvbcopy(il->instance, vb, sizeof(il->instance));
- bool is_matched = 0;
- for (uint32_t i = 0; i < dd->ignores_len; i++) {
- status = fnmatch(dd->ignores[i], il->instance, 0);
- if (status == 0) {
- if (!dd->invert_match) {
- sfree(il);
- return 0;
- } else {
- is_matched = 1;
- break;
- }
- }
- }
- if (dd->invert_match && !is_matched) {
- sfree(il);
- return 0;
- }
- for (ptr = il->instance; *ptr != '\0'; ptr++) {
- if ((*ptr > 0) && (*ptr < 32))
- *ptr = ' ';
- else if (*ptr == '/')
- *ptr = '_';
- }
- DEBUG("snmp plugin: il->instance = `%s';", il->instance);
+
+ csnmp_strvbcopy(il->value, vb, sizeof(il->value));
+
} else {
value_t val = csnmp_value_list_to_value(
vb, DS_TYPE_COUNTER,
/* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
- snprintf(il->instance, sizeof(il->instance), "%" PRIu64,
- (uint64_t)val.counter);
+ snprintf(il->value, sizeof(il->value), "%" PRIu64, (uint64_t)val.counter);
}
- /* TODO: Debugging output */
+ return il;
+} /* csnmp_cell_char_t csnmp_get_char_cell */
+static void csnmp_cells_append(csnmp_cell_char_t **head,
+ csnmp_cell_char_t **tail,
+ csnmp_cell_char_t *il) {
if (*head == NULL)
*head = il;
else
(*tail)->next = il;
*tail = il;
-
+} /* void csnmp_cells_append */
+
+static bool csnmp_ignore_instance(csnmp_cell_char_t *cell,
+ const data_definition_t *dd) {
+ bool is_matched = 0;
+ for (uint32_t i = 0; i < dd->ignores_len; i++) {
+ int status = fnmatch(dd->ignores[i], cell->value, 0);
+ if (status == 0) {
+ if (!dd->invert_match) {
+ return 1;
+ } else {
+ is_matched = 1;
+ break;
+ }
+ }
+ }
+ if (dd->invert_match && !is_matched) {
+ return 1;
+ }
return 0;
-} /* int csnmp_instance_list_add */
+} /* bool csnmp_ignore_instance */
+
+static void csnmp_cell_replace_reserved_chars(csnmp_cell_char_t *cell) {
+ for (char *ptr = cell->value; *ptr != '\0'; ptr++) {
+ if ((*ptr > 0) && (*ptr < 32))
+ *ptr = ' ';
+ else if (*ptr == '/')
+ *ptr = '_';
+ }
+} /* void csnmp_cell_replace_reserved_chars */
static int csnmp_dispatch_table(host_definition_t *host,
data_definition_t *data,
- csnmp_list_instances_t *instance_list,
- csnmp_table_values_t **value_table) {
+ csnmp_cell_char_t *type_instance_cells,
+ 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) {
const data_set_t *ds;
value_list_t vl = VALUE_LIST_INIT;
- csnmp_list_instances_t *instance_list_ptr;
- csnmp_table_values_t *value_table_ptr[data->values_len];
+ csnmp_cell_char_t *type_instance_cell_ptr = type_instance_cells;
+ csnmp_cell_char_t *plugin_instance_cell_ptr = plugin_instance_cells;
+ csnmp_cell_char_t *hostname_cell_ptr = hostname_cells;
+ csnmp_cell_char_t *filter_cell_ptr = filter_cells;
+ csnmp_cell_value_t *value_cell_ptr[data->values_len];
size_t i;
bool have_more;
assert(ds->ds_num == data->values_len);
assert(data->values_len > 0);
- instance_list_ptr = instance_list;
-
for (i = 0; i < data->values_len; i++)
- value_table_ptr[i] = value_table[i];
+ value_cell_ptr[i] = value_cells[i];
- 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));
vl.interval = host->interval;
bool suffix_skipped = 0;
/* Determine next suffix to handle. */
- if (instance_list != NULL) {
- if (instance_list_ptr == NULL) {
+ if (type_instance_cells != NULL) {
+ if (type_instance_cell_ptr == NULL) {
have_more = 0;
continue;
}
- memcpy(¤t_suffix, &instance_list_ptr->suffix,
+ memcpy(¤t_suffix, &type_instance_cell_ptr->suffix,
sizeof(current_suffix));
} else {
/* no instance configured */
- csnmp_table_values_t *ptr = value_table_ptr[0];
+ csnmp_cell_value_t *ptr = value_cell_ptr[0];
if (ptr == NULL) {
have_more = 0;
continue;
memcpy(¤t_suffix, &ptr->suffix, sizeof(current_suffix));
}
- /* Update all the value_table_ptr to point at the entry with the same
+ /*
+ char oid_buffer[1024] = {0};
+ snprint_objid(oid_buffer, sizeof(oid_buffer) - 1, current_suffix.oid,
+ current_suffix.oid_len);
+ DEBUG("SNMP PLUGIN: SUFFIX %s", oid_buffer);
+ */
+
+ /* Update plugin_instance_cell_ptr to point expected suffix */
+ if (plugin_instance_cells != NULL) {
+ while ((plugin_instance_cell_ptr != NULL) &&
+ (csnmp_oid_compare(&plugin_instance_cell_ptr->suffix,
+ ¤t_suffix) < 0))
+ plugin_instance_cell_ptr = plugin_instance_cell_ptr->next;
+
+ if (plugin_instance_cell_ptr == NULL) {
+ have_more = 0;
+ continue;
+ }
+
+ if (csnmp_oid_compare(&plugin_instance_cell_ptr->suffix,
+ ¤t_suffix) > 0) {
+ /* This suffix is missing in the subtree. Indicate this with the
+ * "suffix_skipped" flag and try the next instance / suffix. */
+ suffix_skipped = 1;
+ }
+ }
+
+ /* Update hostname_cell_ptr to point expected suffix */
+ if (hostname_cells != NULL) {
+ while (
+ (hostname_cell_ptr != NULL) &&
+ (csnmp_oid_compare(&hostname_cell_ptr->suffix, ¤t_suffix) < 0))
+ hostname_cell_ptr = hostname_cell_ptr->next;
+
+ if (hostname_cell_ptr == NULL) {
+ have_more = 0;
+ continue;
+ }
+
+ if (csnmp_oid_compare(&hostname_cell_ptr->suffix, ¤t_suffix) > 0) {
+ /* This suffix is missing in the subtree. Indicate this with the
+ * "suffix_skipped" flag and try the next instance / suffix. */
+ suffix_skipped = 1;
+ }
+ }
+
+ /* Update filter_cell_ptr to point expected suffix */
+ if (filter_cells != NULL) {
+ while ((filter_cell_ptr != NULL) &&
+ (csnmp_oid_compare(&filter_cell_ptr->suffix, ¤t_suffix) < 0))
+ filter_cell_ptr = filter_cell_ptr->next;
+
+ if (filter_cell_ptr == NULL) {
+ have_more = 0;
+ continue;
+ }
+
+ if (csnmp_oid_compare(&filter_cell_ptr->suffix, ¤t_suffix) > 0) {
+ /* This suffix is missing in the subtree. Indicate this with the
+ * "suffix_skipped" flag and try the next instance / suffix. */
+ suffix_skipped = 1;
+ }
+ }
+
+ /* Update all the value_cell_ptr to point at the entry with the same
* trailing partial OID */
for (i = 0; i < data->values_len; i++) {
while (
- (value_table_ptr[i] != NULL) &&
- (csnmp_oid_compare(&value_table_ptr[i]->suffix, ¤t_suffix) < 0))
- value_table_ptr[i] = value_table_ptr[i]->next;
+ (value_cell_ptr[i] != NULL) &&
+ (csnmp_oid_compare(&value_cell_ptr[i]->suffix, ¤t_suffix) < 0))
+ value_cell_ptr[i] = value_cell_ptr[i]->next;
- if (value_table_ptr[i] == NULL) {
+ if (value_cell_ptr[i] == NULL) {
have_more = 0;
break;
- } else if (csnmp_oid_compare(&value_table_ptr[i]->suffix,
+ } else if (csnmp_oid_compare(&value_cell_ptr[i]->suffix,
¤t_suffix) > 0) {
/* This suffix is missing in the subtree. Indicate this with the
* "suffix_skipped" flag and try the next instance / suffix. */
/* Matching the values failed. Start from the beginning again. */
if (suffix_skipped) {
- if (instance_list != NULL)
- instance_list_ptr = instance_list_ptr->next;
+ if (type_instance_cells != NULL)
+ type_instance_cell_ptr = type_instance_cell_ptr->next;
else
- value_table_ptr[0] = value_table_ptr[0]->next;
+ value_cell_ptr[0] = value_cell_ptr[0]->next;
continue;
}
-/* if we reach this line, all value_table_ptr[i] are non-NULL and are set
- * to the same subid. instance_list_ptr is either NULL or points to the
+/* if we reach this line, all value_cell_ptr[i] are non-NULL and are set
+ * to the same subid. type_instance_cell_ptr is either NULL or points to the
* same subid, too. */
#if COLLECT_DEBUG
for (i = 1; i < data->values_len; i++) {
- assert(value_table_ptr[i] != NULL);
- assert(csnmp_oid_compare(&value_table_ptr[i - 1]->suffix,
- &value_table_ptr[i]->suffix) == 0);
+ assert(value_cell_ptr[i] != NULL);
+ assert(csnmp_oid_compare(&value_cell_ptr[i - 1]->suffix,
+ &value_cell_ptr[i]->suffix) == 0);
}
- assert((instance_list_ptr == NULL) ||
- (csnmp_oid_compare(&instance_list_ptr->suffix,
- &value_table_ptr[0]->suffix) == 0));
+ assert((type_instance_cell_ptr == NULL) ||
+ (csnmp_oid_compare(&type_instance_cell_ptr->suffix,
+ &value_cell_ptr[0]->suffix) == 0));
+ assert((plugin_instance_cell_ptr == NULL) ||
+ (csnmp_oid_compare(&plugin_instance_cell_ptr->suffix,
+ &value_cell_ptr[0]->suffix) == 0));
+ assert((hostname_cell_ptr == NULL) ||
+ (csnmp_oid_compare(&hostname_cell_ptr->suffix,
+ &value_cell_ptr[0]->suffix) == 0));
+ assert((filter_cell_ptr == NULL) ||
+ (csnmp_oid_compare(&filter_cell_ptr->suffix,
+ &value_cell_ptr[0]->suffix) == 0));
#endif
- sstrncpy(vl.type, data->type, sizeof(vl.type));
+ /* Check the value in filter column */
+ if (filter_cell_ptr &&
+ ignorelist_match(data->ignorelist, filter_cell_ptr->value) != 0) {
+ if (type_instance_cells != NULL)
+ type_instance_cell_ptr = type_instance_cell_ptr->next;
+ else
+ value_cell_ptr[0] = value_cell_ptr[0]->next;
- {
+ continue;
+ }
+
+ /* set vl.host */
+ if (data->host.configured) {
char temp[DATA_MAX_NAME_LEN];
+ if (hostname_cell_ptr == NULL)
+ csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
+ else
+ sstrncpy(temp, hostname_cell_ptr->value, sizeof(temp));
- if (instance_list_ptr == NULL)
+ if (data->host.prefix == NULL)
+ sstrncpy(vl.host, temp, sizeof(vl.host));
+ else
+ snprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
+ } else {
+ sstrncpy(vl.host, host->name, sizeof(vl.host));
+ }
+
+ /* set vl.type_instance */
+ if (data->type_instance.configured) {
+ char temp[DATA_MAX_NAME_LEN];
+ if (type_instance_cell_ptr == NULL)
csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
else
- sstrncpy(temp, instance_list_ptr->instance, sizeof(temp));
+ sstrncpy(temp, type_instance_cell_ptr->value, sizeof(temp));
- if (data->instance.is_plugin) {
- if (data->instance_prefix == NULL)
- sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance));
- else
- snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
- data->instance_prefix, temp);
+ if (data->type_instance.prefix == NULL)
+ sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
+ else
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
+ data->type_instance.prefix, temp);
+ } else if (data->type_instance.value) {
+ sstrncpy(vl.type_instance, data->type_instance.value,
+ sizeof(vl.type_instance));
+ }
- if (data->type_instance)
- sstrncpy(vl.type_instance, data->type_instance,
- sizeof(vl.type_instance));
- } else {
- if (data->instance_prefix == NULL)
- sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
- else
- snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
- data->instance_prefix, temp);
+ /* set vl.plugin_instance */
+ if (data->plugin_instance.configured) {
+ char temp[DATA_MAX_NAME_LEN];
+ if (plugin_instance_cell_ptr == NULL)
+ csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix);
+ else
+ sstrncpy(temp, plugin_instance_cell_ptr->value, sizeof(temp));
- if (data->plugin_instance)
- sstrncpy(vl.plugin_instance, data->plugin_instance,
- sizeof(vl.plugin_instance));
- }
+ if (data->plugin_instance.prefix == NULL)
+ sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance));
+ else
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
+ data->plugin_instance.prefix, temp);
+ } else if (data->plugin_instance.value) {
+ sstrncpy(vl.plugin_instance, data->plugin_instance.value,
+ sizeof(vl.plugin_instance));
}
vl.values_len = data->values_len;
vl.values = values;
for (i = 0; i < data->values_len; i++)
- vl.values[i] = value_table_ptr[i]->value;
+ vl.values[i] = value_cell_ptr[i]->value;
plugin_dispatch_values(&vl);
vl.values_len = 0;
vl.values = NULL;
- if (instance_list != NULL)
- instance_list_ptr = instance_list_ptr->next;
+ if (type_instance_cells != NULL)
+ type_instance_cell_ptr = type_instance_cell_ptr->next;
else
- value_table_ptr[0] = value_table_ptr[0]->next;
+ value_cell_ptr[0] = value_cell_ptr[0]->next;
} /* while (have_more) */
return (0);
const data_set_t *ds;
- size_t oid_list_len = data->values_len + 1;
+ size_t oid_list_len = data->values_len;
+
+ if (data->type_instance.oid.oid_len > 0)
+ oid_list_len++;
+
+ if (data->plugin_instance.oid.oid_len > 0)
+ oid_list_len++;
+
+ if (data->host.oid.oid_len > 0)
+ oid_list_len++;
+
+ if (data->filter_oid.oid_len > 0)
+ oid_list_len++;
+
/* Holds the last OID returned by the device. We use this in the GETNEXT
* request to proceed. */
oid_t oid_list[oid_list_len];
/* Set to false when an OID has left its subtree so we don't re-request it
* again. */
- bool oid_list_todo[oid_list_len];
+ csnmp_oid_type_t oid_list_todo[oid_list_len];
int status;
size_t i;
- /* `value_list_head' and `value_list_tail' implement a linked list for each
- * value. `instance_list_head' and `instance_list_tail' implement a linked
- * list of
- * instance names. This is used to jump gaps in the table. */
- csnmp_list_instances_t *instance_list_head;
- csnmp_list_instances_t *instance_list_tail;
- csnmp_table_values_t **value_list_head;
- csnmp_table_values_t **value_list_tail;
+ /* `value_list_head' and `value_cells_tail' implement a linked list for each
+ * value. `instance_cells_head' and `instance_cells_tail' implement a linked
+ * list of instance names. This is used to jump gaps in the table. */
+ csnmp_cell_char_t *type_instance_cells_head = NULL;
+ csnmp_cell_char_t *type_instance_cells_tail = NULL;
+ csnmp_cell_char_t *plugin_instance_cells_head = NULL;
+ csnmp_cell_char_t *plugin_instance_cells_tail = NULL;
+ csnmp_cell_char_t *hostname_cells_head = NULL;
+ csnmp_cell_char_t *hostname_cells_tail = NULL;
+ csnmp_cell_char_t *filter_cells_head = NULL;
+ csnmp_cell_char_t *filter_cells_tail = NULL;
+ csnmp_cell_value_t **value_cells_head;
+ csnmp_cell_value_t **value_cells_tail;
DEBUG("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name,
data->name);
}
assert(data->values_len > 0);
+ for (i = 0; i < data->values_len; i++)
+ oid_list_todo[i] = OID_TYPE_VARIABLE;
+
/* We need a copy of all the OIDs, because GETNEXT will destroy them. */
memcpy(oid_list, data->values, data->values_len * sizeof(oid_t));
- if (data->instance.oid.oid_len > 0)
- memcpy(oid_list + data->values_len, &data->instance.oid, sizeof(oid_t));
- else /* no InstanceFrom option specified. */
- oid_list_len--;
- for (i = 0; i < oid_list_len; i++)
- oid_list_todo[i] = 1;
+ if (data->type_instance.oid.oid_len > 0) {
+ memcpy(oid_list + i, &data->type_instance.oid, sizeof(oid_t));
+ oid_list_todo[i] = OID_TYPE_TYPEINSTANCE;
+ i++;
+ }
+
+ if (data->plugin_instance.oid.oid_len > 0) {
+ memcpy(oid_list + i, &data->plugin_instance.oid, sizeof(oid_t));
+ oid_list_todo[i] = OID_TYPE_PLUGININSTANCE;
+ i++;
+ }
+
+ if (data->host.oid.oid_len > 0) {
+ memcpy(oid_list + i, &data->host.oid, sizeof(oid_t));
+ oid_list_todo[i] = OID_TYPE_HOST;
+ i++;
+ }
+
+ if (data->filter_oid.oid_len > 0) {
+ memcpy(oid_list + i, &data->filter_oid, sizeof(oid_t));
+ oid_list_todo[i] = OID_TYPE_FILTER;
+ i++;
+ }
/* We're going to construct n linked lists, one for each "value".
- * value_list_head will contain pointers to the heads of these linked lists,
- * value_list_tail will contain pointers to the tail of the lists. */
- value_list_head = calloc(data->values_len, sizeof(*value_list_head));
- value_list_tail = calloc(data->values_len, sizeof(*value_list_tail));
- if ((value_list_head == NULL) || (value_list_tail == NULL)) {
+ * value_cells_head will contain pointers to the heads of these linked lists,
+ * value_cells_tail will contain pointers to the tail of the lists. */
+ value_cells_head = calloc(data->values_len, sizeof(*value_cells_head));
+ value_cells_tail = calloc(data->values_len, sizeof(*value_cells_tail));
+ if ((value_cells_head == NULL) || (value_cells_tail == NULL)) {
ERROR("snmp plugin: csnmp_read_table: calloc failed.");
- sfree(value_list_head);
- sfree(value_list_tail);
+ sfree(value_cells_head);
+ sfree(value_cells_tail);
return -1;
}
- instance_list_head = NULL;
- instance_list_tail = NULL;
-
status = 0;
while (status == 0) {
req = snmp_pdu_create(SNMP_MSG_GETNEXT);
}
/* An instance is configured and the res variable we process is the
- * instance value (last index) */
- if ((data->instance.oid.oid_len > 0) && (i == data->values_len)) {
+ * instance value */
+ if (oid_list_todo[i] == OID_TYPE_TYPEINSTANCE) {
+ if ((vb->type == SNMP_ENDOFMIBVIEW) ||
+ (snmp_oid_ncompare(data->type_instance.oid.oid,
+ data->type_instance.oid.oid_len, vb->name,
+ vb->name_length,
+ data->type_instance.oid.oid_len) != 0)) {
+ DEBUG("snmp plugin: host = %s; data = %s; TypeInstance left its "
+ "subtree.",
+ host->name, data->name);
+ oid_list_todo[i] = 0;
+ continue;
+ }
+
+ /* Allocate a new `csnmp_cell_char_t', insert the instance name and
+ * add it to the list */
+ csnmp_cell_char_t *cell =
+ csnmp_get_char_cell(vb, &data->type_instance.oid, host, data);
+ if (cell == NULL) {
+ ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.",
+ host->name);
+ status = -1;
+ break;
+ }
+
+ if (csnmp_ignore_instance(cell, data)) {
+ sfree(cell);
+ } else {
+ csnmp_cell_replace_reserved_chars(cell);
+
+ DEBUG("snmp plugin: il->type_instance = `%s';", cell->value);
+ csnmp_cells_append(&type_instance_cells_head,
+ &type_instance_cells_tail, cell);
+ }
+ } else if (oid_list_todo[i] == OID_TYPE_PLUGININSTANCE) {
+ if ((vb->type == SNMP_ENDOFMIBVIEW) ||
+ (snmp_oid_ncompare(data->plugin_instance.oid.oid,
+ data->plugin_instance.oid.oid_len, vb->name,
+ vb->name_length,
+ data->plugin_instance.oid.oid_len) != 0)) {
+ DEBUG("snmp plugin: host = %s; data = %s; TypeInstance left its "
+ "subtree.",
+ host->name, data->name);
+ oid_list_todo[i] = 0;
+ continue;
+ }
+
+ /* Allocate a new `csnmp_cell_char_t', insert the instance name and
+ * add it to the list */
+ csnmp_cell_char_t *cell =
+ csnmp_get_char_cell(vb, &data->plugin_instance.oid, host, data);
+ if (cell == NULL) {
+ ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.",
+ host->name);
+ status = -1;
+ break;
+ }
+
+ csnmp_cell_replace_reserved_chars(cell);
+
+ DEBUG("snmp plugin: il->plugin_instance = `%s';", cell->value);
+ csnmp_cells_append(&plugin_instance_cells_head,
+ &plugin_instance_cells_tail, cell);
+ } else if (oid_list_todo[i] == OID_TYPE_HOST) {
+ if ((vb->type == SNMP_ENDOFMIBVIEW) ||
+ (snmp_oid_ncompare(data->host.oid.oid, data->host.oid.oid_len,
+ vb->name, vb->name_length,
+ data->host.oid.oid_len) != 0)) {
+ DEBUG("snmp plugin: host = %s; data = %s; Host left its subtree.",
+ host->name, data->name);
+ oid_list_todo[i] = 0;
+ continue;
+ }
+
+ /* Allocate a new `csnmp_cell_char_t', insert the instance name and
+ * add it to the list */
+ csnmp_cell_char_t *cell =
+ csnmp_get_char_cell(vb, &data->host.oid, host, data);
+ if (cell == NULL) {
+ ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.",
+ host->name);
+ status = -1;
+ break;
+ }
+
+ csnmp_cell_replace_reserved_chars(cell);
+
+ DEBUG("snmp plugin: il->hostname = `%s';", cell->value);
+ csnmp_cells_append(&hostname_cells_head, &hostname_cells_tail, cell);
+ } else if (oid_list_todo[i] == OID_TYPE_FILTER) {
if ((vb->type == SNMP_ENDOFMIBVIEW) ||
- (snmp_oid_ncompare(
- data->instance.oid.oid, data->instance.oid.oid_len, vb->name,
- vb->name_length, data->instance.oid.oid_len) != 0)) {
- DEBUG("snmp plugin: host = %s; data = %s; Instance left its subtree.",
+ (snmp_oid_ncompare(data->filter_oid.oid, data->filter_oid.oid_len,
+ vb->name, vb->name_length,
+ data->filter_oid.oid_len) != 0)) {
+ DEBUG("snmp plugin: host = %s; data = %s; Host left its subtree.",
host->name, data->name);
oid_list_todo[i] = 0;
continue;
}
- /* Allocate a new `csnmp_list_instances_t', insert the instance name and
+ /* Allocate a new `csnmp_cell_char_t', insert the instance name and
* add it to the list */
- if (csnmp_instance_list_add(&instance_list_head, &instance_list_tail,
- res, host, data) != 0) {
- ERROR("snmp plugin: host %s: csnmp_instance_list_add failed.",
+ csnmp_cell_char_t *cell =
+ csnmp_get_char_cell(vb, &data->filter_oid, host, data);
+ if (cell == NULL) {
+ ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.",
host->name);
status = -1;
break;
}
+
+ csnmp_cell_replace_reserved_chars(cell);
+
+ DEBUG("snmp plugin: il->filter = `%s';", cell->value);
+ csnmp_cells_append(&filter_cells_head, &filter_cells_tail, cell);
} else /* The variable we are processing is a normal value */
{
- csnmp_table_values_t *vt;
+ assert(oid_list_todo[i] == OID_TYPE_VARIABLE);
+
+ csnmp_cell_value_t *vt;
oid_t vb_name;
oid_t suffix;
int ret;
}
/* Make sure the OIDs returned by the agent are increasing. Otherwise
- * our
- * table matching algorithm will get confused. */
- if ((value_list_tail[i] != NULL) &&
- (csnmp_oid_compare(&suffix, &value_list_tail[i]->suffix) <= 0)) {
+ * our table matching algorithm will get confused. */
+ if ((value_cells_tail[i] != NULL) &&
+ (csnmp_oid_compare(&suffix, &value_cells_tail[i]->suffix) <= 0)) {
DEBUG("snmp plugin: host = %s; data = %s; i = %" PRIsz "; "
"Suffix is not increasing.",
host->name, data->name, i);
memcpy(&vt->suffix, &suffix, sizeof(vt->suffix));
vt->next = NULL;
- if (value_list_tail[i] == NULL)
- value_list_head[i] = vt;
+ if (value_cells_tail[i] == NULL)
+ value_cells_head[i] = vt;
else
- value_list_tail[i]->next = vt;
- value_list_tail[i] = vt;
+ value_cells_tail[i]->next = vt;
+ value_cells_tail[i] = vt;
}
/* Copy OID to oid_list[i] */
res = NULL;
if (status == 0)
- csnmp_dispatch_table(host, data, instance_list_head, value_list_head);
+ csnmp_dispatch_table(host, data, type_instance_cells_head,
+ plugin_instance_cells_head, hostname_cells_head,
+ filter_cells_head, value_cells_head);
/* Free all allocated variables here */
- while (instance_list_head != NULL) {
- csnmp_list_instances_t *next = instance_list_head->next;
- sfree(instance_list_head);
- instance_list_head = next;
+ while (type_instance_cells_head != NULL) {
+ csnmp_cell_char_t *next = type_instance_cells_head->next;
+ sfree(type_instance_cells_head);
+ type_instance_cells_head = next;
+ }
+
+ while (plugin_instance_cells_head != NULL) {
+ csnmp_cell_char_t *next = plugin_instance_cells_head->next;
+ sfree(plugin_instance_cells_head);
+ plugin_instance_cells_head = next;
+ }
+
+ while (hostname_cells_head != NULL) {
+ csnmp_cell_char_t *next = hostname_cells_head->next;
+ sfree(hostname_cells_head);
+ hostname_cells_head = next;
+ }
+
+ while (filter_cells_head != NULL) {
+ csnmp_cell_char_t *next = filter_cells_head->next;
+ sfree(filter_cells_head);
+ filter_cells_head = next;
}
for (i = 0; i < data->values_len; i++) {
- while (value_list_head[i] != NULL) {
- csnmp_table_values_t *next = value_list_head[i]->next;
- sfree(value_list_head[i]);
- value_list_head[i] = next;
+ while (value_cells_head[i] != NULL) {
+ csnmp_cell_value_t *next = value_cells_head[i]->next;
+ sfree(value_cells_head[i]);
+ value_cells_head[i] = next;
}
}
- sfree(value_list_head);
- sfree(value_list_tail);
+ sfree(value_cells_head);
+ sfree(value_cells_tail);
return 0;
} /* int csnmp_read_table */
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)
- sstrncpy(vl.type_instance, data->type_instance, sizeof(vl.type_instance));
- if (data->plugin_instance)
- sstrncpy(vl.plugin_instance, data->plugin_instance,
+ 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.interval = host->interval;
while (data_this != NULL) {
data_next = data_this->next;
- sfree(data_this->name);
- sfree(data_this->type);
- sfree(data_this->plugin_name);
- sfree(data_this->plugin_instance);
- sfree(data_this->type_instance);
- sfree(data_this->instance_prefix);
- sfree(data_this->values);
- sfree(data_this->ignores);
- sfree(data_this);
+ csnmp_data_definition_destroy(data_this);
data_this = data_next;
}
int ret = 0;
token->key = index_key;
- token->str = strndup(input + t_off, n);
+ /* copy at most n bytes from input with offset t_off into token->str */
+ input += t_off;
+ size_t len = strlen(input);
+ if (n < len)
+ len = n;
+
+ token->str = malloc(len + 1);
if (token->str == NULL)
goto free_offset_error;
+ memcpy(token->str, input, len);
+ token->str[len] = '\0';
+
*offset = t_off;
ret = c_avl_insert(tree, (void *)offset, (void *)token);
/* Parsing input string if necessary */
if (td->index_keys[i].regex) {
- regmatch_t m = {-1, -1};
+ regmatch_t m;
/* Parsing input string */
ret = snmp_agent_parse_index_key(ptr, &td->index_keys[i].regex_info,
snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR,
(const u_char *)plugin_inst, strlen(plugin_inst));
snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_INTEGER,
- (const u_char *)&vcpu, 1);
+ (const u_char *)&vcpu, sizeof(vcpu));
snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_INTEGER,
- (const u_char *)&cpu, 1);
+ (const u_char *)&cpu, sizeof(cpu));
build_oid_noalloc(index_oid.oid, sizeof(index_oid.oid), &index_oid.oid_len,
NULL, 0, index_list_tmp);
}
DEF_TEST(tokenize) {
- regmatch_t m[3] = {{5, 6}, /* "1" */
- {12, 13}, /* "2" */
- {19, 20}}; /* "3" */
+ regmatch_t m[3];
+
+ m[0].rm_so = 5;
+ m[0].rm_eo = 6;
+ m[1].rm_so = 12;
+ m[1].rm_eo = 13;
+ m[2].rm_so = 19;
+ m[2].rm_eo = 20;
+
c_avl_tree_t *tokens =
c_avl_create((int (*)(const void *, const void *))num_compare);
const char input[] = "testA1-testB2-testC3";
/*
* configuration handling
*/
-
-static int tbl_config_set_s(char *name, char **var, oconfig_item_t *ci) {
- if (ci->values_num != 1 || ci->values[0].type != OCONFIG_TYPE_STRING) {
- log_err("\"%s\" expects a single string argument.", name);
- return 1;
- }
-
- sfree(*var);
- *var = sstrdup(ci->values[0].value.string);
- return 0;
-} /* tbl_config_set_separator */
-
static int tbl_config_append_array_i(char *name, size_t **var, size_t *len,
oconfig_item_t *ci) {
if (ci->values_num < 1) {
oconfig_item_t *c = ci->children + i;
if (strcasecmp(c->key, "Type") == 0)
- tbl_config_set_s(c->key, &res->type, c);
+ cf_util_get_string(c, &res->type);
else if (strcasecmp(c->key, "InstancePrefix") == 0)
- tbl_config_set_s(c->key, &res->instance_prefix, c);
+ cf_util_get_string(c, &res->instance_prefix);
else if (strcasecmp(c->key, "InstancesFrom") == 0)
tbl_config_append_array_i(c->key, &res->instances, &res->instances_num,
c);
oconfig_item_t *c = ci->children + i;
if (strcasecmp(c->key, "Separator") == 0)
- tbl_config_set_s(c->key, &tbl->sep, c);
+ cf_util_get_string(c, &tbl->sep);
else if (strcasecmp(c->key, "Plugin") == 0)
- tbl_config_set_s(c->key, &tbl->plugin_name, c);
+ cf_util_get_string(c, &tbl->plugin_name);
else if (strcasecmp(c->key, "Instance") == 0)
- tbl_config_set_s(c->key, &tbl->instance, c);
+ cf_util_get_string(c, &tbl->instance);
else if (strcasecmp(c->key, "Result") == 0)
tbl_config_result(tbl, c);
else
* The following approximately two hundred functions are used to handle the
* configuration and fill the threshold list.
* {{{ */
-static int ut_config_type_datasource(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("threshold values: The `DataSource' option needs exactly one "
- "string argument.");
- return -1;
- }
-
- sstrncpy(th->data_source, ci->values[0].value.string,
- sizeof(th->data_source));
-
- return 0;
-} /* int ut_config_type_datasource */
-
-static int ut_config_type_instance(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("threshold values: The `Instance' option needs exactly one "
- "string argument.");
- return -1;
- }
-
- sstrncpy(th->type_instance, ci->values[0].value.string,
- sizeof(th->type_instance));
-
- return 0;
-} /* int ut_config_type_instance */
-
-static int ut_config_type_max(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- WARNING("threshold values: The `%s' option needs exactly one "
- "number argument.",
- ci->key);
- return -1;
- }
-
- if (strcasecmp(ci->key, "WarningMax") == 0)
- th->warning_max = ci->values[0].value.number;
- else
- th->failure_max = ci->values[0].value.number;
-
- return 0;
-} /* int ut_config_type_max */
-
-static int ut_config_type_min(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- WARNING("threshold values: The `%s' option needs exactly one "
- "number argument.",
- ci->key);
- return -1;
- }
-
- if (strcasecmp(ci->key, "WarningMin") == 0)
- th->warning_min = ci->values[0].value.number;
- else
- th->failure_min = ci->values[0].value.number;
-
- return 0;
-} /* int ut_config_type_min */
-
-static int ut_config_type_hits(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- WARNING("threshold values: The `%s' option needs exactly one "
- "number argument.",
- ci->key);
- return -1;
- }
-
- th->hits = ci->values[0].value.number;
-
- return 0;
-} /* int ut_config_type_hits */
-
-static int ut_config_type_hysteresis(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- WARNING("threshold values: The `%s' option needs exactly one "
- "number argument.",
- ci->key);
- return -1;
- }
-
- th->hysteresis = ci->values[0].value.number;
-
- return 0;
-} /* int ut_config_type_hysteresis */
-
static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) {
threshold_t th;
int status = 0;
oconfig_item_t *option = ci->children + i;
if (strcasecmp("Instance", option->key) == 0)
- status = ut_config_type_instance(&th, option);
+ status = cf_util_get_string_buffer(option, th.type_instance,
+ sizeof(th.type_instance));
else if (strcasecmp("DataSource", option->key) == 0)
- status = ut_config_type_datasource(&th, option);
- else if ((strcasecmp("WarningMax", option->key) == 0) ||
- (strcasecmp("FailureMax", option->key) == 0))
- status = ut_config_type_max(&th, option);
- else if ((strcasecmp("WarningMin", option->key) == 0) ||
- (strcasecmp("FailureMin", option->key) == 0))
- status = ut_config_type_min(&th, option);
+ status = cf_util_get_string_buffer(option, th.data_source,
+ sizeof(th.data_source));
+ else if (strcasecmp("WarningMax", option->key) == 0)
+ status = cf_util_get_double(option, &th.warning_max);
+ else if (strcasecmp("FailureMax", option->key) == 0)
+ status = cf_util_get_double(option, &th.failure_max);
+ else if (strcasecmp("WarningMin", option->key) == 0)
+ status = cf_util_get_double(option, &th.warning_min);
+ else if (strcasecmp("FailureMin", option->key) == 0)
+ status = cf_util_get_double(option, &th.failure_min);
else if (strcasecmp("Interesting", option->key) == 0)
status = cf_util_get_flag(option, &th.flags, UT_FLAG_INTERESTING);
else if (strcasecmp("Invert", option->key) == 0)
else if (strcasecmp("Percentage", option->key) == 0)
status = cf_util_get_flag(option, &th.flags, UT_FLAG_PERCENTAGE);
else if (strcasecmp("Hits", option->key) == 0)
- status = ut_config_type_hits(&th, option);
+ status = cf_util_get_int(option, &th.hits);
else if (strcasecmp("Hysteresis", option->key) == 0)
- status = ut_config_type_hysteresis(&th, option);
+ status = cf_util_get_double(option, &th.hysteresis);
else {
WARNING("threshold values: Option `%s' not allowed inside a `Type' "
"block.",
return status;
} /* int ut_config_type */
-static int ut_config_plugin_instance(threshold_t *th, oconfig_item_t *ci) {
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("threshold values: The `Instance' option needs exactly one "
- "string argument.");
- return -1;
- }
-
- sstrncpy(th->plugin_instance, ci->values[0].value.string,
- sizeof(th->plugin_instance));
-
- return 0;
-} /* int ut_config_plugin_instance */
-
static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) {
threshold_t th;
int status = 0;
if (strcasecmp("Type", option->key) == 0)
status = ut_config_type(&th, option);
else if (strcasecmp("Instance", option->key) == 0)
- status = ut_config_plugin_instance(&th, option);
+ status = cf_util_get_string_buffer(option, th.plugin_instance,
+ sizeof(th.plugin_instance));
else {
WARNING("threshold values: Option `%s' not allowed inside a `Plugin' "
"block.",
clock_stratum value:GAUGE:0:U
compression uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
compression_ratio value:GAUGE:0:2
+commands value:DERIVE:0:U
connections value:DERIVE:0:U
conntrack value:GAUGE:0:4294967295
contextswitch value:DERIVE:0:U
pubsub value:GAUGE:0:U
queue_length value:GAUGE:0:U
records value:GAUGE:0:U
+redis_command_cputime value:DERIVE:0:U
requests value:GAUGE:0:U
response_code value:GAUGE:0:U
response_time value:GAUGE:0:U
/*
* Config Private functions
*/
-static int udb_config_set_string(char **ret_string, /* {{{ */
- oconfig_item_t *ci) {
- char *string;
-
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("db query utils: The `%s' config option "
- "needs exactly one string argument.",
- ci->key);
- return -1;
- }
-
- string = strdup(ci->values[0].value.string);
- if (string == NULL) {
- ERROR("db query utils: strdup failed.");
- return -1;
- }
-
- if (*ret_string != NULL)
- free(*ret_string);
- *ret_string = string;
-
- return 0;
-} /* }}} int udb_config_set_string */
-
static int udb_config_add_string(char ***ret_array, /* {{{ */
size_t *ret_array_len, oconfig_item_t *ci) {
char **array;
size_t array_len;
if (ci->values_num < 1) {
- WARNING("db query utils: The `%s' config option "
- "needs at least one argument.",
- ci->key);
+ P_WARNING("The `%s' config option "
+ "needs at least one argument.",
+ ci->key);
return -1;
}
for (int i = 0; i < ci->values_num; i++) {
if (ci->values[i].type != OCONFIG_TYPE_STRING) {
- WARNING("db query utils: Argument %i to the `%s' option "
- "is not a string.",
- i + 1, ci->key);
+ P_WARNING("Argument %i to the `%s' option "
+ "is not a string.",
+ i + 1, ci->key);
return -1;
}
}
array_len = *ret_array_len;
array = realloc(*ret_array, sizeof(char *) * (array_len + ci->values_num));
if (array == NULL) {
- ERROR("db query utils: realloc failed.");
+ P_ERROR("udb_config_add_string: realloc failed.");
return -1;
}
*ret_array = array;
for (int i = 0; i < ci->values_num; i++) {
array[array_len] = strdup(ci->values[i].value.string);
if (array[array_len] == NULL) {
- ERROR("db query utils: strdup failed.");
+ P_ERROR("udb_config_add_string: strdup failed.");
*ret_array_len = array_len;
return -1;
}
static int udb_config_set_uint(unsigned int *ret_value, /* {{{ */
oconfig_item_t *ci) {
- double tmp;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
- WARNING("db query utils: The `%s' config option "
- "needs exactly one numeric argument.",
- ci->key);
+ P_WARNING("The `%s' config option "
+ "needs exactly one numeric argument.",
+ ci->key);
return -1;
}
- tmp = ci->values[0].value.number;
- if ((tmp < 0.0) || (tmp > ((double)UINT_MAX)))
+ double tmp = ci->values[0].value.number;
+ if ((tmp < 0.0) || (tmp > ((double)UINT_MAX))) {
+ P_WARNING("The value given for the `%s` option is out of range.", ci->key);
return -ERANGE;
+ }
*ret_value = (unsigned int)(tmp + .5);
return 0;
vl.values = calloc(r->values_num, sizeof(*vl.values));
if (vl.values == NULL) {
- ERROR("db query utils: calloc failed.");
+ P_ERROR("udb_result_submit: calloc failed.");
return -1;
}
vl.values_len = r_area->ds->ds_num;
char *value_str = r_area->values_buffer[i];
if (0 != parse_value(value_str, &vl.values[i], r_area->ds->ds[i].type)) {
- ERROR("db query utils: udb_result_submit: Parsing `%s' as %s failed.",
- value_str, DS_TYPE_TO_STRING(r_area->ds->ds[i].type));
+ P_ERROR("udb_result_submit: Parsing `%s' as %s failed.", value_str,
+ DS_TYPE_TO_STRING(r_area->ds->ds[i].type));
errno = EINVAL;
free(vl.values);
return -1;
int status = strjoin(vl.type_instance, sizeof(vl.type_instance),
r_area->instances_buffer, r->instances_num, "-");
if (status < 0) {
- ERROR(
+ P_ERROR(
"udb_result_submit: creating type_instance failed with status %d.",
status);
return status;
int status = strjoin(tmp, sizeof(tmp), r_area->instances_buffer,
r->instances_num, "-");
if (status < 0) {
- ERROR(
+ P_ERROR(
"udb_result_submit: creating type_instance failed with status %d.",
status);
return status;
if (r->metadata_num > 0) {
vl.meta = meta_data_create();
if (vl.meta == NULL) {
- ERROR("db query utils:: meta_data_create failed.");
+ P_ERROR("udb_result_submit: meta_data_create failed.");
free(vl.values);
return -ENOMEM;
}
int status = meta_data_add_string(vl.meta, r->metadata[i],
r_area->metadata_buffer[i]);
if (status != 0) {
- ERROR("db query utils:: meta_data_add_string failed.");
+ P_ERROR("udb_result_submit: meta_data_add_string failed.");
meta_data_destroy(vl.meta);
vl.meta = NULL;
free(vl.values);
/* Read `ds' and check number of values {{{ */
prep_area->ds = plugin_get_ds(r->type);
if (prep_area->ds == NULL) {
- ERROR("db query utils: udb_result_prepare_result: Type `%s' is not "
- "known by the daemon. See types.db(5) for details.",
- r->type);
+ P_ERROR("udb_result_prepare_result: Type `%s' is not "
+ "known by the daemon. See types.db(5) for details.",
+ r->type);
BAIL_OUT(-1);
}
if (prep_area->ds->ds_num != r->values_num) {
- ERROR("db query utils: udb_result_prepare_result: The type `%s' "
- "requires exactly %" PRIsz
- " value%s, but the configuration specifies %" PRIsz ".",
- r->type, prep_area->ds->ds_num,
- (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num);
+ P_ERROR("udb_result_prepare_result: The type `%s' "
+ "requires exactly %" PRIsz
+ " value%s, but the configuration specifies %" PRIsz ".",
+ r->type, prep_area->ds->ds_num,
+ (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num);
BAIL_OUT(-1);
}
/* }}} */
prep_area->instances_pos =
(size_t *)calloc(r->instances_num, sizeof(size_t));
if (prep_area->instances_pos == NULL) {
- ERROR("db query utils: udb_result_prepare_result: calloc failed.");
+ P_ERROR("udb_result_prepare_result: calloc failed.");
BAIL_OUT(-ENOMEM);
}
prep_area->instances_buffer =
(char **)calloc(r->instances_num, sizeof(char *));
if (prep_area->instances_buffer == NULL) {
- ERROR("db query utils: udb_result_prepare_result: calloc failed.");
+ P_ERROR("udb_result_prepare_result: calloc failed.");
BAIL_OUT(-ENOMEM);
}
} /* if (r->instances_num > 0) */
prep_area->values_pos = (size_t *)calloc(r->values_num, sizeof(size_t));
if (prep_area->values_pos == NULL) {
- ERROR("db query utils: udb_result_prepare_result: calloc failed.");
+ P_ERROR("udb_result_prepare_result: calloc failed.");
BAIL_OUT(-ENOMEM);
}
prep_area->values_buffer = (char **)calloc(r->values_num, sizeof(char *));
if (prep_area->values_buffer == NULL) {
- ERROR("db query utils: udb_result_prepare_result: calloc failed.");
+ P_ERROR("udb_result_prepare_result: calloc failed.");
BAIL_OUT(-ENOMEM);
}
prep_area->metadata_pos = (size_t *)calloc(r->metadata_num, sizeof(size_t));
if (prep_area->metadata_pos == NULL) {
- ERROR("db query utils: udb_result_prepare_result: calloc failed.");
+ P_ERROR("udb_result_prepare_result: calloc failed.");
BAIL_OUT(-ENOMEM);
}
prep_area->metadata_buffer = (char **)calloc(r->metadata_num, sizeof(char *));
if (prep_area->metadata_buffer == NULL) {
- ERROR("db query utils: udb_result_prepare_result: calloc failed.");
+ P_ERROR("udb_result_prepare_result: calloc failed.");
BAIL_OUT(-ENOMEM);
}
}
if (j >= column_num) {
- ERROR("db query utils: udb_result_prepare_result: "
- "Column `%s' could not be found.",
- r->instances[i]);
+ P_ERROR("udb_result_prepare_result: "
+ "Column `%s' could not be found.",
+ r->instances[i]);
BAIL_OUT(-ENOENT);
}
} /* }}} for (i = 0; i < r->instances_num; i++) */
}
if (j >= column_num) {
- ERROR("db query utils: udb_result_prepare_result: "
- "Column `%s' could not be found.",
- r->values[i]);
+ P_ERROR("udb_result_prepare_result: "
+ "Column `%s' could not be found.",
+ r->values[i]);
BAIL_OUT(-ENOENT);
}
} /* }}} for (i = 0; i < r->values_num; i++) */
}
if (j >= column_num) {
- ERROR("db query utils: udb_result_prepare_result: "
- "Metadata column `%s' could not be found.",
- r->values[i]);
+ P_ERROR("udb_result_prepare_result: "
+ "Metadata column `%s' could not be found.",
+ r->values[i]);
BAIL_OUT(-ENOENT);
}
} /* }}} for (i = 0; i < r->metadata_num; i++) */
int status;
if (ci->values_num != 0) {
- WARNING("db query utils: The `Result' block doesn't accept "
- "any arguments. Ignoring %i argument%s.",
- ci->values_num, (ci->values_num == 1) ? "" : "s");
+ P_WARNING("The `Result' block doesn't accept "
+ "any arguments. Ignoring %i argument%s.",
+ ci->values_num, (ci->values_num == 1) ? "" : "s");
}
r = calloc(1, sizeof(*r));
if (r == NULL) {
- ERROR("db query utils: calloc failed.");
+ P_ERROR("udb_result_create: calloc failed.");
return -1;
}
r->type = NULL;
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Type", child->key) == 0)
- status = udb_config_set_string(&r->type, child);
+ status = cf_util_get_string(child, &r->type);
else if (strcasecmp("InstancePrefix", child->key) == 0)
- status = udb_config_set_string(&r->instance_prefix, child);
+ status = cf_util_get_string(child, &r->instance_prefix);
else if (strcasecmp("InstancesFrom", child->key) == 0)
status = udb_config_add_string(&r->instances, &r->instances_num, child);
else if (strcasecmp("ValuesFrom", child->key) == 0)
else if (strcasecmp("MetadataFrom", child->key) == 0)
status = udb_config_add_string(&r->metadata, &r->metadata_num, child);
else {
- WARNING("db query utils: Query `%s': Option `%s' not allowed here.",
- query_name, child->key);
+ P_WARNING("Query `%s': Option `%s' not allowed here.", query_name,
+ child->key);
status = -1;
}
/* Check that all necessary options have been given. */
while (status == 0) {
if (r->type == NULL) {
- WARNING("db query utils: `Type' not given for "
- "result in query `%s'",
- query_name);
+ P_WARNING("udb_result_create: `Type' not given for "
+ "result in query `%s'",
+ query_name);
status = -1;
}
if (r->values == NULL) {
- WARNING("db query utils: `ValuesFrom' not given for "
- "result in query `%s'",
- query_name);
+ P_WARNING("udb_result_create: `ValuesFrom' not given for "
+ "result in query `%s'",
+ query_name);
status = -1;
}
query_list_len = *ret_query_list_len;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- WARNING("db query utils: The `Query' block "
- "needs exactly one string argument.");
+ P_WARNING("udb_result_create: The `Query' block "
+ "needs exactly one string argument.");
return -1;
}
q = calloc(1, sizeof(*q));
if (q == NULL) {
- ERROR("db query utils: calloc failed.");
+ P_ERROR("udb_query_create: calloc failed.");
return -1;
}
q->min_version = 0;
q->results = NULL;
q->plugin_instance_from = NULL;
- status = udb_config_set_string(&q->name, ci);
+ status = cf_util_get_string(ci, &q->name);
if (status != 0) {
sfree(q);
return status;
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Statement", child->key) == 0)
- status = udb_config_set_string(&q->statement, child);
+ status = cf_util_get_string(child, &q->statement);
else if (strcasecmp("Result", child->key) == 0)
status = udb_result_create(q->name, &q->results, child);
else if (strcasecmp("MinVersion", child->key) == 0)
else if (strcasecmp("MaxVersion", child->key) == 0)
status = udb_config_set_uint(&q->max_version, child);
else if (strcasecmp("PluginInstanceFrom", child->key) == 0)
- status = udb_config_set_string(&q->plugin_instance_from, child);
+ status = cf_util_get_string(child, &q->plugin_instance_from);
/* Call custom callbacks */
else if (cb != NULL) {
status = (*cb)(q, child);
if (status != 0) {
- WARNING("db query utils: The configuration callback failed "
- "to handle `%s'.",
- child->key);
+ P_WARNING("The configuration callback failed "
+ "to handle `%s'.",
+ child->key);
}
} else {
- WARNING("db query utils: Query `%s': Option `%s' not allowed here.",
- q->name, child->key);
+ P_WARNING("Query `%s': Option `%s' not allowed here.", q->name,
+ child->key);
status = -1;
}
/* Check that all necessary options have been given. */
if (status == 0) {
if (q->statement == NULL) {
- WARNING("db query utils: Query `%s': No `Statement' given.", q->name);
+ P_WARNING("Query `%s': No `Statement' given.", q->name);
status = -1;
}
if (q->results == NULL) {
- WARNING("db query utils: Query `%s': No (valid) `Result' block given.",
- q->name);
+ P_WARNING("Query `%s': No (valid) `Result' block given.", q->name);
status = -1;
}
} /* if (status == 0) */
temp = realloc(query_list, sizeof(*query_list) * (query_list_len + 1));
if (temp == NULL) {
- ERROR("db query utils: realloc failed");
+ P_ERROR("udb_query_create: realloc failed");
status = -1;
} else {
query_list = temp;
if ((name == NULL) || (src_list == NULL) || (dst_list == NULL) ||
(dst_list_len == NULL)) {
- ERROR("db query utils: udb_query_pick_from_list_by_name: "
- "Invalid argument.");
+ P_ERROR("udb_query_pick_from_list_by_name: "
+ "Invalid argument.");
return -EINVAL;
}
tmp_list_len = *dst_list_len;
tmp_list = realloc(*dst_list, (tmp_list_len + 1) * sizeof(udb_query_t *));
if (tmp_list == NULL) {
- ERROR("db query utils: realloc failed.");
+ P_ERROR("udb_query_pick_from_list_by_name: realloc failed.");
return -ENOMEM;
}
} /* for (i = 0; i < src_list_len; i++) */
if (num_added <= 0) {
- ERROR("db query utils: Cannot find query `%s'. Make sure the <Query> "
- "block is above the database definition!",
- name);
+ P_ERROR("Cannot find query `%s'. Make sure the <Query> "
+ "block is above the database definition!",
+ name);
return -ENOENT;
} else {
- DEBUG("db query utils: Added %i versions of query `%s'.", num_added, name);
+ DEBUG("Added %i versions of query `%s'.", num_added, name);
}
return 0;
if ((ci == NULL) || (src_list == NULL) || (dst_list == NULL) ||
(dst_list_len == NULL)) {
- ERROR("db query utils: udb_query_pick_from_list: "
- "Invalid argument.");
+ P_ERROR("udb_query_pick_from_list: "
+ "Invalid argument.");
return -EINVAL;
}
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
- ERROR("db query utils: The `%s' config option "
- "needs exactly one string argument.",
- ci->key);
+ P_ERROR("The `%s' config option "
+ "needs exactly one string argument.",
+ ci->key);
return -1;
}
name = ci->values[0].value.string;
if ((prep_area->column_num < 1) || (prep_area->host == NULL) ||
(prep_area->plugin == NULL) || (prep_area->db_name == NULL)) {
- ERROR("db query utils: Query `%s': Query is not prepared; "
- "can't handle result.",
- q->name);
+ P_ERROR("Query `%s': Query is not prepared; "
+ "can't handle result.",
+ q->name);
return -EINVAL;
}
#if defined(COLLECT_DEBUG) && COLLECT_DEBUG /* {{{ */
do {
for (size_t i = 0; i < prep_area->column_num; i++) {
- DEBUG("db query utils: udb_query_handle_result (%s, %s): "
+ DEBUG("udb_query_handle_result (%s, %s): "
"column[%" PRIsz "] = %s;",
prep_area->db_name, q->name, i, column_values[i]);
}
}
if (success == 0) {
- ERROR("db query utils: udb_query_handle_result (%s, %s): "
- "All results failed.",
- prep_area->db_name, q->name);
+ P_ERROR("udb_query_handle_result (%s, %s): "
+ "All results failed.",
+ prep_area->db_name, q->name);
return -1;
}
if ((prep_area->host == NULL) || (prep_area->plugin == NULL) ||
(prep_area->db_name == NULL)) {
- ERROR("db query utils: Query `%s': Prepare failed: Out of memory.",
- q->name);
+ P_ERROR("Query `%s': Prepare failed: Out of memory.", q->name);
udb_query_finish_result(q, prep_area);
return -ENOMEM;
}
#if defined(COLLECT_DEBUG) && COLLECT_DEBUG
do {
for (size_t i = 0; i < column_num; i++) {
- DEBUG("db query utils: udb_query_prepare_result: "
+ DEBUG("udb_query_prepare_result: "
"query = %s; column[%" PRIsz "] = %s;",
q->name, i, column_names[i]);
}
}
if (i >= column_num) {
- ERROR("db query utils: udb_query_prepare_result: "
- "Column `%s' from `PluginInstanceFrom' could not be found.",
- q->plugin_instance_from);
+ P_ERROR("udb_query_prepare_result: "
+ "Column `%s' from `PluginInstanceFrom' could not be found.",
+ q->plugin_instance_from);
udb_query_finish_result(q, prep_area);
return -ENOENT;
}
for (r = q->results, r_area = prep_area->result_prep_areas; r != NULL;
r = r->next, r_area = r_area->next) {
if (!r_area) {
- ERROR("db query utils: Query `%s': Invalid number of result "
- "preparation areas.",
- q->name);
+ P_ERROR("Query `%s': Invalid number of result "
+ "preparation areas.",
+ q->name);
udb_query_finish_result(q, prep_area);
return -EINVAL;
}
else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
BUFFER_ADD("%" PRIu64, vl->values[ds_num].absolute);
else {
- ERROR("gr_format_values plugin: Unknown data source type: %i",
- ds->ds[ds_num].type);
+ P_ERROR("gr_format_values: Unknown data source type: %i",
+ ds->ds[ds_num].type);
return -1;
}
if (flags & GRAPHITE_STORE_RATES) {
rates = uc_get_rate(ds, vl);
if (rates == NULL) {
- ERROR("format_graphite: error with uc_get_rate");
+ P_ERROR("format_graphite: error with uc_get_rate");
return -1;
}
}
status = gr_format_name(key, sizeof(key), vl, ds_name, prefix, postfix,
escape_char, flags);
if (status != 0) {
- ERROR("format_graphite: error with gr_format_name");
+ P_ERROR("format_graphite: error with gr_format_name");
sfree(rates);
return status;
}
* `values'. */
status = gr_format_values(values, sizeof(values), i, ds, vl, rates);
if (status != 0) {
- ERROR("format_graphite: error with gr_format_values");
+ P_ERROR("format_graphite: error with gr_format_values");
sfree(rates);
return status;
}
(size_t)snprintf(message, sizeof(message), "%s %s %u\r\n", key, values,
(unsigned int)CDTIME_T_TO_TIME_T(vl->time));
if (message_len >= sizeof(message)) {
- ERROR("format_graphite: message buffer too small: "
- "Need %" PRIsz " bytes.",
- message_len + 1);
+ P_ERROR("format_graphite: message buffer too small: "
+ "Need %" PRIsz " bytes.",
+ message_len + 1);
sfree(rates);
return -ENOMEM;
}
/* Append it in case we got multiple data set */
if ((buffer_pos + message_len) >= buffer_size) {
- ERROR("format_graphite: target buffer too small");
+ P_ERROR("format_graphite: target buffer too small");
sfree(rates);
return -ENOMEM;
}
args = calloc(1, sizeof(*args));
if (args == NULL) {
- ERROR("srrd_create_args_create: calloc failed.");
+ P_ERROR("srrd_create_args_create: calloc failed.");
return NULL;
}
args->filename = NULL;
args->filename = strdup(filename);
if (args->filename == NULL) {
- ERROR("srrd_create_args_create: strdup failed.");
+ P_ERROR("srrd_create_args_create: strdup failed.");
srrd_create_args_destroy(args);
return NULL;
}
args->argv = calloc((size_t)(argc + 1), sizeof(*args->argv));
if (args->argv == NULL) {
- ERROR("srrd_create_args_create: calloc failed.");
+ P_ERROR("srrd_create_args_create: calloc failed.");
srrd_create_args_destroy(args);
return NULL;
}
for (args->argc = 0; args->argc < argc; args->argc++) {
args->argv[args->argc] = strdup(argv[args->argc]);
if (args->argv[args->argc] == NULL) {
- ERROR("srrd_create_args_create: strdup failed.");
+ P_ERROR("srrd_create_args_create: strdup failed.");
srrd_create_args_destroy(args);
return NULL;
}
rra_types[j], cfg->xff, cdp_len, cdp_num);
if ((status < 0) || ((size_t)status >= sizeof(buffer))) {
- ERROR("rra_get: Buffer would have been truncated.");
+ P_ERROR("rra_get: Buffer would have been truncated.");
continue;
}
ds_def = calloc(ds->ds_num, sizeof(*ds_def));
if (ds_def == NULL) {
- ERROR("rrdtool plugin: calloc failed: %s", STRERRNO);
+ P_ERROR("ds_get: calloc failed: %s", STRERRNO);
return -1;
}
else if (d->type == DS_TYPE_ABSOLUTE)
type = "ABSOLUTE";
else {
- ERROR("rrdtool plugin: Unknown DS type: %i", d->type);
+ P_ERROR("ds_get: Unknown DS type: %i", d->type);
break;
}
status = rrd_create_r(filename_copy, pdp_step, last_up, argc, (void *)argv);
if (status != 0) {
- WARNING("rrdtool plugin: rrd_create_r (%s) failed: %s", filename,
- rrd_get_error());
+ P_WARNING("srrd_create: rrd_create_r (%s) failed: %s", filename,
+ rrd_get_error());
}
sfree(filename_copy);
new_argc = 6 + argc;
new_argv = malloc((new_argc + 1) * sizeof(*new_argv));
if (new_argv == NULL) {
- ERROR("rrdtool plugin: malloc failed.");
+ P_ERROR("srrd_create: malloc failed.");
return -1;
}
pthread_mutex_unlock(&librrd_lock);
if (status != 0) {
- WARNING("rrdtool plugin: rrd_create (%s) failed: %s", filename,
- rrd_get_error());
+ P_WARNING("srrd_create: rrd_create (%s) failed: %s", filename,
+ rrd_get_error());
}
sfree(new_argv);
status = lock_file(args->filename);
if (status != 0) {
if (status == EEXIST)
- NOTICE("srrd_create_thread: File \"%s\" is already being created.",
- args->filename);
+ P_NOTICE("srrd_create_thread: File \"%s\" is already being created.",
+ args->filename);
else
- ERROR("srrd_create_thread: Unable to lock file \"%s\".", args->filename);
+ P_ERROR("srrd_create_thread: Unable to lock file \"%s\".",
+ args->filename);
srrd_create_args_destroy(args);
return 0;
}
status = srrd_create(tmpfile, args->pdp_step, args->last_up, args->argc,
(void *)args->argv);
if (status != 0) {
- WARNING("srrd_create_thread: srrd_create (%s) returned status %i.",
- args->filename, status);
+ P_WARNING("srrd_create_thread: srrd_create (%s) returned status %i.",
+ args->filename, status);
unlink(tmpfile);
unlock_file(args->filename);
srrd_create_args_destroy(args);
status = rename(tmpfile, args->filename);
if (status != 0) {
- ERROR("srrd_create_thread: rename (\"%s\", \"%s\") failed: %s", tmpfile,
- args->filename, STRERRNO);
+ P_ERROR("srrd_create_thread: rename (\"%s\", \"%s\") failed: %s", tmpfile,
+ args->filename, STRERRNO);
unlink(tmpfile);
unlock_file(args->filename);
srrd_create_args_destroy(args);
status = pthread_create(&thread, &attr, srrd_create_thread, args);
if (status != 0) {
- ERROR("srrd_create_async: pthread_create failed: %s", STRERROR(status));
+ P_ERROR("srrd_create_async: pthread_create failed: %s", STRERROR(status));
pthread_attr_destroy(&attr);
srrd_create_args_destroy(args);
return status;
return -1;
if ((rra_num = rra_get(&rra_def, vl, cfg)) < 1) {
- ERROR("cu_rrd_create_file failed: Could not calculate RRAs");
+ P_ERROR("cu_rrd_create_file failed: Could not calculate RRAs");
return -1;
}
if ((ds_num = ds_get(&ds_def, ds, vl, cfg)) < 1) {
- ERROR("cu_rrd_create_file failed: Could not calculate DSes");
+ P_ERROR("cu_rrd_create_file failed: Could not calculate DSes");
rra_free(rra_num, rra_def);
return -1;
}
argc = ds_num + rra_num;
if ((argv = malloc(sizeof(*argv) * (argc + 1))) == NULL) {
- ERROR("cu_rrd_create_file failed: %s", STRERRNO);
+ P_ERROR("cu_rrd_create_file failed: %s", STRERRNO);
rra_free(rra_num, rra_def);
ds_free(ds_num, ds_def);
return -1;
status = srrd_create_async(filename, stepsize, last_up, argc,
(const char **)argv);
if (status != 0)
- WARNING("cu_rrd_create_file: srrd_create_async (%s) "
- "returned status %i.",
- filename, status);
+ P_WARNING("cu_rrd_create_file: srrd_create_async (%s) "
+ "returned status %i.",
+ filename, status);
} else /* synchronous */
{
status = lock_file(filename);
if (status != 0) {
if (status == EEXIST)
- NOTICE("cu_rrd_create_file: File \"%s\" is already being created.",
- filename);
+ P_NOTICE("cu_rrd_create_file: File \"%s\" is already being created.",
+ filename);
else
- ERROR("cu_rrd_create_file: Unable to lock file \"%s\".", filename);
+ P_ERROR("cu_rrd_create_file: Unable to lock file \"%s\".", filename);
} else {
status =
srrd_create(filename, stepsize, last_up, argc, (const char **)argv);
if (status != 0) {
- WARNING("cu_rrd_create_file: srrd_create (%s) returned status %i.",
- filename, status);
+ P_WARNING("cu_rrd_create_file: srrd_create (%s) returned status %i.",
+ filename, status);
} else {
DEBUG("cu_rrd_create_file: Successfully created RRD file \"%s\".",
filename);
return ENOMEM;
node->host = NULL;
node->port = 0;
- node->timeout.tv_sec = 0;
- node->timeout.tv_usec = 1000;
+ node->timeout.tv_sec = 1;
+ node->timeout.tv_usec = 0;
node->conn = NULL;
node->prefix = NULL;
node->database = 0;
}
} else if (strcasecmp("Timeout", child->key) == 0) {
status = cf_util_get_int(child, &timeout);
- if (status == 0)
- node->timeout.tv_usec = timeout;
+ if (status == 0) {
+ node->timeout.tv_usec = timeout * 1000;
+ node->timeout.tv_sec = node->timeout.tv_usec / 1000000L;
+ node->timeout.tv_usec %= 1000000L;
+ }
} else if (strcasecmp("Prefix", child->key) == 0) {
status = cf_util_get_string(child, &node->prefix);
} else if (strcasecmp("Database", child->key) == 0) {
} else if (strcasecmp("Port", child->key) == 0) {
host->port = cf_util_get_port_number(child);
if (host->port == -1) {
- ERROR("write_riemann plugin: Invalid argument "
- "configured for the \"Port\" "
- "option.");
break;
}
} else if (strcasecmp("Protocol", child->key) == 0) {
char tmp[16];
status = cf_util_get_string_buffer(child, tmp, sizeof(tmp));
- if (status != 0) {
- ERROR("write_riemann plugin: cf_util_get_"
- "string_buffer failed with "
- "status %i.",
- status);
+ if (status != 0)
break;
- }
if (strcasecmp("UDP", tmp) == 0)
host->client_type = RIEMANN_CLIENT_UDP;
tmp);
} else if (strcasecmp("TLSCAFile", child->key) == 0) {
status = cf_util_get_string(child, &host->tls_ca_file);
- if (status != 0) {
- ERROR("write_riemann plugin: cf_util_get_"
- "string_buffer failed with "
- "status %i.",
- status);
+ if (status != 0)
break;
- }
} else if (strcasecmp("TLSCertFile", child->key) == 0) {
status = cf_util_get_string(child, &host->tls_cert_file);
- if (status != 0) {
- ERROR("write_riemann plugin: cf_util_get_"
- "string_buffer failed with "
- "status %i.",
- status);
+ if (status != 0)
break;
- }
} else if (strcasecmp("TLSKeyFile", child->key) == 0) {
status = cf_util_get_string(child, &host->tls_key_file);
- if (status != 0) {
- ERROR("write_riemann plugin: cf_util_get_"
- "string_buffer failed with "
- "status %i.",
- status);
+ if (status != 0)
break;
- }
} else if (strcasecmp("StoreRates", child->key) == 0) {
status = cf_util_get_boolean(child, &host->store_rates);
if (status != 0)
break;
} else if (strcasecmp("Port", child->key) == 0) {
status = cf_util_get_service(child, &host->service);
- if (status != 0) {
- ERROR("write_sensu plugin: Invalid argument "
- "configured for the \"Port\" "
- "option.");
+ if (status != 0)
break;
- }
} else if (strcasecmp("StoreRates", child->key) == 0) {
status = cf_util_get_boolean(child, &host->store_rates);
if (status != 0)