From 666394e4a4fe8efe6a98266b9dbac32e30064f45 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Mon, 9 Aug 2010 21:54:09 +0200 Subject: [PATCH] =?utf8?q?collectdctl:=20Added=20support=20for=20the=20?= =?utf8?q?=E2=80=98putval=E2=80=99=20command.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- src/collectdctl.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/collectdctl.pod | 29 ++++++++-- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/src/collectdctl.c b/src/collectdctl.c index 68b16750..adf45c97 100644 --- a/src/collectdctl.c +++ b/src/collectdctl.c @@ -59,6 +59,7 @@ static void exit_usage (const char *name, int status) { " * getval \n" " * flush [timeout=] [plugin=] [identifier=]\n" " * listval\n" + " * putval [interval=] \n" "\nIdentifiers:\n\n" @@ -355,6 +356,156 @@ static int listval (lcc_connection_t *c, int argc, char **argv) #undef BAIL_OUT } /* listval */ +static int putval (lcc_connection_t *c, int argc, char **argv) +{ + lcc_value_list_t vl = LCC_VALUE_LIST_INIT; + + /* 64 ought to be enough for anybody ;-) */ + value_t values[64]; + int values_types[64]; + size_t values_len = 0; + + int status; + int i; + + assert (strcasecmp (argv[0], "putval") == 0); + + if (argc < 3) { + fprintf (stderr, "ERROR: putval: Missing identifier " + "and/or value list.\n"); + return (-1); + } + + vl.values = values; + vl.values_types = values_types; + + status = parse_identifier (c, argv[1], &vl.identifier); + if (status != 0) + return (status); + + for (i = 2; i < argc; ++i) { + char *tmp; + + tmp = strchr (argv[i], (int)'='); + + if (tmp != NULL) { /* option */ + char *key = argv[i]; + char *value = tmp; + + *value = '\0'; + ++value; + + if (strcasecmp (key, "interval") == 0) { + char *endptr; + + vl.interval = strtol (value, &endptr, 0); + + if (endptr == value) { + fprintf (stderr, "ERROR: Failed to parse interval as number: %s.\n", + value); + return (-1); + } + else if ((endptr != NULL) && (*endptr != '\0')) { + fprintf (stderr, "WARNING: Ignoring trailing garbage after " + "interval: %s.\n", endptr); + } + } + else { + fprintf (stderr, "ERROR: putval: Unknown option `%s'.\n", key); + return (-1); + } + } + else { /* value list */ + char *value; + + tmp = strchr (argv[i], (int)':'); + + if (tmp == NULL) { + fprintf (stderr, "ERROR: putval: Invalid value list: %s.\n", + argv[i]); + return (-1); + } + + *tmp = '\0'; + ++tmp; + + if (strcasecmp (argv[i], "N") == 0) { + vl.time = 0; + } + else { + char *endptr; + + vl.time = strtol (argv[i], &endptr, 0); + + if (endptr == value) { + fprintf (stderr, "ERROR: Failed to parse time as number: %s.\n", + argv[i]); + return (-1); + } + else if ((endptr != NULL) && (*endptr != '\0')) { + fprintf (stderr, "ERROR: Garbage after time: %s.\n", endptr); + return (-1); + } + } + + values_len = 0; + value = tmp; + while (value != 0) { + char *dot, *endptr; + + tmp = strchr (argv[i], (int)':'); + + if (tmp != NULL) { + *tmp = '\0'; + ++tmp; + } + + /* This is a bit of a hack, but parsing types.db just does not make + * much sense imho -- the server might have different types defined + * anyway. Also, lcc uses the type information for formatting the + * number only, so the real meaning does not matter. -tokkee */ + dot = strchr (value, (int)'.'); + if (dot) { /* floating point value */ + values[values_len].gauge = strtod (value, &endptr); + values_types[values_len] = LCC_TYPE_GAUGE; + } + else { /* integer */ + values[values_len].counter = strtol (value, &endptr, 0); + values_types[values_len] = LCC_TYPE_COUNTER; + } + ++values_len; + + if (endptr == value) { + fprintf (stderr, "ERROR: Failed to parse value as number: %s.\n", + argv[i]); + return (-1); + } + else if ((endptr != NULL) && (*endptr != '\0')) { + fprintf (stderr, "ERROR: Garbage after value: %s.\n", endptr); + return (-1); + } + + value = tmp; + } + + assert (values_len >= 1); + vl.values_len = values_len; + + status = lcc_putval (c, &vl); + if (status != 0) { + fprintf (stderr, "ERROR: %s\n", lcc_strerror (c)); + return (-1); + } + } + } + + if (values_len == 0) { + fprintf (stderr, "ERROR: putval: Missing value list(s).\n"); + return (-1); + } + return (0); +} /* putval */ + int main (int argc, char **argv) { char address[1024] = "unix:"DEFAULT_SOCK; @@ -402,6 +553,8 @@ int main (int argc, char **argv) { status = flush (c, argc - optind, argv + optind); else if (strcasecmp (argv[optind], "listval") == 0) status = listval (c, argc - optind, argv + optind); + else if (strcasecmp (argv[optind], "putval") == 0) + status = putval (c, argc - optind, argv + optind); else { fprintf (stderr, "%s: invalid command: %s\n", argv[0], argv[optind]); return (1); diff --git a/src/collectdctl.pod b/src/collectdctl.pod index aff67ef6..65d4e051 100644 --- a/src/collectdctl.pod +++ b/src/collectdctl.pod @@ -83,6 +83,18 @@ C plugin. Each value is printed on its own line. I.Ee., this command returns a list of valid identifiers that may be used with the other commands. +=item B IidentifierE> [BIsecondsE>] +Ivalue-list(s)E> + +Submit one or more values (identified by IidentifierE>, see below) +to the daemon which will then dispatch them to the write plugins. B +specifies the interval (in seconds) used to collect the values following that +option. It defaults to the default of the running collectd instance receiving +the data. Multiple Ivalue-list(s)E> (see below) may be specified. +Each of them will be submitted to the daemon. The values have to match the +data-set definition specified by the type as given in the identifier (see +L for details). + =back =head1 IDENTIFIERS @@ -100,6 +112,16 @@ Hostname defaults to the local (non-fully qualified) hostname if omitted. No error is returned if the specified identifier does not exist (this is a limitation in the C library). +=head1 VALUE-LIST + +A value list describes one data-set as handled by collectd. It is a colon +(C<:>) separated list of the time and the values. Each value is either given +as an integer if the data-type is a counter, or as a double if the data-type +is a gauge value. The number of values and the data-types have to match the +type specified in the identifier (see L for details). The time is +specified as epoch (i.Ee., standard UNIX time) or as a literal C +which will be interpreted as now. + =head1 EXAMPLES =over 4 @@ -120,9 +142,10 @@ collectd instance. =head1 SEE ALSO -L -L -L +L, +L, +L, +L =head1 AUTHOR -- 2.11.0