Merge pull request #2733 from elfiesmelfie/feat_pcie_aer
authorPavel Rochnyak <pavel2000@ngs.ru>
Thu, 5 Jul 2018 09:03:17 +0000 (16:03 +0700)
committerGitHub <noreply@github.com>
Thu, 5 Jul 2018 09:03:17 +0000 (16:03 +0700)
New plugin to read PCIe errors

1  2 
Makefile.am
configure.ac
src/collectd.conf.in
src/collectd.conf.pod

diff --combined Makefile.am
@@@ -1381,6 -1381,24 +1381,24 @@@ ovs_stats_la_LDFLAGS = $(PLUGIN_LDFLAGS
  ovs_stats_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
  endif
  
+ if BUILD_PLUGIN_PCIE_ERRORS
+ pkglib_LTLIBRARIES += pcie_errors.la
+ pcie_errors_la_SOURCES = src/pcie_errors.c
+ pcie_errors_la_CPPFLAGS = $(AM_CPPFLAGS)
+ pcie_errors_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ test_plugin_pcie_errors_SOURCES = \
+       src/pcie_errors_test.c \
+       src/daemon/utils_llist.c \
+       src/daemon/configfile.c \
+       src/daemon/types_list.c
+ test_plugin_pcie_errors_CPPFLAGS = $(AM_CPPFLAGS)
+ test_plugin_pcie_errors_LDFLAGS = $(PLUGIN_LDFLAGS)
+ test_plugin_pcie_errors_LDADD = liboconfig.la libplugin_mock.la
+ check_PROGRAMS += test_plugin_pcie_errors
+ TESTS += test_plugin_pcie_errors
+ endif
  if BUILD_PLUGIN_PERL
  pkglib_LTLIBRARIES += perl.la
  perl_la_SOURCES = src/perl.c
@@@ -1558,7 -1576,7 +1576,7 @@@ pkglib_LTLIBRARIES += snmp.l
  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
@@@ -1567,23 -1585,6 +1585,23 @@@ snmp_agent_la_SOURCES = src/snmp_agent.
  snmp_agent_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBNETSNMPAGENT_CPPFLAGS)
  snmp_agent_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBNETSNMPAGENT_LDFLAGS)
  snmp_agent_la_LIBADD = $(BUILD_WITH_LIBNETSNMPAGENT_LIBS)
 +
 +test_plugin_snmp_agent_SOURCES = src/snmp_agent_test.c \
 +                                 src/daemon/utils_avltree.c \
 +                                 src/daemon/utils_llist.c \
 +                                 src/daemon/configfile.c \
 +                                 src/daemon/types_list.c
 +test_plugin_snmp_agent_CPPFLAGS = $(AM_CPPFLAGS) \
 +      $(BUILD_WITH_LIBNETSNMPAGENT_CPPFLAGS)
 +test_plugin_snmp_agent_LDFLAGS = $(PLUGIN_LDFLAGS) \
 +      $(BUILD_WITH_LIBNETSNMPAGENT_LDFLAGS)
 +test_plugin_snmp_agent_LDADD = liboconfig.la libplugin_mock.la \
 +      $(BUILD_WITH_LIBNETSNMPAGENT_LIBS) $(BUILD_WITH_LIBNETSNMP_LIBS)
 +
 +check_PROGRAMS += test_plugin_snmp_agent
 +TESTS += test_plugin_snmp_agent
 +
 +
  endif
  
  if BUILD_PLUGIN_STATSD
diff --combined configure.ac
@@@ -550,6 -550,12 +550,12 @@@ if test "x$ac_system" = "xLinux"; the
      AC_DEFINE([HAVE_CAPABILITY], [1], [Define to 1 if you have cap_get_proc() (-lcap).])
    fi
  
+   # For pcie_errors plugin
+   AC_CHECK_HEADERS([linux/pci_regs.h],
+     [have_pci_regs_h="yes"],
+     [have_pci_regs_h="no (linux/pci_regs.h not found)"]
+   )
  else
    have_linux_raid_md_u_h="no"
    have_linux_wireless_h="no"
@@@ -767,8 -773,6 +773,8 @@@ AC_FUNC_STRERROR_
  
  SAVE_CFLAGS="$CFLAGS"
  CFLAGS="-Wall -Werror"
 +SAVE_LDFAGS="$LDFLAGS"
 +LDFLAGS=""
  
  AC_CACHE_CHECK([for strtok_r],
    [c_cv_have_strtok_r_default],
@@@ -841,7 -845,6 +847,7 @@@ if test "x$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
@@@ -3817,7 -3820,7 +3823,7 @@@ if test "x$with_libnetsnmp" = "xyes"; t
    LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags"
  
    AC_CHECK_LIB([netsnmp], [init_snmp],
 -    [with_libnetsmp="yes"],
 +    [with_libnetsnmp="yes"],
      [with_libnetsnmp="no (libnetsnmp not found)"]
    )
  
  fi
  
  if test "x$with_libnetsnmp" = "xyes"; then
 +  SAVE_LDFLAGS="$LDFLAGS"
 +  LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags"
 +
 +  AC_CHECK_LIB([netsnmp], [netsnmp_get_version],
 +    [with_libnetsnmp="yes"],
 +    [with_libnetsnmp="no (couldn't get libnetsnmp version)"]
 +  )
 +
 +  LDFLAGS="$SAVE_LDFLAGS"
 +fi
 +
 +if test "x$with_libnetsnmp" = "xyes"; then
 +  SAVE_CPPFLAGS="$CPPFLAGS"
 +  SAVE_LDFLAGS="$LDFLAGS"
 +  SAVE_LIBS="$LIBS"
 +  CPPFLAGS="$CPPFLAGS $with_libnetsnmp_cppflags -Wall -Werror"
 +  LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags"
 +  LIBS="$LIBS -lnetsnmp"
 +
 +  AC_CACHE_CHECK([whether netsnmp library has old API],
 +    [c_cv_have_netsnmp_old_api],
 +    [
 +      AC_LINK_IFELSE(
 +        [
 +          AC_LANG_PROGRAM(
 +            [[
 +              #include <net-snmp/net-snmp-config.h>
 +              #include <net-snmp/net-snmp-includes.h>
 +            ]],
 +            [[
 +              netsnmp_variable_list *key = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);;
 +              int val;
 +              u_char type = ASN_INTEGER;
 +              snmp_set_var_value(key, &val, sizeof(val));
 +              snmp_set_var_typed_value(key, type, &val, sizeof(val));
 +              return 0;
 +            ]]
 +          )
 +        ],
 +        [c_cv_have_netsnmp_old_api="no"],
 +        [c_cv_have_netsnmp_old_api="yes"]
 +      )
 +    ]
 +  )
 +
 +  if test "x$c_cv_have_netsnmp_old_api" = "xyes"; then
 +    AC_DEFINE([HAVE_NETSNMP_OLD_API], [1],
 +              ["Define 1 if you have old netsnmp API]")
 +  fi
 +
 +  CPPFLAGS="$SAVE_CPPFLAGS"
 +  LDFLAGS="$SAVE_LDFLAGS"
 +  LIBS="$SAVE_LIBS"
 +fi
 +
 +if test "x$with_libnetsnmp" = "xyes"; then
    BUILD_WITH_LIBNETSNMP_CPPFLAGS="$with_libnetsnmp_cppflags"
    BUILD_WITH_LIBNETSNMP_LDFLAGS="$with_libnetsnmp_ldflags"
    BUILD_WITH_LIBNETSNMP_LIBS="-lnetsnmp"
@@@ -3891,7 -3838,7 +3897,7 @@@ AC_SUBST([BUILD_WITH_LIBNETSNMP_LDFLAGS
  AC_SUBST([BUILD_WITH_LIBNETSNMP_LIBS])
  # }}}
  
 -# --with-libnetsmpagent {{{
 +# --with-libnetsnmpagent {{{
  AC_ARG_WITH([libnetsnmpagent],
    [AS_HELP_STRING([--with-libnetsnmpagent@<:@=PREFIX@:>@], [Path to libnetsnmpagent.])],
    [
@@@ -6288,6 -6235,7 +6294,7 @@@ plugin_nfs="no
  plugin_numa="no"
  plugin_ovs_events="no"
  plugin_ovs_stats="no"
+ plugin_pcie_errors="no"
  plugin_perl="no"
  plugin_pinba="no"
  plugin_processes="no"
@@@ -6366,6 -6314,10 +6373,10 @@@ if test "x$ac_system" = "xLinux"; the
      plugin_ovs_events="yes"
      plugin_ovs_stats="yes"
    fi
+   if test "x$have_pci_regs_h" = "xyes"; then
+     plugin_pcie_errors="yes"
+   fi
  fi
  
  if test "x$ac_system" = "xOpenBSD"; then
@@@ -6743,6 -6695,7 +6754,7 @@@ AC_PLUGIN([openvpn],             [yes]
  AC_PLUGIN([oracle],              [$with_oracle],            [Oracle plugin])
  AC_PLUGIN([ovs_events],          [$plugin_ovs_events],      [OVS events plugin])
  AC_PLUGIN([ovs_stats],           [$plugin_ovs_stats],       [OVS statistics plugin])
+ AC_PLUGIN([pcie_errors],         [$plugin_pcie_errors],     [PCIe errors plugin])
  AC_PLUGIN([perl],                [$plugin_perl],            [Embed a Perl interpreter])
  AC_PLUGIN([pf],                  [$have_net_pfvar_h],       [BSD packet filter (PF) statistics])
  # FIXME: Check for libevent, too.
@@@ -7164,6 -7117,7 +7176,7 @@@ AC_MSG_RESULT([    openvpn . . . . . . 
  AC_MSG_RESULT([    oracle  . . . . . . . $enable_oracle])
  AC_MSG_RESULT([    ovs_events  . . . . . $enable_ovs_events])
  AC_MSG_RESULT([    ovs_stats . . . . . . $enable_ovs_stats])
+ AC_MSG_RESULT([    pcie_errors . . . . . $enable_pcie_errors])
  AC_MSG_RESULT([    perl  . . . . . . . . $enable_perl])
  AC_MSG_RESULT([    pf  . . . . . . . . . $enable_pf])
  AC_MSG_RESULT([    pinba . . . . . . . . $enable_pinba])
diff --combined src/collectd.conf.in
  #@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
  #@BUILD_PLUGIN_OVS_EVENTS_TRUE@LoadPlugin ovs_events
  #@BUILD_PLUGIN_OVS_STATS_TRUE@LoadPlugin ovs_stats
+ #@BUILD_PLUGIN_PCIE_ERRORS_TRUE@LoadPlugin pcie_errors
  #@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
  #@BUILD_PLUGIN_PINBA_TRUE@LoadPlugin pinba
  #@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
  #  Bridges "br0" "br_ext"
  #</Plugin>
  
+ #<Plugin pcie_errors>
+ #  Source "sysfs"
+ #  ReportMasked false
+ #  PersistentNotifications false
+ #</Plugin>
  #<Plugin perl>
  #     IncludeDir "/my/include/path"
  #     BaseName "Collectd::Plugins"
  
  #<Plugin snmp>
  #   <Data "powerplus_voltge_input">
 -#       Type "voltage"
  #       Table false
 -#       Instance "input_line1"
 +#       Type "voltage"
 +#       TypeInstance "input_line1"
  #       Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1"
  #   </Data>
  #   <Data "hr_users">
 -#       Type "users"
  #       Table false
 -#       Instance ""
 +#       Type "users"
 +#       TypeInstance ""
  #       Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0"
  #   </Data>
  #   <Data "std_traffic">
 +#       Table true
  #       Type "if_octets"
 +#       TypeInstanceOID "IF-MIB::ifDescr"
 +#       #TypeInstancePrefix "port"
 +#       Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
 +#       #FilterOID "IF-MIB::ifOperStatus"
 +#       #FilterValues "1", "2"
 +#   </Data>
 +#   <Data "interface_traffic">
  #       Table true
 -#       Instance "IF-MIB::ifDescr"
 +#       Type "if_octets"
 +#       Plugin "interface"
 +#       PluginInstanceOID "IF-MIB::ifDescr"
  #       Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
  #   </Data>
  #
  #    IndexOID "IF-MIB::ifIndex"
  #    SizeOID "IF-MIB::ifNumber"
  #    <Data "ifDescr">
 -#      Instance true
 +#      <IndexKey>
 +#        Source "PluginInstance"
 +#      </IndexKey>
  #      Plugin "interface"
  #      OIDs "IF-MIB::ifDescr"
  #    </Data>
diff --combined src/collectd.conf.pod
@@@ -1908,11 -1908,6 +1908,11 @@@ plugin below on how matches are defined
  B<MeasureResponseCode> options are set to B<true>, B<Match> blocks are
  optional.
  
 +=item B<Interval> I<Interval>
 +
 +Sets the interval (in seconds) in which the values will be collected from this
 +URL. By default the global B<Interval> setting will be used.
 +
  =item B<Timeout> I<Milliseconds>
  
  The B<Timeout> option sets the overall timeout for HTTP requests to B<URL>, in
@@@ -2109,11 -2104,6 +2109,11 @@@ Use I<Instance> as the plugin instance 
  May be overridden by B<PluginInstanceFrom> option inside B<XPath> blocks.
  Defaults to an empty string (no plugin instance).
  
 +=item B<Interval> I<Interval>
 +
 +Sets the interval (in seconds) in which the values will be collected from this
 +URL. By default the global B<Interval> setting will be used.
 +
  =item B<Namespace> I<Prefix> I<URL>
  
  If an XPath expression references namespaces, they must be specified
@@@ -5448,12 -5438,6 +5448,12 @@@ behavior is to let the kernel choose th
  that the manual selection of an interface for unicast traffic is only
  necessary in rare cases.
  
 +=item B<BindAddress> I<IP Address>
 +
 +Set the outgoing IP address for IP packets. This option can be used instead of
 +the I<Interface> option to explicitly define the IP address which will be used
 +to send Packets to the remote server. 
 +
  =item B<ResolveInterval> I<Seconds>
  
  Sets the interval at which to re-resolve the DNS for the I<Host>. This is
@@@ -6281,6 -6265,52 +6281,52 @@@ Default: empty (monitor all bridges
  
  =back
  
+ =head2 Plugin C<pcie_errors>
+ The I<pcie_errors> plugin collects PCI Express errors from Device Status in Capability
+ structure and from Advanced Error Reporting Extended Capability where available.
+ At every read it polls config space of PCI Express devices and dispatches
+ notification for every error that is set. It checks for new errors at every read.
+ The device is indicated in plugin_instance according to format "domain:bus:dev.fn".
+ Errors are divided into categories indicated by type_instance: "correctable", and
+ for uncorrectable errors "non_fatal" or "fatal".
+ Fatal errors are reported as I<NOTIF_FAILURE> and all others as I<NOTIF_WARNING>.
+ B<Synopsis:>
+   <Plugin "pcie_errors">
+     Source "sysfs"
+     AccessDir "/sys/bus/pci"
+     ReportMasked false
+     PersistentNotifications false
+   </Plugin>
+ B<Options:>
+ =over 4
+ =item B<Source> B<sysfs>|B<proc>
+ Use B<sysfs> or B<proc> to read data from /sysfs or /proc.
+ The default value is B<sysfs>.
+ =item B<AccessDir> I<dir>
+ Directory used to access device config space. It is optional and defaults to
+ /sys/bus/pci for B<sysfs> and to /proc/bus/pci for B<proc>.
+ =item B<ReportMasked> B<false>|B<true>
+ If true plugin will notify about errors that are set to masked in Error Mask register.
+ Such errors are not reported to the PCI Express Root Complex. Defaults to B<false>.
+ =item B<PersistentNotifications> B<false>|B<true>
+ If false plugin will dispatch notification only on set/clear of error.
+ The ones already reported will be ignored. Defaults to B<false>.
+ =back
  =head2 Plugin C<perl>
  
  This plugin embeds a Perl-interpreter into collectd and provides an interface
@@@ -7297,26 -7327,26 +7343,26 @@@ Defaults to B<false>
  
  =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>
  
@@@ -7346,47 -7374,30 +7392,47 @@@ Use I<Password> to authenticate when co
  =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
  
@@@ -7826,9 -7837,7 +7872,9 @@@ B<Synopsis:
        IndexOID "IF-MIB::ifIndex"
        SizeOID "IF-MIB::ifNumber"
        <Data "ifDescr">
 -        Instance true
 +        <IndexKey>
 +          Source "PluginInstance"
 +        </IndexKey>
          Plugin "interface"
          OIDs "IF-MIB::ifDescr"
        </Data>
          OIDs "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
        </Data>
      </Table>
 +    <Table "CPUAffinityTable">
 +      <Data "DomainName">
 +        <IndexKey>
 +          Source "PluginInstance"
 +        </IndexKey>
 +        Plugin "virt"
 +        OIDs "LIBVIRT-HYPERVISOR-MIB::lvhAffinityDomainName"
 +      </Data>
 +      <Data "VCPU">
 +        Plugin "virt"
 +        <IndexKey>
 +          Source "TypeInstance"
 +          Regex "^vcpu_([0-9]{1,3})-cpu_[0-9]{1,3}$"
 +          Group 1
 +        </IndexKey>
 +        OIDs "LIBVIRT-HYPERVISOR-MIB::lvhVCPUIndex"
 +      </Data>
 +      <Data "CPU">
 +        Plugin "virt"
 +        <IndexKey>
 +          Source "TypeInstance"
 +          Regex "^vcpu_[0-9]{1,3}-cpu_([0-9]{1,3})$"
 +          Group 1
 +        </IndexKey>
 +        OIDs "LIBVIRT-HYPERVISOR-MIB::lvhCPUIndex"
 +      </Data>
 +      <Data "CPUAffinity">
 +        Plugin "virt"
 +        Type "cpu_affinity"
 +        OIDs "LIBVIRT-HYPERVISOR-MIB::lvhCPUAffinity"
 +      </Data>
 +    </Table>
    </Plugin>
  
  There are two types of blocks that can be contained in the
  C<E<lt>PluginE<nbsp> snmp_agentE<gt>> block: B<Data> and B<Table>:
  
 -=head3 The B<Data> block
 +=head3 B<Data> block
  
  The B<Data> block defines a list OIDs that are to be handled. This block can
  define scalar or table OIDs. If B<Data> block is defined inside of B<Table>
@@@ -7885,34 -7862,11 +7931,34 @@@ The following options can be set
  
  =over 4
  
 -=item B<Instance> I<true|false>
 +=item B<IndexKey> block
 +
 +B<IndexKey> block contains all data needed for proper index build of snmp table.
 +In case more than
 +one table B<Data> block has B<IndexKey> block present then multiple key index is
 +built. If B<Data> block defines scalar data type B<IndexKey> has no effect and can
 +be omitted.
 +
 +=over 8
 +
 +=item B<Source> I<String>
 +
 +B<Source> can be set to one of the following values: "Hostname", "Plugin",
 +"PluginInstance", "Type", "TypeInstance". This value indicates which field of
 +corresponding collectd metric is taken as a SNMP table index.
 +
 +=item B<Regex> I<String>
  
 -When B<Instance> is set to B<true>, the value for requested OID is copied from
 -plugin instance field of corresponding collectd value. If B<Data> block defines
 -scalar data type B<Instance> has no effect and can be omitted.
 +B<Regex> option can also be used to parse strings or numbers out of
 +specific field. For example: type-instance field which is "vcpu1-cpu2" can be
 +parsed into two numeric fields CPU = 2 and VCPU = 1 and can be later used
 +as a table index.
 +
 +=item B<Group> I<Number>
 +
 +B<Group> number can be specified in case groups are used in regex.
 +
 +=back
  
  =item B<Plugin> I<String>
  
@@@ -9294,7 -9248,6 +9340,7 @@@ Synopsis
       Protocol "tcp"
       LogSendErrors true
       Prefix "collectd"
 +     UseTags false
     </Node>
   </Plugin>
  
@@@ -9332,20 -9285,13 +9378,20 @@@ approach and logging errors fills syslo
  
  =item B<Prefix> I<String>
  
 -When set, I<String> is added in front of the host name. Dots and whitespace are
 -I<not> escaped in this string (see B<EscapeCharacter> below).
 +When B<UseTags> is I<false>, B<Prefix> value is added in front of the host name.
 +When B<UseTags> is I<true>, B<Prefix> value is added in front of series name.
 +
 +Dots and whitespace are I<not> escaped in this string (see B<EscapeCharacter>
 +below).
  
  =item B<Postfix> I<String>
  
 -When set, I<String> is appended to the host name. Dots and whitespace are
 -I<not> escaped in this string (see B<EscapeCharacter> below).
 +When B<UseTags> is I<false>, B<Postfix> value appended to the host name.
 +When B<UseTags> is I<true>, B<Postgix> value appended to the end of series name
 +(before the first ; that separates the name from the tags).
 +
 +Dots and whitespace are I<not> escaped in this string (see B<EscapeCharacter>
 +below).
  
  =item B<EscapeCharacter> I<Char>
  
@@@ -9367,8 -9313,6 +9413,8 @@@ path component, for example C<host.cpu.
  default), the plugin and plugin instance (and likewise the type and type
  instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
  
 +Option value is not used when B<UseTags> is I<true>.
 +
  =item B<AlwaysAppendDS> B<false>|B<true>
  
  If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
@@@ -9381,31 -9325,12 +9427,31 @@@ If set to B<false> (the default) the C<
  I<EscapeCharacter>. Otherwise, if set to B<true>, the C<.> (dot) character
  is preserved, i.e. passed through.
  
 +Option value is not used when B<UseTags> is I<true>.
 +
  =item B<DropDuplicateFields> B<false>|B<true>
  
  If set to B<true>, detect and remove duplicate components in Graphite metric
  names. For example, the metric name  C<host.load.load.shortterm> will
  be shortened to C<host.load.shortterm>.
  
 +=item B<UseTags> B<false>|B<true>
 +
 +If set to B<true>, Graphite metric names will be generated as tagged series.
 +This allows for much more flexibility than the traditional hierarchical layout.
 +
 +Example:
 +C<test.single;host=example.com;plugin=test;plugin_instance=foo;type=single;type_instance=bar>
 +
 +You can use B<Postfix> option to add more tags by specifying it like
 +C<;tag1=value1;tag2=value2>. Note what tagging support was added since Graphite
 +version 1.1.x.
 +
 +If set to B<true>, the B<SeparateInstances> and B<PreserveSeparator> settings
 +are not used.
 +
 +Default value: B<false>.
 +
  =back
  
  =head2 Plugin C<write_log>
@@@ -9831,26 -9756,17 +9877,26 @@@ been set to B<JSON>
  =item B<GraphitePrefix> (B<Format>=I<Graphite> only)
  
  A prefix can be added in the metric name when outputting in the I<Graphite>
 -format. It's added before the I<Host> name.
 +format.
 +
 +When B<GraphiteUseTags> is I<false>, prefix is added before the I<Host> name.
  Metric name will be
  C<E<lt>prefixE<gt>E<lt>hostE<gt>E<lt>postfixE<gt>E<lt>pluginE<gt>E<lt>typeE<gt>E<lt>nameE<gt>>
  
 +When B<GraphiteUseTags> is I<true>, prefix is added in front of series name.
 +
  =item B<GraphitePostfix> (B<Format>=I<Graphite> only)
  
  A postfix can be added in the metric name when outputting in the I<Graphite>
 -format. It's added after the I<Host> name.
 +format.
 +
 +When B<GraphiteUseTags> is I<false>, postfix is added after the I<Host> name.
  Metric name will be
  C<E<lt>prefixE<gt>E<lt>hostE<gt>E<lt>postfixE<gt>E<lt>pluginE<gt>E<lt>typeE<gt>E<lt>nameE<gt>>
  
 +When B<GraphiteUseTags> is I<true>, prefix value appended to the end of series
 +name (before the first ; that separates the name from the tags).
 +
  =item B<GraphiteEscapeChar> (B<Format>=I<Graphite> only)
  
  Specify a character to replace dots (.) in the host part of the metric name.
@@@ -9865,8 -9781,6 +9911,8 @@@ path component, for example C<host.cpu.
  default), the plugin and plugin instance (and likewise the type and type
  instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
  
 +Option value is not used when B<GraphiteUseTags> is I<true>.
 +
  =item B<GraphiteAlwaysAppendDS> B<true>|B<false>
  
  If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
@@@ -9879,14 -9793,6 +9925,14 @@@ If set to B<false> (the default) the C<
  I<GraphiteEscapeChar>. Otherwise, if set to B<true>, the C<.> (dot) character
  is preserved, i.e. passed through.
  
 +Option value is not used when B<GraphiteUseTags> is I<true>.
 +
 +=item B<GraphiteUseTags> B<false>|B<true>
 +
 +If set to B<true> Graphite metric names will be generated as tagged series.
 +
 +Default value: B<false>.
 +
  =item B<StoreRates> B<true>|B<false>
  
  If set to B<true> (the default), convert counter values to rates. If set to