]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
initial attempt at statistics handling
authorAlan T. DeKok <aland@freeradius.org>
Thu, 29 Sep 2022 21:29:29 +0000 (17:29 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 29 Sep 2022 22:09:34 +0000 (18:09 -0400)
src/lib/util/libfreeradius-util.mk
src/lib/util/stats.c [new file with mode: 0644]
src/lib/util/stats.h [new file with mode: 0644]

index 1b0af87db1d84f8200488e128907dcfca8f76bfc..86ed0cc8f719dc46a15262ff387fb739b3714c12 100644 (file)
@@ -77,6 +77,7 @@ SOURCES               := \
                   size.c \
                   snprintf.c \
                   socket.c \
+                  stats.c \
                   strerror.c \
                   strlcat.c \
                   strlcpy.c \
diff --git a/src/lib/util/stats.c b/src/lib/util/stats.c
new file mode 100644 (file)
index 0000000..89139ef
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Map internal data structures to statistics
+ *
+ * @file src/lib/util/stats.c
+ *
+ * @copyright 2022 Network RADIUS SAS (legal@networkradius.com)
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/util/stats.h>
+
+/** Define dictionary attributes for a given statistics structure.
+ *
+ *  @param     parent the parent attribute under which statistics are defined
+ *  @param     stats the statistics mapping structure.
+ *  @return
+ *     - <0 on error
+ *     - 0 on success
+ */
+int fr_stats_attr_init(fr_dict_attr_t *parent, fr_stats_struct_t const *stats)
+{
+       fr_stats_entry_t const *entry;
+       fr_dict_t *dict;
+
+       dict = fr_dict_unconst(fr_dict_by_da(parent));
+
+       for (entry = &stats->table[0]; entry->name != NULL; entry++) {
+               fr_dict_attr_flags_t flags = {
+                       .internal = true,
+                       .counter = entry->flags.counter,
+               };
+
+               fr_assert(entry->number > 0);
+               fr_assert((entry->type == FR_TYPE_TIME_DELTA) || (fr_type_is_integer(entry->type)));
+
+               if (fr_dict_attr_add(dict, parent, entry->name, entry->number, entry->type, &flags) < 0) return -1;
+       }
+
+       return 0;
+}
+
+/** Add statistics VPs for a particular struct / context
+ *
+ *  @param parent      structural vp where the children will be added
+ *  @param stats       structure which maps between #fr_dict_attr_t and internal stats structures
+ *  @param ctx         the internal structure holding the stastics
+ *  @return
+ *     - <0 on error
+ *     - 0 on success
+ */
+int fr_stats_pair_add(fr_pair_t *parent, fr_stats_struct_t const *stats, void const *ctx)
+{
+       fr_stats_entry_t const *entry;
+
+       fr_assert(fr_type_is_structural(parent->da->type));
+
+       for (entry = &stats->table[0]; entry->name != NULL; entry++) {
+               fr_pair_t *vp;
+               fr_dict_attr_t const *da;
+
+               da = fr_dict_attr_child_by_num(parent->da, entry->number);
+               if (!da) {
+                       fr_strerror_printf("Unknown child %d for parent %s", entry->number, parent->da->name);
+                       return -1;
+               }
+
+               vp = fr_pair_afrom_da(parent, da);
+               if (!vp) return -1;
+
+               if (fr_value_box_memcpy_in(&vp->data, ((uint8_t const *) ctx) + entry->offset) < 0) return -1;
+
+               fr_pair_append(&parent->vp_group, vp);
+       }
+
+       return 0;
+}
diff --git a/src/lib/util/stats.h b/src/lib/util/stats.h
new file mode 100644 (file)
index 0000000..fb88889
--- /dev/null
@@ -0,0 +1,66 @@
+#pragma once
+/*
+ *  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 Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that 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
+ */
+
+/**
+ * $Id$
+ *
+ * @file lib/util/stats.h
+ * @brief Structures and functions for statistics.
+ *
+ * @copyright 2022 Network RADIUS SAS (legal@networkradius.com)
+ */
+RCSIDH(stats_h, "$Id$")
+
+#include <freeradius-devel/util/pair.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Define a statistics mapping between dictionary attribute and a field in an internal structure.
+ *
+ *  Note that the data types used in the internal structure have to match the #fr_type_t.
+ */
+typedef struct {
+       char const      *name;          //!< Attribute name
+       fr_type_t       type;           //!< data type for this statistics
+       int             number;         //!< attribute number, so that numbers are consistent
+       struct {
+               bool    counter;        //!< data type is a counter (can add them)
+               bool    gauge;          //!< data type is a gauge (take the maximum)
+       } flags;
+
+       size_t          offset;         //!< from start of the structure
+} fr_stats_entry_t;
+
+#define STATS_ENTRY_TERMINATOR { .attr = NULL }
+
+/** Define a statistics mapping between a public name and an entire internal structure
+ *
+ */
+typedef struct {
+       char const      *name;          //!< of this structure for public consumption
+       fr_stats_entry_t table[];       //!< of mappings
+} fr_stats_struct_t;
+
+int    fr_stats_attr_init(fr_dict_attr_t *parent, fr_stats_struct_t const *stats) CC_HINT(nonnull);
+
+int    fr_stats_pair_add(fr_pair_t *parent, fr_stats_struct_t const *stats, void const *ctx) CC_HINT(nonnull);
+
+#ifdef __cplusplus
+}
+#endif