From: Alan T. DeKok Date: Thu, 29 Sep 2022 21:29:29 +0000 (-0400) Subject: initial attempt at statistics handling X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=434a0c7b15f2b97eec3847348c99cd9849f56eaa;p=thirdparty%2Ffreeradius-server.git initial attempt at statistics handling --- diff --git a/src/lib/util/libfreeradius-util.mk b/src/lib/util/libfreeradius-util.mk index 1b0af87db1d..86ed0cc8f71 100644 --- a/src/lib/util/libfreeradius-util.mk +++ b/src/lib/util/libfreeradius-util.mk @@ -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 index 00000000000..89139ef15be --- /dev/null +++ b/src/lib/util/stats.c @@ -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 + +/** 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 index 00000000000..fb888897784 --- /dev/null +++ b/src/lib/util/stats.h @@ -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 + +#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