LCOV - code coverage report
Current view: top level - lib/metrics - metrics_store.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 52 53 98.1 %
Date: 2021-11-24 03:28:48 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2020-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * @file metrics_store.c
       6             :  * @brief Metrics interface to store them based on specific store type and get
       7             :  *        their MetricsPort output.
       8             :  **/
       9             : 
      10             : #define METRICS_STORE_ENTRY_PRIVATE
      11             : 
      12             : #include "orconfig.h"
      13             : 
      14             : #include "lib/container/map.h"
      15             : #include "lib/log/util_bug.h"
      16             : #include "lib/malloc/malloc.h"
      17             : 
      18             : #include "lib/metrics/metrics_store.h"
      19             : #include "lib/metrics/metrics_store_entry.h"
      20             : 
      21             : /* Format Drivers. */
      22             : #include "lib/metrics/prometheus.h"
      23             : 
      24             : /** A metric store which contains a map of entries. */
      25             : struct metrics_store_t {
      26             :   /** Indexed by metrics entry name. An entry is a smartlist_t of one or more
      27             :    * metrics_store_entry_t allowing for multiple metrics of the same name.
      28             :    *
      29             :    * The reason we allow multiple entries is because there are cases where one
      30             :    * metrics can be used twice by the same entity but with different labels.
      31             :    * One example is an onion service with multiple ports, the port specific
      32             :    * metrics will have a port value as a label. */
      33             :   strmap_t *entries;
      34             : };
      35             : 
      36             : /** Function pointer to the format function of a specific driver. */
      37             : typedef void (fmt_driver_fn_t)(const metrics_store_entry_t *, buf_t *,
      38             :                                bool no_comment);
      39             : 
      40             : /** Helper: Free a single entry in a metrics_store_t taking a void pointer
      41             :  * parameter. */
      42             : static void
      43         248 : metrics_store_free_void(void *p)
      44             : {
      45         248 :   smartlist_t *list = p;
      46         497 :   SMARTLIST_FOREACH(list, metrics_store_entry_t *, entry,
      47             :                     metrics_store_entry_free(entry));
      48         248 :   smartlist_free(list);
      49         248 : }
      50             : 
      51             : #include <stdio.h>
      52             : 
      53             : /** Put the given store output in the buffer data and use the format function
      54             :  * given in fmt to get it for each entry. */
      55             : static void
      56           2 : get_output(const metrics_store_t *store, buf_t *data, fmt_driver_fn_t fmt)
      57             : {
      58           2 :   tor_assert(store);
      59           2 :   tor_assert(data);
      60           2 :   tor_assert(fmt);
      61             : 
      62          10 :   STRMAP_FOREACH(store->entries, key, const smartlist_t *, entries) {
      63             :     /* Indicate that we've formatted the coment already for the entries. */
      64           8 :     bool comment_formatted = false;
      65          63 :     SMARTLIST_FOREACH_BEGIN(entries, const metrics_store_entry_t *, entry) {
      66          55 :       fmt(entry, data, comment_formatted);
      67          55 :       comment_formatted = true;
      68          55 :     } SMARTLIST_FOREACH_END(entry);
      69           2 :   } STRMAP_FOREACH_END;
      70           2 : }
      71             : 
      72             : /** Return a newly allocated and initialized store of the given type. */
      73             : metrics_store_t *
      74         288 : metrics_store_new(void)
      75             : {
      76         288 :   metrics_store_t *store = tor_malloc_zero(sizeof(*store));
      77             : 
      78         288 :   store->entries = strmap_new();
      79             : 
      80         288 :   return store;
      81             : }
      82             : 
      83             : /** Free the given store including all its entries. */
      84             : void
      85         315 : metrics_store_free_(metrics_store_t *store)
      86             : {
      87         315 :   if (store == NULL) {
      88             :     return;
      89             :   }
      90             : 
      91         278 :   strmap_free(store->entries, metrics_store_free_void);
      92         278 :   tor_free(store);
      93             : }
      94             : 
      95             : /** Find all metrics entry in the given store identified by name. If not found,
      96             :  * NULL is returned. */
      97             : smartlist_t *
      98         317 : metrics_store_get_all(const metrics_store_t *store, const char *name)
      99             : {
     100         317 :   tor_assert(store);
     101         317 :   tor_assert(name);
     102             : 
     103         317 :   return strmap_get(store->entries, name);
     104             : }
     105             : 
     106             : /** Add a new metrics entry to the given store and type. The name MUST be the
     107             :  * unique identifier. The help string can be omitted. */
     108             : metrics_store_entry_t *
     109         309 : metrics_store_add(metrics_store_t *store, metrics_type_t type,
     110             :                   const char *name, const char *help)
     111             : {
     112         309 :   smartlist_t *entries;
     113         309 :   metrics_store_entry_t *entry;
     114             : 
     115         309 :   tor_assert(store);
     116         309 :   tor_assert(name);
     117             : 
     118         309 :   entries = metrics_store_get_all(store, name);
     119         309 :   if (!entries) {
     120         261 :     entries = smartlist_new();
     121         261 :     strmap_set(store->entries, name, entries);
     122             :   }
     123         309 :   entry = metrics_store_entry_new(type, name, help);
     124         309 :   smartlist_add(entries, entry);
     125             : 
     126         309 :   return entry;
     127             : }
     128             : 
     129             : /** Set the output of the given store of the format fmt into the given buffer
     130             :  * data. */
     131             : void
     132           2 : metrics_store_get_output(const metrics_format_t fmt,
     133             :                          const metrics_store_t *store, buf_t *data)
     134             : {
     135           2 :   tor_assert(store);
     136             : 
     137           2 :   switch (fmt) {
     138           2 :   case METRICS_FORMAT_PROMETHEUS:
     139           2 :     get_output(store, data, prometheus_format_store_entry);
     140           2 :     break;
     141           0 :   default:
     142             :     // LCOV_EXCL_START
     143             :     tor_assert_unreached();
     144             :     // LCOV_EXCL_STOP
     145             :   }
     146           2 : }
     147             : 
     148             : /** Reset a store as in free its content. */
     149             : void
     150           1 : metrics_store_reset(metrics_store_t *store)
     151             : {
     152           1 :   if (store == NULL) {
     153             :     return;
     154             :   }
     155           1 :   strmap_free(store->entries, metrics_store_free_void);
     156           1 :   store->entries = strmap_new();
     157             : }

Generated by: LCOV version 1.14