if BUILD_PLUGIN_TURBOSTAT
pkglib_LTLIBRARIES += turbostat.la
-turbostat_la_SOURCES = src/turbostat.c
+turbostat_la_SOURCES = \
+ src/turbostat.c \
+ src/msr-index.h
turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
]]
)
# For the turbostat plugin
- AC_CHECK_HEADERS([asm/msr-index.h],
- [have_asm_msrindex_h="yes"],
- [have_asm_msrindex_h="no"]
- )
-
- if test "x$have_asm_msrindex_h" = "xyes"; then
- AC_CACHE_CHECK([whether asm/msr-index.h has MSR_PKG_C10_RESIDENCY],
- [c_cv_have_usable_asm_msrindex_h],
- [
- AC_COMPILE_IFELSE(
- [
- AC_LANG_PROGRAM(
- [[#include<asm/msr-index.h>]],
- [[
- int y = MSR_PKG_C10_RESIDENCY;
- return(y);
- ]]
- )
- ],
- [c_cv_have_usable_asm_msrindex_h="yes"],
- [c_cv_have_usable_asm_msrindex_h="no"],
- )
- ]
- )
- fi
-
AC_CHECK_HEADERS([cpuid.h],
[have_cpuid_h="yes"],
[have_cpuid_h="no (cpuid.h not found)"]
plugin_ipvs="yes"
fi
- if test "x$c_cv_have_usable_asm_msrindex_h" = "xyes" && test "x$have_cpuid_h" = "xyes"; then
+ if test "x$have_cpuid_h" = "xyes"; then
plugin_turbostat="yes"
fi
#<Plugin filecount>
# <Directory "/path/to/dir">
+# #Plugin "foo"
# Instance "foodir"
# Name "*.conf"
# MTime "-5m"
# Size "+10k"
# Recursive true
# IncludeHidden false
+# #FilesSizeType "bytes"
+# #FilesCountType "files"
+# #TypeInstance "instance"
# </Directory>
#</Plugin>
# Bucket 0.5 1.0 # -> bucket-latency-foo-0.5_1
# Bucket 1.0 2.0 # -> bucket-latency-foo-1_2
# Bucket 2.0 0 # -> bucket-latency-foo-2_inf
+# #BucketType "bucket"
# </DSType>
# Type "latency"
# Instance "foo"
# CollectPurge false # Varnish 2 only
# CollectSession false
# CollectSHM true
-# CollectSMA false # Varnish 2 only
+# CollectSMA false # Varnish 2 & 4 only
# CollectSMS false
# CollectSM false # Varnish 2 only
# CollectStruct false
# CollectVCL false
# CollectVSM false # Varnish 4 only
# CollectWorkers false
+# CollectLock false # Varnish 4 only
+# CollectMempool false # Varnish 4 only
+# CollectManagement false # Varnish 4 only
+# CollectSMF false # Varnish 4 only
+# CollectVBE false # Varnish 4 only
# </Instance>
#</Plugin>
=over 4
+=item B<Plugin> I<Plugin>
+
+Use I<Plugin> as the plugin name when submitting values.
+Defaults to B<filecount>.
+
=item B<Instance> I<Instance>
-Sets the plugin instance to I<Instance>. That instance name must be unique, but
-it's your responsibility, the plugin doesn't check for that. If not given, the
-instance is set to the directory name with all slashes replaced by underscores
-and all leading underscores removed.
+Sets the plugin instance to I<Instance>. If not given, the instance is set to
+the directory name with all slashes replaced by underscores and all leading
+underscores removed. Empty value is allowed.
=item B<Name> I<Pattern>
"Hidden" files and directories are those, whose name begins with a dot.
Defaults to I<false>, i.e. by default hidden files and directories are ignored.
+=item B<FilesSizeType> I<Type>
+
+Sets the type used to dispatch files combined size. Empty value ("") disables
+reporting. Defaults to B<bytes>.
+
+=item B<FilesCountType> I<Type>
+
+Sets the type used to dispatch number of files. Empty value ("") disables
+reporting. Defaults to B<files>.
+
+=item B<TypeInstance> I<Instance>
+
+Sets the I<type instance> used to dispatch values. Defaults to an empty string
+(no plugin instance).
+
=back
=head2 Plugin C<GenericJMX>
<DSType "Distribution">
Percentile 99
Bucket 0 100
+ #BucketType "bucket"
</DSType>
Type "latency"
Instance "foo"
<DSType "Distribution">
Percentile 99
Bucket 0 100
+ BucketType "bucket"
</DSType>
=over 4
Bucket 20 50
Bucket 50 0
-Metrics are reported with the I<type> C<bucket> and the I<type instance>
+Metrics are reported with the I<type> set by B<BucketType> option (C<bucket>
+by default) and the I<type instance>
C<E<lt>TypeE<gt>[-E<lt>InstanceE<gt>]-E<lt>lower_boundE<gt>_E<lt>upper_boundE<gt>>.
This option may be repeated to calculate more than one rate.
+=item B<BucketType> I<Type>
+
+Sets the type used to dispatch B<Bucket> metrics.
+Optional, by default C<bucket> will be used.
+
=back
=back
Boolean enabling the use of logical core numbering for per core statistics.
When enabled, C<cpuE<lt>nE<gt>> is used as plugin instance, where I<n> is a
-sequential number assigned by the kernel. Otherwise, C<coreE<lt>nE<gt>> is used
-where I<n> is the n-th core of the socket, causing name conflicts when there is
-more than one socket.
+dynamic number assigned by the kernel. Otherwise, C<coreE<lt>nE<gt>> is used
+if there is only one package and C<pkgE<lt>nE<gt>-coreE<lt>mE<gt>> if there is
+more than one, where I<n> is the n-th core of package I<m>.
=back
CollectVCL false
CollectVSM false
CollectWorkers false
+ CollectLock false
+ CollectMempool false
+ CollectManagement false
+ CollectSMF false
+ CollectVBE false
</Instance>
</Plugin>
=item B<CollectSMA> B<true>|B<false>
malloc or umem (umem_alloc(3MALLOC) based) storage statistics. The umem storage
-component is Solaris specific. Only available with Varnish 2.x. False by
+component is Solaris specific.
+Note: SMA and SMF share counters, enable only the one used by the Varnish
+instance.
+Only available with Varnish 2.x. False by
default.
=item B<CollectSMS> B<true>|B<false>
=item B<CollectSM> B<true>|B<false>
-file (memory mapped file) storage statistics. Only available with Varnish 2.x.
+file (memory mapped file) storage statistics. Only available with Varnish 2.x.,
+in varnish 4.x. use CollectSMF.
False by default.
=item B<CollectStruct> B<true>|B<false>
Collect statistics about worker threads. False by default.
+=item B<CollectVBE> B<true>|B<false>
+
+Backend counters. Only available with Varnish 4.x. False by default.
+
+=item B<CollectSMF> B<true>|B<false>
+
+file (memory mapped file) storage statistics. Only available with Varnish 4.x.
+Note: SMA and SMF share counters, enable only the one used by the Varnish
+instance.
+Used to be called SM in Varnish 2.x. False by default.
+
+=item B<CollectManagement> B<true>|B<false>
+
+Management process counters. Only available with Varnish 4.x. False by default.
+
+=item B<CollectLock> B<true>|B<false>
+
+Lock counters. Only available with Varnish 4.x. False by default.
+
+=item B<CollectMempool> B<true>|B<false>
+
+Memory pool counters. Only available with Varnish 4.x. False by default.
+
=back
=head2 Plugin C<virt>
if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
/* if recv returns zero (even though poll() said there is data to be
* read), that means the connection has been closed */
- return errno ? errno : -1;
+ errno = ECONNRESET;
+ return -1;
}
}
struct fc_directory_conf_s {
char *path;
+ char *plugin_name;
char *instance;
+ char *files_size_type;
+ char *files_num_type;
+ char *type_instance;
int options;
static fc_directory_conf_t **directories = NULL;
static size_t directories_num = 0;
+void fc_free_dir(fc_directory_conf_t *dir) {
+ sfree(dir->path);
+ sfree(dir->plugin_name);
+ sfree(dir->instance);
+ sfree(dir->files_size_type);
+ sfree(dir->files_num_type);
+ sfree(dir->type_instance);
+ sfree(dir->name);
+
+ sfree(dir);
+} /* void fc_free_dir */
+
static void fc_submit_dir(const fc_directory_conf_t *dir) {
value_list_t vl = VALUE_LIST_INIT;
- vl.values = &(value_t){.gauge = (gauge_t)dir->files_num};
- vl.values_len = 1;
- sstrncpy(vl.plugin, "filecount", sizeof(vl.plugin));
- sstrncpy(vl.plugin_instance, dir->instance, sizeof(vl.plugin_instance));
- sstrncpy(vl.type, "files", sizeof(vl.type));
+ sstrncpy(vl.plugin, dir->plugin_name, sizeof(vl.plugin));
+ if (dir->instance != NULL)
+ sstrncpy(vl.plugin_instance, dir->instance, sizeof(vl.plugin_instance));
+ if (dir->type_instance != NULL)
+ sstrncpy(vl.type_instance, dir->type_instance, sizeof(vl.type_instance));
- plugin_dispatch_values(&vl);
+ vl.values_len = 1;
- vl.values = &(value_t){.gauge = (gauge_t)dir->files_size};
- sstrncpy(vl.type, "bytes", sizeof(vl.type));
+ if (dir->files_num_type != NULL) {
+ vl.values = &(value_t){.gauge = (gauge_t)dir->files_num};
+ sstrncpy(vl.type, dir->files_num_type, sizeof(vl.type));
+ plugin_dispatch_values(&vl);
+ }
- plugin_dispatch_values(&vl);
+ if (dir->files_size_type != NULL) {
+ vl.values = &(value_t){.gauge = (gauge_t)dir->files_size};
+ sstrncpy(vl.type, dir->files_size_type, sizeof(vl.type));
+ plugin_dispatch_values(&vl);
+ }
} /* void fc_submit_dir */
/*
* Config:
* <Plugin filecount>
* <Directory /path/to/dir>
+ * Plugin "foo"
* Instance "foobar"
* Name "*.conf"
* MTime -3600
* Size "+10M"
+ * Recursive true
+ * IncludeHidden false
+ * FilesSizeType "bytes"
+ * FilesCountType "files"
+ * TypeInstance "instance"
* </Directory>
* </Plugin>
*
static int fc_config_set_instance(fc_directory_conf_t *dir, const char *str) {
char buffer[1024];
char *ptr;
- char *copy;
sstrncpy(buffer, str, sizeof(buffer));
for (ptr = buffer; *ptr != 0; ptr++)
for (ptr = buffer; *ptr == '_'; ptr++)
/* do nothing */;
- if (*ptr == 0)
- return -1;
-
- copy = strdup(ptr);
+ char *copy = strdup(ptr);
if (copy == NULL)
return -1;
static int fc_config_add_dir_name(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
- char *temp;
-
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;
}
- temp = strdup(ci->values[0].value.string);
+ char *temp = strdup(ci->values[0].value.string);
if (temp == NULL) {
ERROR("filecount plugin: strdup failed.");
return -1;
static int fc_config_add_dir_mtime(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
- char *endptr;
- double temp;
-
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
(ci->values[0].type != OCONFIG_TYPE_NUMBER))) {
WARNING("filecount plugin: The `MTime' config option needs exactly one "
}
errno = 0;
- endptr = NULL;
- temp = strtod(ci->values[0].value.string, &endptr);
+ char *endptr = NULL;
+ double temp = strtod(ci->values[0].value.string, &endptr);
if ((errno != 0) || (endptr == NULL) ||
(endptr == ci->values[0].value.string)) {
WARNING("filecount plugin: Converting `%s' to a number failed.",
static int fc_config_add_dir_size(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
- char *endptr;
- double temp;
-
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
(ci->values[0].type != OCONFIG_TYPE_NUMBER))) {
WARNING("filecount plugin: The `Size' config option needs exactly one "
}
errno = 0;
- endptr = NULL;
- temp = strtod(ci->values[0].value.string, &endptr);
+ char *endptr = NULL;
+ double temp = strtod(ci->values[0].value.string, &endptr);
if ((errno != 0) || (endptr == NULL) ||
(endptr == ci->values[0].value.string)) {
WARNING("filecount plugin: Converting `%s' to a number failed.",
} /* int fc_config_add_dir_option */
static int fc_config_add_dir(oconfig_item_t *ci) {
- fc_directory_conf_t *dir;
- int status;
-
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("filecount plugin: `Directory' needs exactly one string "
"argument.");
}
/* Initialize `dir' */
- dir = calloc(1, sizeof(*dir));
+ fc_directory_conf_t *dir = calloc(1, sizeof(*dir));
if (dir == NULL) {
ERROR("filecount plugin: calloc failed.");
return -1;
dir->path = strdup(ci->values[0].value.string);
if (dir->path == NULL) {
ERROR("filecount plugin: strdup failed.");
- sfree(dir);
+ fc_free_dir(dir);
return -1;
}
- fc_config_set_instance(dir, dir->path);
-
dir->options = FC_RECURSIVE;
dir->name = NULL;
+ dir->plugin_name = strdup("filecount");
+ dir->instance = NULL;
+ dir->type_instance = NULL;
dir->mtime = 0;
dir->size = 0;
- status = 0;
+ dir->files_size_type = strdup("bytes");
+ dir->files_num_type = strdup("files");
+
+ if (dir->plugin_name == NULL || dir->files_size_type == NULL ||
+ dir->files_num_type == NULL) {
+ ERROR("filecount plugin: strdup failed.");
+ fc_free_dir(dir);
+ return -1;
+ }
+
+ int status = 0;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
- if (strcasecmp("Instance", option->key) == 0)
+ if (strcasecmp("Plugin", option->key) == 0)
+ status = cf_util_get_string(option, &dir->plugin_name);
+ 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 = fc_config_add_dir_option(dir, option, FC_RECURSIVE);
else if (strcasecmp("IncludeHidden", option->key) == 0)
status = fc_config_add_dir_option(dir, option, FC_HIDDEN);
+ else if (strcasecmp("FilesSizeType", option->key) == 0)
+ status = cf_util_get_string(option, &dir->files_size_type);
+ else if (strcasecmp("FilesCountType", option->key) == 0)
+ status = cf_util_get_string(option, &dir->files_num_type);
+ else if (strcasecmp("TypeInstance", option->key) == 0)
+ status = cf_util_get_string(option, &dir->type_instance);
else {
WARNING("filecount plugin: fc_config_add_dir: "
"Option `%s' not allowed here.",
break;
} /* for (ci->children) */
- if (status == 0) {
- fc_directory_conf_t **temp;
+ if (status != 0) {
+ fc_free_dir(dir);
+ return -1;
+ }
- temp = realloc(directories, sizeof(*directories) * (directories_num + 1));
- if (temp == NULL) {
- ERROR("filecount plugin: realloc failed.");
- status = -1;
- } else {
- directories = temp;
- directories[directories_num] = dir;
- directories_num++;
+ /* Set default plugin instance */
+ if (dir->instance == NULL) {
+ fc_config_set_instance(dir, dir->path);
+ if (dir->instance == NULL || strlen(dir->instance) == 0) {
+ ERROR("filecount plugin: failed to build plugin instance name.");
+ fc_free_dir(dir);
+ return -1;
}
}
- if (status != 0) {
- sfree(dir->name);
+ /* Handle disabled types */
+ if (strlen(dir->instance) == 0)
sfree(dir->instance);
- sfree(dir->path);
- sfree(dir);
+
+ if (strlen(dir->files_size_type) == 0)
+ sfree(dir->files_size_type);
+
+ if (strlen(dir->files_num_type) == 0)
+ sfree(dir->files_num_type);
+
+ if (dir->files_size_type == NULL && dir->files_num_type == NULL) {
+ WARNING("filecount plugin: Both `FilesSizeType' and `FilesCountType ' "
+ "are disabled for '%s'. There's no types to report.",
+ dir->path);
+ fc_free_dir(dir);
+ return -1;
+ }
+
+ /* Ready to add it to list */
+ fc_directory_conf_t **temp =
+ realloc(directories, sizeof(*directories) * (directories_num + 1));
+ if (temp == NULL) {
+ ERROR("filecount plugin: realloc failed.");
+ fc_free_dir(dir);
return -1;
}
+ directories = temp;
+ directories[directories_num] = dir;
+ directories_num++;
+
return 0;
} /* int fc_config_add_dir */
fc_directory_conf_t *dir = user_data;
char abs_path[PATH_MAX];
struct stat statbuf;
- int status;
if (dir == NULL)
return -1;
snprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename);
- status = lstat(abs_path, &statbuf);
+ int status = lstat(abs_path, &statbuf);
if (status != 0) {
ERROR("filecount plugin: stat (%s) failed.", abs_path);
return -1;
} /* int fc_read_dir_callback */
static int fc_read_dir(fc_directory_conf_t *dir) {
- int status;
-
dir->files_num = 0;
dir->files_size = 0;
if (dir->mtime != 0)
dir->now = time(NULL);
- status =
+ int status =
walk_directory(dir->path, fc_read_dir_callback, dir,
/* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0);
if (status != 0) {
* Copyright (C) 2009 Doug MacEachern
* Copyright (C) 2009 Franck Lombardi
* Copyright (C) 2012 Nicolas Szalay
+ * Copyright (C) 2017 Pavel Rochnyak
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Doug MacEachern <dougm at hyperic.com>
* Franck Lombardi
* Nicolas Szalay
+ * Pavel Rochnyak <pavel2000 ngs.ru>
**/
#include "collectd.h"
#include <netinet/tcp.h>
#include <sys/un.h>
+#include <poll.h>
+
#define MEMCACHED_DEF_HOST "127.0.0.1"
#define MEMCACHED_DEF_PORT "11211"
+#define MEMCACHED_CONNECT_TIMEOUT 10000
+#define MEMCACHED_IO_TIMEOUT 5000
struct memcached_s {
char *name;
char *socket;
char *connhost;
char *connport;
+ int fd;
};
typedef struct memcached_s memcached_t;
if (st == NULL)
return;
+ if (st->fd >= 0) {
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
+ }
+
sfree(st->name);
sfree(st->host);
sfree(st->socket);
if (status != 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
- fd = -1;
+ return -1;
+ }
+
+ /* switch to non-blocking mode */
+ int flags = fcntl(fd, F_GETFL);
+ status = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (status != 0) {
+ close(fd);
+ return -1;
}
return fd;
continue;
}
+ /* switch socket to non-blocking mode */
+ int flags = fcntl(fd, F_GETFL);
+ status = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (status != 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+
/* connect to the memcached daemon */
status = (int)connect(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
- if (status != 0) {
+ if (status != 0 && errno != EINPROGRESS) {
shutdown(fd, SHUT_RDWR);
close(fd);
fd = -1;
continue;
}
- /* A socket could be opened and connecting succeeded. We're done. */
+ /* Wait until connection establishes */
+ struct pollfd pollfd = {
+ .fd = fd, .events = POLLOUT,
+ };
+ do
+ status = poll(&pollfd, 1, MEMCACHED_CONNECT_TIMEOUT);
+ while (status < 0 && errno == EINTR);
+ if (status <= 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+
+ /* Check if all is good */
+ int socket_error;
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&socket_error,
+ &(socklen_t){sizeof(socket_error)});
+ if (status != 0 || socket_error != 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+ /* A socket is opened and connection succeeded. We're done. */
break;
}
return fd;
} /* int memcached_connect_inet */
-static int memcached_connect(memcached_t *st) {
+static void memcached_connect(memcached_t *st) {
+ if (st->fd >= 0)
+ return;
+
if (st->socket != NULL)
- return memcached_connect_unix(st);
+ st->fd = memcached_connect_unix(st);
else
- return memcached_connect_inet(st);
+ st->fd = memcached_connect_inet(st);
+
+ if (st->fd >= 0)
+ INFO("memcached plugin: Instance \"%s\": connection established.",
+ st->name);
}
static int memcached_query_daemon(char *buffer, size_t buffer_size,
memcached_t *st) {
- int fd, status;
+ int status;
size_t buffer_fill;
- fd = memcached_connect(st);
- if (fd < 0) {
+ memcached_connect(st);
+ if (st->fd < 0) {
ERROR("memcached plugin: Instance \"%s\" could not connect to daemon.",
st->name);
return -1;
}
- status = (int)swrite(fd, "stats\r\n", strlen("stats\r\n"));
+ struct pollfd pollfd = {
+ .fd = st->fd, .events = POLLOUT,
+ };
+
+ do
+ status = poll(&pollfd, 1, MEMCACHED_IO_TIMEOUT);
+ while (status < 0 && errno == EINTR);
+
+ if (status <= 0) {
+ ERROR("memcached plugin: poll() failed for write() call.");
+ close(st->fd);
+ st->fd = -1;
+ return -1;
+ }
+
+ status = (int)swrite(st->fd, "stats\r\n", strlen("stats\r\n"));
if (status != 0) {
char errbuf[1024];
- ERROR("memcached plugin: write(2) failed: %s",
+ ERROR("memcached plugin: Instance \"%s\": write(2) failed: %s", st->name,
sstrerror(errno, errbuf, sizeof(errbuf)));
- shutdown(fd, SHUT_RDWR);
- close(fd);
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
return -1;
}
memset(buffer, 0, buffer_size);
buffer_fill = 0;
- while ((status = (int)recv(fd, buffer + buffer_fill,
- buffer_size - buffer_fill, /* flags = */ 0)) !=
- 0) {
+ pollfd.events = POLLIN;
+ while (1) {
+ do
+ status = poll(&pollfd, 1, MEMCACHED_IO_TIMEOUT);
+ while (status < 0 && errno == EINTR);
+
+ if (status <= 0) {
+ ERROR("memcached plugin: Instance \"%s\": Timeout reading from socket",
+ st->name);
+ close(st->fd);
+ st->fd = -1;
+ return -1;
+ }
+
+ do
+ status = (int)recv(st->fd, buffer + buffer_fill,
+ buffer_size - buffer_fill, /* flags = */ 0);
+ while (status < 0 && errno == EINTR);
+
char const end_token[5] = {'E', 'N', 'D', '\r', '\n'};
if (status < 0) {
char errbuf[1024];
- if ((errno == EAGAIN) || (errno == EINTR))
+ if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
continue;
- ERROR("memcached: Error reading from socket: %s",
- sstrerror(errno, errbuf, sizeof(errbuf)));
- shutdown(fd, SHUT_RDWR);
- close(fd);
+ ERROR("memcached plugin: Instance \"%s\": Error reading from socket: %s",
+ st->name, sstrerror(errno, errbuf, sizeof(errbuf)));
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
return -1;
}
buffer_fill += (size_t)status;
if (buffer_fill > buffer_size) {
buffer_fill = buffer_size;
- WARNING("memcached plugin: Message was truncated.");
+ WARNING("memcached plugin: Instance \"%s\": Message was truncated.",
+ st->name);
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
break;
}
status = 0;
if (buffer_fill == 0) {
- WARNING("memcached plugin: No data returned by memcached.");
+ WARNING("memcached plugin: Instance \"%s\": No data returned by memcached.",
+ st->name);
status = -1;
}
- shutdown(fd, SHUT_RDWR);
- close(fd);
return status;
} /* int memcached_query_daemon */
} else if (FIELD_IS("listen_disabled_num")) {
submit_derive("connections", "listen_disabled", atof(fields[2]), st);
}
+ /*
+ * Total number of connections opened since the server started running
+ * Report this as connection rate.
+ */
+ else if (FIELD_IS("total_connections")) {
+ submit_derive("connections", "opened", atof(fields[2]), st);
+ }
/*
* Commands
st->connhost = NULL;
st->connport = NULL;
+ st->fd = -1;
+
if (strcasecmp(ci->key, "Instance") == 0)
status = cf_util_get_string(ci, &st->name);
st->connhost = NULL;
st->connport = NULL;
+ st->fd = -1;
+
status = memcached_add_read_callback(st);
if (status == 0)
memcached_have_instances = 1;
--- /dev/null
+/*
+ * Partial header file imported from the linux kernel
+ * (arch/x86/include/asm/msr-index.h)
+ * as it is not provided by the kernel sources anymore
+ *
+ * Only the minimal blocks of macro have been included
+ * ----
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * ----
+ */
+
+#ifndef _ASM_X86_MSR_INDEX_H
+#define _ASM_X86_MSR_INDEX_H
+
+/*
+ * CPU model specific register (MSR) numbers.
+ *
+ * Do not add new entries to this file unless the definitions are shared
+ * between multiple compilation units.
+ */
+
+/* Intel MSRs. Some also available on other CPUs */
+
+/* C-state Residency Counters */
+#define MSR_PKG_C3_RESIDENCY 0x000003f8
+#define MSR_PKG_C6_RESIDENCY 0x000003f9
+#define MSR_ATOM_PKG_C6_RESIDENCY 0x000003fa
+#define MSR_PKG_C7_RESIDENCY 0x000003fa
+#define MSR_CORE_C3_RESIDENCY 0x000003fc
+#define MSR_CORE_C6_RESIDENCY 0x000003fd
+#define MSR_CORE_C7_RESIDENCY 0x000003fe
+#define MSR_KNL_CORE_C6_RESIDENCY 0x000003ff
+#define MSR_PKG_C2_RESIDENCY 0x0000060d
+#define MSR_PKG_C8_RESIDENCY 0x00000630
+#define MSR_PKG_C9_RESIDENCY 0x00000631
+#define MSR_PKG_C10_RESIDENCY 0x00000632
+
+/* Run Time Average Power Limiting (RAPL) Interface */
+
+#define MSR_RAPL_POWER_UNIT 0x00000606
+
+#define MSR_PKG_POWER_LIMIT 0x00000610
+#define MSR_PKG_ENERGY_STATUS 0x00000611
+#define MSR_PKG_PERF_STATUS 0x00000613
+#define MSR_PKG_POWER_INFO 0x00000614
+
+#define MSR_DRAM_POWER_LIMIT 0x00000618
+#define MSR_DRAM_ENERGY_STATUS 0x00000619
+#define MSR_DRAM_PERF_STATUS 0x0000061b
+#define MSR_DRAM_POWER_INFO 0x0000061c
+
+#define MSR_PP0_POWER_LIMIT 0x00000638
+#define MSR_PP0_ENERGY_STATUS 0x00000639
+#define MSR_PP0_POLICY 0x0000063a
+#define MSR_PP0_PERF_STATUS 0x0000063b
+
+#define MSR_PP1_POWER_LIMIT 0x00000640
+#define MSR_PP1_ENERGY_STATUS 0x00000641
+#define MSR_PP1_POLICY 0x00000642
+
+
+
+/* Intel defined MSRs. */
+#define MSR_IA32_TSC 0x00000010
+#define MSR_SMI_COUNT 0x00000034
+
+#define MSR_IA32_MPERF 0x000000e7
+#define MSR_IA32_APERF 0x000000e8
+
+#define MSR_IA32_THERM_STATUS 0x0000019c
+
+#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
+
+#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
+
+
+#endif /* _ASM_X86_MSR_INDEX_H */
#include "plugin.h"
#include "utils_time.h"
-#include <asm/msr-index.h>
+#include "msr-index.h"
#include <cpuid.h>
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
/* If not using logical core numbering, set core id */
if (!config_lcn) {
- snprintf(name, sizeof(name), "core%02d", c->core_id);
+ if (topology.num_packages > 1)
+ snprintf(name, sizeof(name), "pkg%02d-core%02d", p->package_id, c->core_id);
+ else
+ snprintf(name, sizeof(name), "core%02d", c->core_id);
}
if (do_core_cstate & (1 << 3))
ping_droprate value:GAUGE:0:100
ping_stddev value:GAUGE:0:65535
players value:GAUGE:0:1000000
+pools value:GAUGE:0:U
power value:GAUGE:U:U
pressure value:GAUGE:0:U
protocol_counter value:DERIVE:0:U
#include "plugin.h"
#if KERNEL_LINUX
-#define UPTIME_FILE "/proc/uptime"
-/* Using /proc filesystem to retrieve the boot time, Linux only. */
+#include <sys/sysinfo.h>
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
/*
* Global variables
*/
-/* boottime always used, no OS distinction */
-static time_t boottime;
#if HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
plugin_dispatch_values(&vl);
}
-static int uptime_init(void) /* {{{ */
-{
/*
* On most unix systems the uptime is calculated by looking at the boot
* time (stored in unix time, since epoch) and the current one. We are
* the boot time, the plugin is unregistered and there is no chance to
* try again later. Nevertheless, this is very unlikely to happen.
*/
-
+static time_t uptime_get_sys(void) { /* {{{ */
+ time_t result;
#if KERNEL_LINUX
- FILE *fh = fopen(UPTIME_FILE, "r");
- if (fh == NULL) {
+ struct sysinfo info;
+ int status;
+
+ status = sysinfo(&info);
+ if (status != 0) {
char errbuf[1024];
- ERROR("uptime plugin: Cannot open " UPTIME_FILE ": %s",
+ ERROR("uptime plugin: Error calling sysinfo: %s",
sstrerror(errno, errbuf, sizeof(errbuf)));
return -1;
}
- double uptime_seconds = 0.0;
- if (fscanf(fh, "%lf", &uptime_seconds) != 1) {
- ERROR("uptime plugin: No value read from " UPTIME_FILE "");
- fclose(fh);
- return -1;
- }
-
- fclose(fh);
-
- if (uptime_seconds == 0.0) {
- ERROR("uptime plugin: uptime read from " UPTIME_FILE ", "
- "but it is zero!");
- return -1;
- }
-
- boottime = time(NULL) - (long)uptime_seconds;
+ result = (time_t)info.uptime;
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
return -1;
}
- boottime = (time_t)knp->value.ui32;
-
- if (boottime == 0) {
+ if (knp->value.ui32 == 0) {
ERROR("uptime plugin: kstat_data_lookup returned success, "
"but `boottime' is zero!");
return -1;
}
+
+ result = time(NULL) - (time_t)knp->value.ui32;
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYS_SYSCTL_H
return -1;
}
- boottime = boottv.tv_sec;
-
- if (boottime == 0) {
+ if (boottv.tv_sec == 0) {
ERROR("uptime plugin: sysctl(3) returned success, "
"but `boottime' is zero!");
return -1;
}
+
+ result = time(NULL) - boottv.tv_sec;
/* #endif HAVE_SYS_SYSCTL_H */
#elif HAVE_PERFSTAT
if (hertz <= 0)
hertz = HZ;
- boottime = time(NULL) - cputotal.lbolt / hertz;
+ result = cputotal.lbolt / hertz;
#endif /* HAVE_PERFSTAT */
- return 0;
-} /* }}} int uptime_init */
+ return result;
+} /* }}} int uptime_get_sys */
static int uptime_read(void) {
gauge_t uptime;
time_t elapsed;
/* calculate the amount of time elapsed since boot, AKA uptime */
- elapsed = time(NULL) - boottime;
+ elapsed = uptime_get_sys();
uptime = (gauge_t)elapsed;
}
void module_register(void) {
- plugin_register_init("uptime", uptime_init);
plugin_register_read("uptime", uptime_read);
} /* void module_register */
status = latency_config_add_percentile(conf, child, plugin);
else if (strcasecmp("Bucket", child->key) == 0)
status = latency_config_add_bucket(conf, child, plugin);
+ else if (strcasecmp("BucketType", child->key) == 0)
+ status = cf_util_get_string(child, &conf->bucket_type);
else
WARNING("%s plugin: \"%s\" is not a valid option within a \"%s\" block.",
plugin, child->key, ci->key);
return ENOMEM;
}
+ if (src.bucket_type != NULL) {
+ dst->bucket_type = strdup(src.bucket_type);
+ if (dst->bucket_type == NULL) {
+ latency_config_free(*dst);
+ return ENOMEM;
+ }
+ }
+
memmove(dst->percentile, src.percentile,
dst->percentile_num * sizeof(*dst->percentile));
memmove(dst->buckets, src.buckets, dst->buckets_num * sizeof(*dst->buckets));
void latency_config_free(latency_config_t conf) {
sfree(conf.percentile);
sfree(conf.buckets);
+ sfree(conf.bucket_type);
} /* void latency_config_free */
latency_bucket_t *buckets;
size_t buckets_num;
+ char *bucket_type;
/*
_Bool lower;
/* Reset GAUGE metrics only and except GAUGE_PERSIST. */
if ((mv->ds_type & UTILS_MATCH_DS_TYPE_GAUGE) &&
!(mv->ds_type & UTILS_MATCH_CF_GAUGE_PERSIST)) {
- mv->value.gauge = NAN;
+ mv->value.gauge = (mv->ds_type & UTILS_MATCH_CF_GAUGE_INC) ? 0 : NAN;
mv->values_num = 0;
}
} /* }}} void match_value_reset */
}
/* Submit buckets */
- sstrncpy(vl.type, "bucket", sizeof(vl.type));
+ if (data->latency_config.bucket_type != NULL)
+ sstrncpy(vl.type, data->latency_config.bucket_type, sizeof(vl.type));
+ else
+ sstrncpy(vl.type, "bucket", sizeof(vl.type));
+
for (size_t i = 0; i < data->latency_config.buckets_num; i++) {
latency_bucket_t bucket = data->latency_config.buckets[i];
* Jérôme Renard <jerome.renard at gmail.com>
* Marc Fournier <marc.fournier at camptocamp.com>
* Florian octo Forster <octo at collectd.org>
+ * Denes Matetelki <dmatetelki at varnish-software.com>
**/
#include "collectd.h"
_Bool collect_sms;
#if HAVE_VARNISH_V2
_Bool collect_sm;
+#endif
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
_Bool collect_sma;
#endif
_Bool collect_struct;
_Bool collect_workers;
#if HAVE_VARNISH_V4
_Bool collect_vsm;
+ _Bool collect_lck;
+ _Bool collect_mempool;
+ _Bool collect_mgt;
+ _Bool collect_smf;
+ _Bool collect_vbe;
#endif
};
typedef struct user_config_s user_config_t; /* }}} */
else if (strcmp(name, "client_req") == 0)
return varnish_submit_derive(conf->instance, "connections", "connections",
"received", val);
+#ifdef HAVE_VARNISH_V4
+ else if (strcmp(name, "client_req_400") == 0)
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "error_400", val);
+ else if (strcmp(name, "client_req_417") == 0)
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "error_417", val);
+#endif
}
#ifdef HAVE_VARNISH_V3
else if (strcmp(name, "fetch_304") == 0)
return varnish_submit_derive(conf->instance, "fetch", "http_requests",
"no_body_304", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "fetch_no_thread") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "no_thread", val);
+ else if (strcmp(name, "fetch_none") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "none", val);
+ else if (strcmp(name, "busy_sleep") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "busy_sleep", val);
+ else if (strcmp(name, "busy_wakeup") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "busy_wakeup", val);
+#endif
}
if (conf->collect_hcb) {
else if (strcmp(name, "n_objoverflow") == 0)
return varnish_submit_derive(conf->instance, "objects", "total_objects",
"workspace_overflow", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "exp_mailed") == 0)
+ return varnish_submit_derive(conf->instance, "struct", "objects",
+ "exp_mailed", val);
+ else if (strcmp(name, "exp_received") == 0)
+ return varnish_submit_derive(conf->instance, "struct", "objects",
+ "exp_received", val);
+#endif
}
#if HAVE_VARNISH_V3
else if (strcmp(name, "bans_dups") == 0)
return varnish_submit_derive(conf->instance, "ban", "total_operations",
"duplicate", val);
+ else if (strcmp(name, "bans_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "tested", val);
+ else if (strcmp(name, "bans_lurker_contention") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_contention", val);
+ else if (strcmp(name, "bans_lurker_obj_killed") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_obj_killed", val);
+ else if (strcmp(name, "bans_lurker_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_tested", val);
+ else if (strcmp(name, "bans_lurker_tests_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_tests_tested", val);
+ else if (strcmp(name, "bans_obj_killed") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "obj_killed", val);
+ else if (strcmp(name, "bans_persisted_bytes") == 0)
+ return varnish_submit_gauge(conf->instance, "ban", "total_bytes",
+ "persisted_bytes", val);
+ else if (strcmp(name, "bans_persisted_fragmentation") == 0)
+ return varnish_submit_gauge(conf->instance, "ban", "total_bytes",
+ "persisted_fragmentation", val);
+ else if (strcmp(name, "bans_tests_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "tests_tested", val);
+
}
#endif
else if (strcmp(name, "sess_herd") == 0)
return varnish_submit_derive(conf->instance, "session",
"total_operations", "herd", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "sess_closed_err") == 0)
+ return varnish_submit_derive(conf->instance, "session",
+ "total_operations", "closed_err", val);
+ else if (strcmp(name, "sess_dropped") == 0)
+ return varnish_submit_derive(conf->instance, "session",
+ "total_operations", "dropped_for_thread", val);
+#endif
}
if (conf->collect_shm) {
else if (strcmp(name, "n_wrk_lqueue") == 0)
return varnish_submit_derive(conf->instance, "workers", "total_requests",
"queue_length", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "pools") == 0)
+ return varnish_submit_gauge(conf->instance, "workers", "pools",
+ "pools", val);
+ else if (strcmp(name, "busy_killed") == 0)
+ return varnish_submit_derive(conf->instance, "workers", "http_requests",
+ "busy_killed", val);
+
+#endif
}
#if HAVE_VARNISH_V4
return varnish_submit_derive(conf->instance, "vsm", "total_bytes",
"overflowed", val);
}
+
+ if (conf->collect_vbe) {
+ /* @TODO figure out the collectd type for bitmap
+ if (strcmp(name, "happy") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "bitmap", "happy_hprobes", val);
+ */
+ if (strcmp(name, "bereq_hdrbytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "bereq_hdrbytes", val);
+ else if (strcmp(name, "bereq_bodybytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "bereq_bodybytes", val);
+ else if (strcmp(name, "beresp_hdrbytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "beresp_hdrbytes", val);
+ else if (strcmp(name, "beresp_bodybytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "beresp_bodybytes", val);
+ else if (strcmp(name, "pipe_hdrbytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "pipe_hdrbytes", val);
+ else if (strcmp(name, "pipe_out") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "pipe_out", val);
+ else if (strcmp(name, "pipe_in") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "pipe_in", val);
+ else if (strcmp(name, "conn") == 0)
+ return varnish_submit_derive(conf->instance, "vbe", "connections",
+ "c_conns", val);
+ else if (strcmp(name, "req") == 0)
+ return varnish_submit_gauge(conf->instance, "vbe", "http_requests",
+ "b_reqs", val);
+ }
+
+ /* All Stevedores support these counters */
+ if (conf->collect_sma || conf->collect_smf) {
+
+ char category[4];
+ if (conf->collect_sma)
+ strncpy(category, "sma", 4);
+ else
+ strncpy(category, "smf", 4);
+
+ if (strcmp(name, "c_req") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_operations", "alloc_req", val);
+ else if (strcmp(name, "c_fail") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_operations", "alloc_fail", val);
+ else if (strcmp(name, "c_bytes") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_bytes", "bytes_allocated", val);
+ else if (strcmp(name, "c_freed") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_bytes", "bytes_freed", val);
+ else if (strcmp(name, "g_alloc") == 0)
+ return varnish_submit_gauge(conf->instance, category,
+ "total_operations", "alloc_outstanding", val);
+ else if (strcmp(name, "g_bytes") == 0)
+ return varnish_submit_gauge(conf->instance, category, "bytes",
+ "bytes_outstanding", val);
+ else if (strcmp(name, "g_space") == 0)
+ return varnish_submit_gauge(conf->instance, category, "bytes",
+ "bytes_available", val);
+ }
+
+ /* No SMA specific counters */
+
+ if (conf->collect_smf) {
+ if (strcmp(name, "g_smf") == 0)
+ return varnish_submit_gauge(conf->instance, "smf", "objects",
+ "n_struct_smf", val);
+ else if (strcmp(name, "g_smf_frag") == 0)
+ return varnish_submit_gauge(conf->instance, "smf", "objects",
+ "n_small_free_smf", val);
+ else if (strcmp(name, "g_smf_large") == 0)
+ return varnish_submit_gauge(conf->instance, "smf", "objects",
+ "n_large_free_smf", val);
+ }
+
+ if (conf->collect_mgt) {
+ if (strcmp(name, "uptime") == 0)
+ return varnish_submit_gauge(conf->instance, "mgt", "uptime",
+ "mgt_proc_uptime", val);
+ else if (strcmp(name, "child_start") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_start", val);
+ else if (strcmp(name, "child_exit") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_exit", val);
+ else if (strcmp(name, "child_stop") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_stop", val);
+ else if (strcmp(name, "child_died") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_died", val);
+ else if (strcmp(name, "child_dump") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_dump", val);
+ else if (strcmp(name, "child_panic") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_panic", val);
+ }
+
+ if (conf->collect_lck) {
+ if (strcmp(name, "creat") == 0)
+ return varnish_submit_derive(conf->instance, "lck", "objects",
+ "created", val);
+ else if (strcmp(name, "destroy") == 0)
+ return varnish_submit_derive(conf->instance, "lck", "objects",
+ "destroyed", val);
+ else if (strcmp(name, "locks") == 0)
+ return varnish_submit_derive(conf->instance, "lck", "total_operations",
+ "lock_ops", val);
+ }
+
+ if (conf->collect_mempool) {
+ if (strcmp(name, "live") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "objects",
+ "in_use", val);
+ else if (strcmp(name, "pool") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "objects",
+ "in_pool", val);
+ else if (strcmp(name, "sz_wanted") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "bytes",
+ "size_requested", val);
+ else if (strcmp(name, "sz_actual") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "bytes",
+ "size_allocated", val);
+ else if (strcmp(name, "allocs") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "total_operations", "allocations", val);
+ else if (strcmp(name, "frees") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "total_operations", "frees", val);
+ else if (strcmp(name, "recycle") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "recycled", val);
+ else if (strcmp(name, "timeout") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "timed_out", val);
+ else if (strcmp(name, "toosmall") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "too_small", val);
+ else if (strcmp(name, "surplus") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "surplus", val);
+ else if (strcmp(name, "randry") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "ran_dry", val);
+ }
#endif
return 0;
conf->collect_shm = 1;
#if HAVE_VARNISH_V2
conf->collect_sm = 0;
+#endif
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
conf->collect_sma = 0;
#endif
conf->collect_sms = 0;
conf->collect_workers = 0;
#if HAVE_VARNISH_V4
conf->collect_vsm = 0;
+ conf->collect_lck = 0;
+ conf->collect_mempool = 0;
+ conf->collect_mgt = 0;
+ conf->collect_smf = 0;
+ conf->collect_vbe = 0;
#endif
return 0;
else if (strcasecmp("CollectSMS", child->key) == 0)
cf_util_get_boolean(child, &conf->collect_sms);
else if (strcasecmp("CollectSMA", child->key) == 0)
-#if HAVE_VARNISH_V2
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
cf_util_get_boolean(child, &conf->collect_sma);
#else
WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
- child->key, "v2");
+ child->key, "v2 and v4");
#endif
else if (strcasecmp("CollectSM", child->key) == 0)
#if HAVE_VARNISH_V2
WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
child->key, "v4");
#endif
+ else if (strcasecmp("CollectLock", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_lck);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectMempool", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_mempool);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectManagement", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_mgt);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectSMF", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_smf);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectSMF", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_smf);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectVBE", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_vbe);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
else {
WARNING("Varnish plugin: Ignoring unknown "
"configuration option: \"%s\". Did "
#endif
&& !conf->collect_session && !conf->collect_shm && !conf->collect_sms
#if HAVE_VARNISH_V2
- && !conf->collect_sma && !conf->collect_sm
+ && !conf->collect_sm
+#endif
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
+ && !conf->collect_sma
#endif
&& !conf->collect_struct && !conf->collect_totals
#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
#endif
&& !conf->collect_vcl && !conf->collect_workers
#if HAVE_VARNISH_V4
- && !conf->collect_vsm
+ && !conf->collect_vsm && !conf->collect_vbe && !conf->collect_smf
+ && !conf->collect_mgt && !conf->collect_lck && !conf->collect_mempool
#endif
) {
WARNING("Varnish plugin: No metric has been configured for "
char *prefix;
int database;
int max_set_size;
+ int max_set_duration;
_Bool store_rates;
redisContext *conn;
freeReplyObject(rr);
}
+ if (node->max_set_duration > 0) {
+ /*
+ * remove element, scored less than 'current-max_set_duration'
+ * '(%d' indicates 'less than' in redis CLI.
+ */
+ rr = redisCommand(node->conn, "ZREMRANGEBYSCORE %s -1 (%d", key,
+ (time - node->max_set_duration) + 1);
+ if (rr == NULL)
+ WARNING("ZREMRANGEBYSCORE command error. key:%s message:%s", key,
+ node->conn->errstr);
+ else
+ freeReplyObject(rr);
+ }
+
/* TODO(octo): This is more overhead than necessary. Use the cache and
* metadata to determine if it is a new metric and call SADD only once for
* each metric. */
node->prefix = NULL;
node->database = 0;
node->max_set_size = -1;
+ node->max_set_duration = -1;
node->store_rates = 1;
pthread_mutex_init(&node->lock, /* attr = */ NULL);
status = cf_util_get_int(child, &node->database);
} else if (strcasecmp("MaxSetSize", child->key) == 0) {
status = cf_util_get_int(child, &node->max_set_size);
+ } else if (strcasecmp("MaxSetDuration", child->key) == 0) {
+ status = cf_util_get_int(child, &node->max_set_duration);
} else if (strcasecmp("StoreRates", child->key) == 0) {
status = cf_util_get_boolean(child, &node->store_rates);
} else
/*
* Global variables
*/
+static value_to_rate_state_t arc_hits_state;
+static value_to_rate_state_t arc_misses_state;
+static value_to_rate_state_t l2_hits_state;
+static value_to_rate_state_t l2_misses_state;
#if defined(KERNEL_LINUX)
#include "utils_llist.h"
za_read_derive(ksp, "mru_hits", "cache_result", "mru-hit");
za_read_derive(ksp, "mru_ghost_hits", "cache_result", "mru_ghost-hit");
+ cdtime_t now = cdtime();
+
/* Ratios */
- arc_hits = (gauge_t)get_zfs_value(ksp, "hits");
- arc_misses = (gauge_t)get_zfs_value(ksp, "misses");
- l2_hits = (gauge_t)get_zfs_value(ksp, "l2_hits");
- l2_misses = (gauge_t)get_zfs_value(ksp, "l2_misses");
+ if ((value_to_rate(&arc_hits, (value_t){.derive = get_zfs_value(ksp, "hits")},
+ DS_TYPE_DERIVE, now, &arc_hits_state) == 0) &&
+ (value_to_rate(&arc_misses,
+ (value_t){.derive = get_zfs_value(ksp, "misses")},
+ DS_TYPE_DERIVE, now, &arc_misses_state) == 0)) {
+ za_submit_ratio("arc", arc_hits, arc_misses);
+ }
- za_submit_ratio("arc", arc_hits, arc_misses);
- za_submit_ratio("L2", l2_hits, l2_misses);
+ if ((value_to_rate(&l2_hits,
+ (value_t){.derive = get_zfs_value(ksp, "l2_hits")},
+ DS_TYPE_DERIVE, now, &l2_hits_state) == 0) &&
+ (value_to_rate(&l2_misses,
+ (value_t){.derive = get_zfs_value(ksp, "l2_misses")},
+ DS_TYPE_DERIVE, now, &l2_misses_state) == 0)) {
+ za_submit_ratio("L2", l2_hits, l2_misses);
+ }
/* I/O */
value_t l2_io[] = {