The branch stable/13 has been updated by rew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=0cfae878f057692b9dc8c8c51630ce0a3a5dd4be

commit 0cfae878f057692b9dc8c8c51630ce0a3a5dd4be
Author:     Robert Wing <[email protected]>
AuthorDate: 2021-10-08 01:00:27 +0000
Commit:     Robert Wing <[email protected]>
CommitDate: 2021-10-10 18:15:18 +0000

    prometheus_sysctl_exporter(8): filter output using a regex
    
    Add two options, -i and -e, for filtering prometheus metrics.
    
    Each option takes a regular expression as an argument. The provided
    regex will be tested against the prometheus metric name.
    
    The -i option includes metrics matching the given regex.
    The -e option excludes metrics matching the given regex.
    
    Sponsored by:   Modirum MDPay
    Sponsored by:   Klara Inc.
    Reviewed by:    0mp, debdrup
    Differential Revision:  https://reviews.freebsd.org/D32269
    
    (cherry picked from commit 8ff2b52241400f2b5c2287b91e6e12b97ffd5773)
---
 .../prometheus_sysctl_exporter.8                   | 18 ++++-
 .../prometheus_sysctl_exporter.c                   | 88 ++++++++++++++++------
 2 files changed, 80 insertions(+), 26 deletions(-)

diff --git a/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.8 
b/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.8
index f4ac44891ecb..7d73e3cab8cd 100644
--- a/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.8
+++ b/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.8
@@ -22,7 +22,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $FreeBSD$
-.Dd December 18, 2016
+.Dd October 7, 2021
 .Dt PROMETHEUS_SYSCTL_EXPORTER 8
 .Os
 .Sh NAME
@@ -31,6 +31,8 @@
 .Sh SYNOPSIS
 .Nm prometheus_sysctl_exporter
 .Op Fl dgh
+.Op Fl e Ar pattern
+.Op Fl i Ar pattern
 .Op Ar prefix ...
 .Sh DESCRIPTION
 Prometheus is a monitoring system that gathers metrics from its targets
@@ -74,12 +76,26 @@ The following options are available:
 .Bl -tag -width indent
 .It Fl d
 Print descriptions of metrics when available.
+.It Fl e Ar pattern
+Same as
+.Fl i ,
+except exclude metrics that match
+.Ar pattern .
 .It Fl g
 Gzip compresses the HTTP response body.
 .It Fl h
 Precede the output with a HTTP response header.
 This flag is required when running this utility through
 .Xr inetd 8 .
+.It Fl i Ar pattern
+If specified, include metrics that match
+.Ar pattern .
+The format of
+.Ar pattern
+is to be a regular expression as described in
+.Xr re_format 7 .
+The provided regular expression is tested against the Prometheus
+metric name.
 .El
 .Sh SEE ALSO
 .Xr cron 8 ,
diff --git a/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c 
b/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c
index b1f24ddf203a..25e60f5dddbe 100644
--- a/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c
+++ b/usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <errno.h>
 #include <math.h>
+#include <regex.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -44,6 +45,10 @@ __FBSDID("$FreeBSD$");
 #include <unistd.h>
 #include <zlib.h>
 
+/* Regular expressions for filtering output. */
+static regex_t inc_regex;
+static regex_t exc_regex;
+
 /*
  * Cursor for iterating over all of the system's sysctl OIDs.
  */
@@ -370,25 +375,27 @@ oid_get_name(const struct oid *o, struct oidname *on)
        on->oid = *o;
 }
 
-/* Prints the name and labels of an OID to a file stream. */
+/* Populates the name and labels of an OID to a buffer. */
 static void
-oidname_print(const struct oidname *on, const struct oidformat *of,
-    FILE *fp)
+oid_get_metric(const struct oidname *on, const struct oidformat *of,
+    char *metric, size_t mlen)
 {
        const char *name, *label;
        size_t i;
-       char separator;
+       char separator, buf[BUFSIZ];
 
        /* Print the name of the metric. */
-       fprintf(fp, "sysctl");
+       snprintf(metric, mlen, "%s", "sysctl");
        name = on->names;
        label = on->labels;
        for (i = 0; i < on->oid.len; ++i) {
                if (*label == '\0') {
-                       fputc('_', fp);
+                       strlcat(metric, "_", mlen);
                        while (*name != '\0') {
                                /* Map unsupported characters to underscores. */
-                               fputc(isalnum(*name) ? *name : '_', fp);
+                               snprintf(buf, sizeof(buf), "%c",
+                                   isalnum(*name) ? *name : '_');
+                               strlcat(metric, buf, mlen);
                                ++name;
                        }
                }
@@ -396,9 +403,9 @@ oidname_print(const struct oidname *on, const struct 
oidformat *of,
                label += strlen(label) + 1;
        }
        if (oidformat_is_temperature(of))
-               fprintf(fp, "_celcius");
+               strlcat(metric, "_celcius", mlen);
        else if (oidformat_is_timeval(of))
-               fprintf(fp, "_seconds");
+               strlcat(metric, "_seconds", mlen);
 
        /* Print the labels of the metric. */
        name = on->names;
@@ -410,21 +417,23 @@ oidname_print(const struct oidname *on, const struct 
oidformat *of,
                            "abcdefghijklmnopqrstuvwxyz"
                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                            "0123456789_")] == '\0');
-                       fprintf(fp, "%c%s=\"", separator, label);
+                       snprintf(buf, sizeof(buf), "%c%s=\"", separator, label);
+                       strlcat(metric, buf, mlen);
                        while (*name != '\0') {
                                /* Escape backslashes and double quotes. */
                                if (*name == '\\' || *name == '"')
-                                       fputc('\\', fp);
-                               fputc(*name++, fp);
+                                       strlcat(metric, "\\", mlen);
+                               snprintf(buf, sizeof(buf), "%c", *name++);
+                               strlcat(metric, buf, mlen);
                        }
-                       fputc('"', fp);
+                       strlcat(metric, "\"", mlen);
                        separator = ',';
                }
                name += strlen(name) + 1;
                label += strlen(label) + 1;
        }
        if (separator != '{')
-               fputc('}', fp);
+               strlcat(metric, "}", mlen);
 }
 
 /* Returns whether the OID name has any labels associated to it. */
@@ -483,16 +492,25 @@ oiddescription_print(const struct oiddescription *od, 
FILE *fp)
 
 static void
 oid_print(const struct oid *o, struct oidname *on, bool print_description,
-    FILE *fp)
+    bool exclude, bool include, FILE *fp)
 {
        struct oidformat of;
        struct oidvalue ov;
        struct oiddescription od;
+       char metric[BUFSIZ];
 
        if (!oid_get_format(o, &of) || !oid_get_value(o, &of, &ov))
                return;
        oid_get_name(o, on);
 
+       oid_get_metric(on, &of, metric, sizeof(metric));
+
+       if (exclude && regexec(&exc_regex, metric, 0, NULL, 0) == 0)
+               return;
+
+       if (include && regexec(&inc_regex, metric, 0, NULL, 0) != 0)
+               return;
+
        /*
         * Print the line with the description. Prometheus expects a
         * single unique description for every metric, which cannot be
@@ -502,14 +520,14 @@ oid_print(const struct oid *o, struct oidname *on, bool 
print_description,
        if (print_description && !oidname_has_labels(on) &&
            oid_get_description(o, &od)) {
                fprintf(fp, "# HELP ");
-               oidname_print(on, &of, fp);
+               fprintf(fp, "%s", metric);
                fputc(' ', fp);
                oiddescription_print(&od, fp);
                fputc('\n', fp);
        }
 
        /* Print the line with the value. */
-       oidname_print(on, &of, fp);
+       fprintf(fp, "%s", metric);
        fputc(' ', fp);
        oidvalue_print(&ov, fp);
        fputc('\n', fp);
@@ -539,8 +557,9 @@ static void
 usage(void)
 {
 
-       fprintf(stderr,
-           "usage: prometheus_sysctl_exporter [-dgh] [prefix ...]\n");
+       fprintf(stderr, "%s",
+           "usage: prometheus_sysctl_exporter [-dgh] [-e pattern] [-i 
pattern]\n"
+           "\t[prefix ...]\n");
        exit(1);
 }
 
@@ -551,22 +570,41 @@ main(int argc, char *argv[])
        char *http_buf;
        FILE *fp;
        size_t http_buflen;
-       int ch;
-       bool gzip_mode, http_mode, print_descriptions;
+       int ch, error;
+       bool exclude, include, gzip_mode, http_mode, print_descriptions;
+       char errbuf[BUFSIZ];
 
        /* Parse command line flags. */
-       gzip_mode = http_mode = print_descriptions = false;
-       while ((ch = getopt(argc, argv, "dgh")) != -1) {
+       include = exclude = gzip_mode = http_mode = print_descriptions = false;
+       while ((ch = getopt(argc, argv, "de:ghi:")) != -1) {
                switch (ch) {
                case 'd':
                        print_descriptions = true;
                        break;
+               case 'e':
+                       error = regcomp(&exc_regex, optarg, REG_EXTENDED);
+                       if (error != 0) {
+                               regerror(error, &exc_regex, errbuf, 
sizeof(errbuf));
+                               errx(1, "bad regular expression '%s': %s",
+                                   optarg, errbuf);
+                       }
+                       exclude = true;
+                       break;
                case 'g':
                        gzip_mode = true;
                        break;
                case 'h':
                        http_mode = true;
                        break;
+               case 'i':
+                       error = regcomp(&inc_regex, optarg, REG_EXTENDED);
+                       if (error != 0) {
+                               regerror(error, &inc_regex, errbuf, 
sizeof(errbuf));
+                               errx(1, "bad regular expression '%s': %s",
+                                   optarg, errbuf);
+                       }
+                       include = true;
+                       break;
                default:
                        usage();
                }
@@ -590,7 +628,7 @@ main(int argc, char *argv[])
                /* Print all OIDs. */
                oid_get_root(&o);
                do {
-                       oid_print(&o, &on, print_descriptions, fp);
+                       oid_print(&o, &on, print_descriptions, exclude, 
include, fp);
                } while (oid_get_next(&o, &o));
        } else {
                int i;
@@ -602,7 +640,7 @@ main(int argc, char *argv[])
                        oid_get_by_name(&root, argv[i]);
                        o = root;
                        do {
-                               oid_print(&o, &on, print_descriptions, fp);
+                               oid_print(&o, &on, print_descriptions, exclude, 
include, fp);
                        } while (oid_get_next(&o, &o) &&
                            oid_is_beneath(&o, &root));
                }

Reply via email to