Merge branch 'collectd-4.4'
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Tue, 10 Jun 2008 15:10:05 +0000 (17:10 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Tue, 10 Jun 2008 15:10:05 +0000 (17:10 +0200)
1  2 
configure.in
src/disk.c
src/network.c
src/plugin.h
src/wireless.c

diff --combined configure.in
@@@ -57,7 -57,7 +57,7 @@@ AC_HEADER_STD
  AC_HEADER_SYS_WAIT
  AC_HEADER_DIRENT
  
- AC_CHECK_HEADERS(stdint.h stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h)
+ AC_CHECK_HEADERS(stdint.h stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h)
  
  # For ping library
  AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
@@@ -1489,44 -1489,6 +1489,44 @@@ AC_DEFINE_UNQUOTED(COLLECT_LIBPCAP, [$c
        [Wether or not to use the pcap library])
  AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes")
  
 +AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])],
 +[
 +      if test "x$withval" != "xno" && test "x$withval" != "xyes"
 +      then
 +              LDFLAGS="$LDFLAGS -L$withval/lib"
 +              CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE"
 +              with_libesmtp="yes"
 +      else
 +              with_libesmtp="$withval"
 +      fi
 +],
 +[
 +      with_libesmtp="yes"
 +])
 +if test "x$with_libesmtp" = "xyes"
 +then
 +      AC_CHECK_LIB(esmtp, smtp_create_session,
 +      [
 +              AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).])
 +      ], [with_libesmtp="no (libesmtp not found)"])
 +fi
 +if test "x$with_libesmtp" = "xyes"
 +then
 +      AC_CHECK_HEADERS(libesmtp.h,
 +      [
 +              AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the <libesmtp.h> header file.])
 +      ], [with_libesmtp="no (libesmtp.h not found)"])
 +fi
 +if test "x$with_libesmtp" = "xyes"
 +then
 +      collect_libesmtp=1
 +else
 +      collect_libesmtp=0
 +fi
 +AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp],
 +      [Wether or not to use the esmtp library])
 +AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes")
 +
  perl_interpreter="perl"
  AC_ARG_WITH(libperl, [AS_HELP_STRING([--with-libperl@<:@=PREFIX@:>@], [Path to libperl.])],
  [
  fi
  AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
  
 +PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
 +              [with_libnotify="yes"],
 +              [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"])
 +
  with_upsclient_config="libupsclient-config"
  with_upsclient_cflags=""
  with_upsclient_libs=""
  
  if test "x$with_libkvm" = "xyes"
  then
 +      plugin_processes="yes"
        plugin_swap="yes"
  fi
  
@@@ -2512,7 -2469,6 +2512,7 @@@ AC_PLUGIN([battery],     [$plugin_batte
  AC_PLUGIN([cpu],         [$plugin_cpu],        [CPU usage statistics])
  AC_PLUGIN([cpufreq],     [$plugin_cpufreq],    [CPU frequency statistics])
  AC_PLUGIN([csv],         [yes],                [CSV output plugin])
 +AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
  AC_PLUGIN([df],          [$plugin_df],         [Filesystem usage statistics])
  AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
  AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
@@@ -2537,7 -2493,6 +2537,7 @@@ AC_PLUGIN([netlink],     [$with_libnetl
  AC_PLUGIN([network],     [yes],                [Network communication plugin])
  AC_PLUGIN([nfs],         [$plugin_nfs],        [NFS statistics])
  AC_PLUGIN([nginx],       [$with_libcurl],      [nginx statistics])
 +AC_PLUGIN([notify_email], [$with_libesmtp],    [Email notifier])
  AC_PLUGIN([ntpd],        [yes],                [NTPd statistics])
  AC_PLUGIN([nut],         [$with_libupsclient], [Network UPS tools statistics])
  AC_PLUGIN([perl],        [$plugin_perl],       [Embed a Perl interpreter])
@@@ -2635,93 -2590,90 +2635,93 @@@ cat <<EOF
  
  Configuration:
    Libraries:
 -    libcurl . . . . . . $with_libcurl
 -    libiokit  . . . . . $with_libiokit
 -    libiptc . . . . . . $with_libiptc
 -    libkstat  . . . . . $with_kstat
 -    libkvm  . . . . . . $with_libkvm
 -    libmysql  . . . . . $with_libmysql
 -    libnetlink  . . . . $with_libnetlink
 -    libnetsnmp  . . . . $with_libnetsnmp
 -    liboconfig  . . . . $with_liboconfig
 -    libopenipmi . . . . $with_libopenipmipthread
 -    liboping  . . . . . $with_liboping
 -    libpcap . . . . . . $with_libpcap
 -    libperl . . . . . . $with_libperl
 -    libpthread  . . . . $with_libpthread
 -    librrd  . . . . . . $with_rrdtool
 -    libsensors  . . . . $with_lm_sensors
 -    libstatgrab . . . . $with_libstatgrab
 -    libupsclient  . . . $with_libupsclient
 -    libvirt . . . . . . $with_libvirt
 -    libxml2 . . . . . . $with_libxml2
 -    libxmms . . . . . . $with_libxmms
 +    libcurl . . . . . . . $with_libcurl
 +    libiokit  . . . . . . $with_libiokit
 +    libiptc . . . . . . . $with_libiptc
 +    libkstat  . . . . . . $with_kstat
 +    libkvm  . . . . . . . $with_libkvm
 +    libmysql  . . . . . . $with_libmysql
 +    libnetlink  . . . . . $with_libnetlink
 +    libnetsnmp  . . . . . $with_libnetsnmp
 +    libnotify . . . . . . $with_libnotify
 +    liboconfig  . . . . . $with_liboconfig
 +    libopenipmi . . . . . $with_libopenipmipthread
 +    liboping  . . . . . . $with_liboping
 +    libpcap . . . . . . . $with_libpcap
 +    libperl . . . . . . . $with_libperl
 +    libpthread  . . . . . $with_libpthread
 +    librrd  . . . . . . . $with_rrdtool
 +    libsensors  . . . . . $with_lm_sensors
 +    libstatgrab . . . . . $with_libstatgrab
 +    libupsclient  . . . . $with_libupsclient
 +    libvirt . . . . . . . $with_libvirt
 +    libxml2 . . . . . . . $with_libxml2
 +    libxmms . . . . . . . $with_libxmms
  
    Features:
 -    daemon mode . . . . $enable_daemon
 -    debug . . . . . . . $enable_debug
 +    daemon mode . . . . $enable_daemon
 +    debug . . . . . . . $enable_debug
  
    Bindings:
 -    perl  . . . . . . . $with_perl_bindings
 +    perl  . . . . . . . $with_perl_bindings
  
    Modules:
 -    apache  . . . . . . $enable_apache
 -    apcups  . . . . . . $enable_apcups
 -    apple_sensors . . . $enable_apple_sensors
 -    ascent  . . . . . . $enable_ascent
 -    battery . . . . . . $enable_battery
 -    cpu . . . . . . . . $enable_cpu
 -    cpufreq . . . . . . $enable_cpufreq
 -    csv . . . . . . . . $enable_csv
 -    df  . . . . . . . . $enable_df
 -    disk  . . . . . . . $enable_disk
 -    dns . . . . . . . . $enable_dns
 -    email . . . . . . . $enable_email
 -    entropy . . . . . . $enable_entropy
 -    exec  . . . . . . . $enable_exec
 -    hddtemp . . . . . . $enable_hddtemp
 -    interface . . . . . $enable_interface
 -    iptables  . . . . . $enable_iptables
 -    ipmi  . . . . . . . $enable_ipmi
 -    ipvs  . . . . . . . $enable_ipvs
 -    irq . . . . . . . . $enable_irq
 -    libvirt . . . . . . $enable_libvirt
 -    load  . . . . . . . $enable_load
 -    logfile . . . . . . $enable_logfile
 -    mbmon . . . . . . . $enable_mbmon
 -    memcached . . . . . $enable_memcached
 -    memory  . . . . . . $enable_memory
 -    multimeter  . . . . $enable_multimeter
 -    mysql . . . . . . . $enable_mysql
 -    netlink . . . . . . $enable_netlink
 -    network . . . . . . $enable_network
 -    nfs . . . . . . . . $enable_nfs
 -    nginx . . . . . . . $enable_nginx
 -    ntpd  . . . . . . . $enable_ntpd
 -    nut . . . . . . . . $enable_nut
 -    perl  . . . . . . . $enable_perl
 -    ping  . . . . . . . $enable_ping
 -    powerdns  . . . . . $enable_powerdns
 -    processes . . . . . $enable_processes
 -    rrdtool . . . . . . $enable_rrdtool
 -    sensors . . . . . . $enable_sensors
 -    serial  . . . . . . $enable_serial
 -    snmp  . . . . . . . $enable_snmp
 -    swap  . . . . . . . $enable_swap
 -    syslog  . . . . . . $enable_syslog
 -    tail  . . . . . . . $enable_tail
 -    tape  . . . . . . . $enable_tape
 -    tcpconns  . . . . . $enable_tcpconns
 -    teamspeak2  . . . . $enable_teamspeak2
 -    unixsock  . . . . . $enable_unixsock
 -    users . . . . . . . $enable_users
 -    uuid  . . . . . . . $enable_uuid
 -    vmem  . . . . . . . $enable_vmem
 -    vserver . . . . . . $enable_vserver
 -    wireless  . . . . . $enable_wireless
 -    xmms  . . . . . . . $enable_xmms
 +    apache  . . . . . . . $enable_apache
 +    apcups  . . . . . . . $enable_apcups
 +    apple_sensors . . . . $enable_apple_sensors
 +    ascent  . . . . . . . $enable_ascent
 +    battery . . . . . . . $enable_battery
 +    cpu . . . . . . . . . $enable_cpu
 +    cpufreq . . . . . . . $enable_cpufreq
 +    csv . . . . . . . . . $enable_csv
 +    df  . . . . . . . . . $enable_df
 +    disk  . . . . . . . . $enable_disk
 +    dns . . . . . . . . . $enable_dns
 +    email . . . . . . . . $enable_email
 +    entropy . . . . . . . $enable_entropy
 +    exec  . . . . . . . . $enable_exec
 +    hddtemp . . . . . . . $enable_hddtemp
 +    interface . . . . . . $enable_interface
 +    iptables  . . . . . . $enable_iptables
 +    ipmi  . . . . . . . . $enable_ipmi
 +    ipvs  . . . . . . . . $enable_ipvs
 +    irq . . . . . . . . . $enable_irq
 +    libvirt . . . . . . . $enable_libvirt
 +    load  . . . . . . . . $enable_load
 +    logfile . . . . . . . $enable_logfile
 +    mbmon . . . . . . . . $enable_mbmon
 +    memcached . . . . . . $enable_memcached
 +    memory  . . . . . . . $enable_memory
 +    multimeter  . . . . . $enable_multimeter
 +    mysql . . . . . . . . $enable_mysql
 +    netlink . . . . . . . $enable_netlink
 +    network . . . . . . . $enable_network
 +    nfs . . . . . . . . . $enable_nfs
 +    nginx . . . . . . . . $enable_nginx
 +    notify_desktop  . . . $enable_notify_desktop
 +    notify_email  . . . . $enable_notify_email
 +    ntpd  . . . . . . . . $enable_ntpd
 +    nut . . . . . . . . . $enable_nut
 +    perl  . . . . . . . . $enable_perl
 +    ping  . . . . . . . . $enable_ping
 +    powerdns  . . . . . . $enable_powerdns
 +    processes . . . . . . $enable_processes
 +    rrdtool . . . . . . . $enable_rrdtool
 +    sensors . . . . . . . $enable_sensors
 +    serial  . . . . . . . $enable_serial
 +    snmp  . . . . . . . . $enable_snmp
 +    swap  . . . . . . . . $enable_swap
 +    syslog  . . . . . . . $enable_syslog
 +    tail  . . . . . . . . $enable_tail
 +    tape  . . . . . . . . $enable_tape
 +    tcpconns  . . . . . . $enable_tcpconns
 +    teamspeak2  . . . . . $enable_teamspeak2
 +    unixsock  . . . . . . $enable_unixsock
 +    users . . . . . . . . $enable_users
 +    uuid  . . . . . . . . $enable_uuid
 +    vmem  . . . . . . . . $enable_vmem
 +    vserver . . . . . . . $enable_vserver
 +    wireless  . . . . . . $enable_wireless
 +    xmms  . . . . . . . . $enable_xmms
  
  EOF
diff --combined src/disk.c
@@@ -215,11 -215,10 +215,11 @@@ static void disk_submit (const char *pl
        vl.time = time (NULL);
        strcpy (vl.host, hostname_g);
        strcpy (vl.plugin, "disk");
 -      strncpy (vl.plugin_instance, plugin_instance,
 +      sstrncpy (vl.plugin_instance, plugin_instance,
                        sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void disk_submit */
  
  #if HAVE_IOKIT_IOKITLIB_H
@@@ -376,8 -375,7 +376,8 @@@ static int disk_read (void
                write_tme = dict_get_value (stats_dict,
                                kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
  
 -              if (snprintf (disk_name, 64, "%i-%i", disk_major, disk_minor) >= 64)
 +              if (ssnprintf (disk_name, sizeof (disk_name),
 +                              "%i-%i", disk_major, disk_minor) >= sizeof (disk_name))
                {
                        DEBUG ("snprintf (major, minor) failed.");
                        CFRelease (child_dict);
                major = atoll (fields[0]);
                minor = atoll (fields[1]);
  
-               disk_name = fields[2];
+               disk_name = fields[2 + fieldshift];
  
                for (ds = disklist, pre_ds = disklist; ds != NULL; pre_ds = ds, ds = ds->next)
                        if (strcmp (disk_name, ds->name) == 0)
diff --combined src/network.c
@@@ -183,7 -183,7 +183,7 @@@ static pthread_mutex_t send_buffer_loc
  
  static c_avl_tree_t      *cache_tree = NULL;
  static pthread_mutex_t  cache_lock = PTHREAD_MUTEX_INITIALIZER;
- static time_t           cache_flush_last;
+ static time_t           cache_flush_last = 0;
  static int              cache_flush_interval = 1800;
  
  /*
@@@ -246,7 -246,7 +246,7 @@@ static int cache_flush (void
        return (0);
  } /* int cache_flush */
  
 -static int cache_check (const char *type, const value_list_t *vl)
 +static int cache_check (const value_list_t *vl)
  {
        char key[1024];
        time_t *value = NULL;
                return (-1);
  
        if (format_name (key, sizeof (key), vl->host, vl->plugin,
 -                              vl->plugin_instance, type, vl->type_instance))
 +                              vl->plugin_instance, vl->type, vl->type_instance))
                return (-1);
  
        pthread_mutex_lock (&cache_lock);
@@@ -678,12 -678,14 +678,12 @@@ static int parse_packet (void *buffer, 
        int status;
  
        value_list_t vl = VALUE_LIST_INIT;
 -      char type[DATA_MAX_NAME_LEN];
        notification_t n;
  
        DEBUG ("network plugin: parse_packet: buffer = %p; buffer_len = %i;",
                        buffer, buffer_len);
  
        memset (&vl, '\0', sizeof (vl));
 -      memset (&type, '\0', sizeof (type));
        memset (&n, '\0', sizeof (n));
        status = 0;
  
                        if ((vl.time > 0)
                                        && (strlen (vl.host) > 0)
                                        && (strlen (vl.plugin) > 0)
 -                                      && (strlen (type) > 0)
 -                                      && (cache_check (type, &vl) == 0))
 +                                      && (strlen (vl.type) > 0)
 +                                      && (cache_check (&vl) == 0))
                        {
 -                              plugin_dispatch_values (type, &vl);
 +                              plugin_dispatch_values (&vl);
                        }
                        else
                        {
                else if (pkg_type == TYPE_TYPE)
                {
                        status = parse_part_string (&buffer, &buffer_len,
 -                                      type, sizeof (type));
 +                                      vl.type, sizeof (vl.type));
                        if (status == 0)
 -                              sstrncpy (n.type, type, sizeof (n.type));
 +                              sstrncpy (n.type, vl.type, sizeof (n.type));
                }
                else if (pkg_type == TYPE_TYPE_INSTANCE)
                {
@@@ -1439,12 -1441,12 +1439,12 @@@ static int add_to_buffer (char *buffer
                strcpy (vl_def->plugin_instance, vl->plugin_instance);
        }
  
 -      if (strcmp (type_def, ds->type) != 0)
 +      if (strcmp (type_def, vl->type) != 0)
        {
                if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
 -                                      ds->type, strlen (ds->type)) != 0)
 +                                      vl->type, strlen (vl->type)) != 0)
                        return (-1);
 -              strcpy (type_def, ds->type);
 +              strcpy (type_def, vl->type);
        }
  
        if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
@@@ -1481,7 -1483,7 +1481,7 @@@ static int network_write (const data_se
        /* If the value is already in the cache, we have received it via the
         * network. We write it again if forwarding is activated. It's then in
         * the cache and should we receive it again we will ignore it. */
 -      status = cache_check (ds->type, vl);
 +      status = cache_check (vl);
        if ((network_config_forward == 0)
                        && (status != 0))
                return (0);
@@@ -1704,11 -1706,19 +1704,19 @@@ static int network_shutdown (void
        plugin_unregister_write ("network");
        plugin_unregister_shutdown ("network");
  
+       /* Let the init function do it's move again ;) */
+       cache_flush_last = 0;
        return (0);
  } /* int network_shutdown */
  
  static int network_init (void)
  {
+       /* Check if we were already initialized. If so, just return - there's
+        * nothing more to do (for now, that is). */
+       if (cache_flush_last != 0)
+               return (0);
        plugin_register_shutdown ("network", network_shutdown);
  
        send_buffer_ptr  = send_buffer;
        return (0);
  } /* int network_init */
  
 -static int network_flush (int timeout)
 +/* 
 + * The flush option of the network plugin cannot flush individual identifiers.
 + * All the values are added to a buffer and sent when the buffer is full, the
 + * requested value may or may not be in there, it's not worth finding out. We
 + * just send the buffer if `flush'  is called - if the requested value was in
 + * there, good. If not, well, then there is nothing to flush.. -octo
 + */
 +static int network_flush (int timeout, const char *identifier)
  {
        pthread_mutex_lock (&send_buffer_lock);
  
diff --combined src/plugin.h
@@@ -74,13 -74,12 +74,13 @@@ struct value_list_
        char     host[DATA_MAX_NAME_LEN];
        char     plugin[DATA_MAX_NAME_LEN];
        char     plugin_instance[DATA_MAX_NAME_LEN];
 +      char     type[DATA_MAX_NAME_LEN];
        char     type_instance[DATA_MAX_NAME_LEN];
  };
  typedef struct value_list_s value_list_t;
  
 -#define VALUE_LIST_INIT { NULL, 0, 0, interval_g, "localhost", "", "", "" }
 -#define VALUE_LIST_STATIC { NULL, 0, 0, 0, "localhost", "", "", "" }
 +#define VALUE_LIST_INIT { NULL, 0, 0, interval_g, "localhost", "", "", "", "" }
 +#define VALUE_LIST_STATIC { NULL, 0, 0, 0, "localhost", "", "", "", "" }
  
  struct data_source_s
  {
@@@ -151,11 -150,10 +151,11 @@@ int plugin_load (const char *name)
  
  void plugin_init_all (void);
  void plugin_read_all (void);
 -void plugin_flush_all (int timeout);
  void plugin_shutdown_all (void);
  
 +void plugin_flush_all (int timeout);
  int plugin_flush_one (int timeout, const char *name);
 +int plugin_flush (const char *plugin, int timeout, const char *identifier);
  
  /*
   * The `plugin_register_*' functions are used to make `config', `init',
@@@ -174,7 -172,7 +174,7 @@@ int plugin_register_read (const char *n
  int plugin_register_write (const char *name,
                int (*callback) (const data_set_t *ds, const value_list_t *vl));
  int plugin_register_flush (const char *name,
 -              int (*callback) (const int));
 +              int (*callback) (const int timeout, const char *identifier));
  int plugin_register_shutdown (char *name,
                int (*callback) (void));
  int plugin_register_data_set (const data_set_t *ds);
@@@ -206,14 -204,17 +206,16 @@@ int plugin_unregister_notification (con
   *  write-functions.
   *
   * ARGUMENTS
 - *  `name'      Name/type of the data-set that describe the values in `vl'.
   *  `vl'        Value list of the values that have been read by a `read'
   *              function.
   */
 -int plugin_dispatch_values (const char *name, value_list_t *vl);
 +int plugin_dispatch_values (value_list_t *vl);
  
  int plugin_dispatch_notification (const notification_t *notif);
  
- void plugin_log (int level, const char *format, ...);
+ void plugin_log (int level, const char *format, ...)
+       __attribute__ ((format(printf,2,3)));
  #define ERROR(...)   plugin_log (LOG_ERR,     __VA_ARGS__)
  #define WARNING(...) plugin_log (LOG_WARNING, __VA_ARGS__)
  #define NOTICE(...)  plugin_log (LOG_NOTICE,  __VA_ARGS__)
diff --combined src/wireless.c
@@@ -58,11 -58,10 +58,11 @@@ static void wireless_submit (const cha
        vl.time = time (NULL);
        strcpy (vl.host, hostname_g);
        strcpy (vl.plugin, "wireless");
 -      strncpy (vl.plugin_instance, plugin_instance,
 +      sstrncpy (vl.plugin_instance, plugin_instance,
                        sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void wireless_submit */
  
  #define POWER_MIN -90.0
@@@ -129,7 -128,9 +129,9 @@@ static int wireless_read (void
                        power = 1.0; /* invalid */
                else if ((power >= 0.0) && (power <= 100.0))
                        power = wireless_percent_to_power (power);
-               else if (power > 100.0)
+               else if ((power > 100.0) && (power <= 256.0))
+                       power = power - 256.0;
+               else if (power > 0.0)
                        power = 1.0; /* invalid */
  
                /* noise [dBm] < 0.0 */
                        noise = 1.0; /* invalid */
                else if ((noise >= 0.0) && (noise <= 100.0))
                        noise = wireless_percent_to_power (noise);
-               else if (noise > 100.0)
+               else if ((noise > 100.0) && (noise <= 256.0))
+                       noise = noise - 256.0;
+               else if (noise > 0.0)
                        noise = 1.0; /* invalid */
  
                wireless_submit (device, "signal_quality", quality);