mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 05:03:43 +01:00
lib: New metrics library
Used to provide an interface to create metrics store and update the entries. Related to #40063 Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
bd582583f6
commit
ec731290a5
@ -73,7 +73,8 @@ TOR_UTIL_LIBS = \
|
||||
src/lib/libtor-version.a \
|
||||
src/lib/libtor-llharden.a \
|
||||
src/lib/libtor-intmath.a \
|
||||
src/lib/libtor-ctime.a
|
||||
src/lib/libtor-ctime.a \
|
||||
src/lib/libtor-metrics.a
|
||||
|
||||
# Variants of the above for linking the testing variant of tor (for coverage
|
||||
# and tests)
|
||||
@ -108,7 +109,8 @@ TOR_UTIL_TESTING_LIBS = \
|
||||
src/lib/libtor-version-testing.a \
|
||||
src/lib/libtor-llharden-testing.a \
|
||||
src/lib/libtor-intmath.a \
|
||||
src/lib/libtor-ctime-testing.a
|
||||
src/lib/libtor-ctime-testing.a \
|
||||
src/lib/libtor-metrics-testing.a
|
||||
endif
|
||||
|
||||
# Internal crypto libraries used in Tor
|
||||
|
@ -22,10 +22,11 @@ include src/lib/intmath/include.am
|
||||
include src/lib/llharden/include.am
|
||||
include src/lib/lock/include.am
|
||||
include src/lib/log/include.am
|
||||
include src/lib/malloc/include.am
|
||||
include src/lib/math/include.am
|
||||
include src/lib/memarea/include.am
|
||||
include src/lib/meminfo/include.am
|
||||
include src/lib/malloc/include.am
|
||||
include src/lib/metrics/include.am
|
||||
include src/lib/net/include.am
|
||||
include src/lib/osinfo/include.am
|
||||
include src/lib/process/include.am
|
||||
|
25
src/lib/metrics/include.am
Normal file
25
src/lib/metrics/include.am
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
noinst_LIBRARIES += src/lib/libtor-metrics.a
|
||||
|
||||
if UNITTESTS_ENABLED
|
||||
noinst_LIBRARIES += src/lib/libtor-metrics-testing.a
|
||||
endif
|
||||
|
||||
# ADD_C_FILE: INSERT SOURCES HERE.
|
||||
src_lib_libtor_metrics_a_SOURCES = \
|
||||
src/lib/metrics/metrics_store.c \
|
||||
src/lib/metrics/metrics_store_entry.c \
|
||||
src/lib/metrics/metrics_common.c \
|
||||
src/lib/metrics/prometheus.c
|
||||
|
||||
src_lib_libtor_metrics_testing_a_SOURCES = \
|
||||
$(src_lib_libtor_metrics_a_SOURCES)
|
||||
src_lib_libtor_metrics_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
|
||||
src_lib_libtor_metrics_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
|
||||
|
||||
# ADD_C_FILE: INSERT HEADERS HERE.
|
||||
noinst_HEADERS += \
|
||||
src/lib/metrics/metrics_store.h \
|
||||
src/lib/metrics/metrics_store_entry.h \
|
||||
src/lib/metrics/metrics_common.h \
|
||||
src/lib/metrics/prometheus.h
|
29
src/lib/metrics/metrics_common.c
Normal file
29
src/lib/metrics/metrics_common.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file metrics_common.c
|
||||
* @brief Common code for the metrics library
|
||||
**/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "orconfig.h"
|
||||
|
||||
#include "lib/log/util_bug.h"
|
||||
|
||||
#include "lib/metrics/metrics_common.h"
|
||||
|
||||
/** Return string representation of a metric type. */
|
||||
const char *
|
||||
metrics_type_to_str(const metrics_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case METRICS_TYPE_COUNTER:
|
||||
return "counter";
|
||||
case METRICS_TYPE_GAUGE:
|
||||
return "gauge";
|
||||
default:
|
||||
tor_assert_unreached();
|
||||
}
|
||||
}
|
40
src/lib/metrics/metrics_common.h
Normal file
40
src/lib/metrics/metrics_common.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file metrics_common.h
|
||||
* @brief Header for lib/metrics/metrics_common.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_LIB_METRICS_METRICS_COMMON_H
|
||||
#define TOR_LIB_METRICS_METRICS_COMMON_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
|
||||
/** Format output type. */
|
||||
typedef enum {
|
||||
/** Prometheus data output format. */
|
||||
METRICS_FORMAT_PROMETHEUS = 1,
|
||||
} metrics_format_t;
|
||||
|
||||
/** Metric type. */
|
||||
typedef enum {
|
||||
/* Increment only. */
|
||||
METRICS_TYPE_COUNTER,
|
||||
/* Can go up or down. */
|
||||
METRICS_TYPE_GAUGE,
|
||||
} metrics_type_t;
|
||||
|
||||
/** Metric counter object (METRICS_TYPE_COUNTER). */
|
||||
typedef struct metrics_counter_t {
|
||||
uint64_t value;
|
||||
} metrics_counter_t;
|
||||
|
||||
/** Metric gauge object (METRICS_TYPE_GAUGE). */
|
||||
typedef struct metrics_gauge_t {
|
||||
int64_t value;
|
||||
} metrics_gauge_t;
|
||||
|
||||
const char *metrics_type_to_str(const metrics_type_t type);
|
||||
|
||||
#endif /* !defined(TOR_LIB_METRICS_METRICS_COMMON_H) */
|
140
src/lib/metrics/metrics_store.c
Normal file
140
src/lib/metrics/metrics_store.c
Normal file
@ -0,0 +1,140 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file metrics_store.c
|
||||
* @brief Metrics interface to store them based on specific store type and get
|
||||
* their MetricsPort output.
|
||||
**/
|
||||
|
||||
#define METRICS_STORE_ENTRY_PRIVATE
|
||||
|
||||
#include "orconfig.h"
|
||||
|
||||
#include "lib/container/map.h"
|
||||
#include "lib/log/util_bug.h"
|
||||
#include "lib/malloc/malloc.h"
|
||||
|
||||
#include "lib/metrics/metrics_store.h"
|
||||
#include "lib/metrics/metrics_store_entry.h"
|
||||
|
||||
/* Format Drivers. */
|
||||
#include "lib/metrics/prometheus.h"
|
||||
|
||||
/** A metric store which contains a map of entries. */
|
||||
typedef struct metrics_store_t {
|
||||
/** Indexed by metrics entry name. An entry is a smartlist_t of one or more
|
||||
* metrics_store_entry_t allowing for multiple metrics of the same name.
|
||||
*
|
||||
* The reason we allow multiple entires is because there are cases where one
|
||||
* metrics can be used twice by the same entity but with different labels.
|
||||
* One example is an onion service with multiple ports, the port specific
|
||||
* metrics will have a port value as a label. */
|
||||
strmap_t *entries;
|
||||
} metrics_store_t;
|
||||
|
||||
/** Function pointer to the format function of a specific driver. */
|
||||
typedef void (fmt_driver_fn_t)(const metrics_store_entry_t *, buf_t *);
|
||||
|
||||
/** Helper: Free a single entry in a metrics_store_t taking a void pointer
|
||||
* parameter. */
|
||||
static void
|
||||
metrics_store_free_void(void *p)
|
||||
{
|
||||
smartlist_t *list = p;
|
||||
SMARTLIST_FOREACH(list, metrics_store_entry_t *, entry,
|
||||
metrics_store_entry_free(entry));
|
||||
smartlist_free(list);
|
||||
}
|
||||
|
||||
/** Put the given store output in the buffer data and use the format function
|
||||
* given in fmt to get it for each entry. */
|
||||
static void
|
||||
get_output(const metrics_store_t *store, buf_t *data, fmt_driver_fn_t fmt)
|
||||
{
|
||||
tor_assert(store);
|
||||
tor_assert(data);
|
||||
tor_assert(fmt);
|
||||
|
||||
STRMAP_FOREACH(store->entries, key, const smartlist_t *, entries) {
|
||||
SMARTLIST_FOREACH_BEGIN(entries, const metrics_store_entry_t *, entry) {
|
||||
fmt(entry, data);
|
||||
} SMARTLIST_FOREACH_END(entry);
|
||||
} STRMAP_FOREACH_END;
|
||||
}
|
||||
|
||||
/** Return a newly allocated and initialized store of the given type. */
|
||||
metrics_store_t *
|
||||
metrics_store_new(void)
|
||||
{
|
||||
metrics_store_t *store = tor_malloc_zero(sizeof(*store));
|
||||
|
||||
store->entries = strmap_new();
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
/** Free the given store including all its entries. */
|
||||
void
|
||||
metrics_store_free_(metrics_store_t *store)
|
||||
{
|
||||
if (store == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
strmap_free(store->entries, metrics_store_free_void);
|
||||
tor_free(store);
|
||||
}
|
||||
|
||||
/** Find all metrics entry in the given store identified by name. If not found,
|
||||
* NULL is returned. */
|
||||
smartlist_t *
|
||||
metrics_store_get_all(const metrics_store_t *store, const char *name)
|
||||
{
|
||||
tor_assert(store);
|
||||
tor_assert(name);
|
||||
|
||||
return strmap_get(store->entries, name);
|
||||
}
|
||||
|
||||
/** Add a new metrics entry to the given store and type. The name MUST be the
|
||||
* unique identifier. The help string can be omitted. */
|
||||
metrics_store_entry_t *
|
||||
metrics_store_add(metrics_store_t *store, metrics_type_t type,
|
||||
const char *name, const char *help)
|
||||
{
|
||||
smartlist_t *entries;
|
||||
metrics_store_entry_t *entry;
|
||||
|
||||
tor_assert(store);
|
||||
tor_assert(name);
|
||||
|
||||
entries = metrics_store_get_all(store, name);
|
||||
if (!entries) {
|
||||
entries = smartlist_new();
|
||||
strmap_set(store->entries, name, entries);
|
||||
}
|
||||
entry = metrics_store_entry_new(type, name, help);
|
||||
smartlist_add(entries, entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** Set the output of the given store of the format fmt into the given buffer
|
||||
* data. */
|
||||
void
|
||||
metrics_store_get_output(const metrics_format_t fmt,
|
||||
const metrics_store_t *store, buf_t *data)
|
||||
{
|
||||
tor_assert(store);
|
||||
|
||||
switch (fmt) {
|
||||
case METRICS_FORMAT_PROMETHEUS:
|
||||
get_output(store, data, prometheus_format_store_entry);
|
||||
break;
|
||||
default:
|
||||
// LCOV_EXCL_START
|
||||
tor_assert_unreached();
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
42
src/lib/metrics/metrics_store.h
Normal file
42
src/lib/metrics/metrics_store.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file metrics_store.h
|
||||
* @brief Header for lib/metrics/metrics_store.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_LIB_METRICS_METRICS_STORE_H
|
||||
#define TOR_LIB_METRICS_METRICS_STORE_H
|
||||
|
||||
#include "lib/buf/buffers.h"
|
||||
#include "lib/container/smartlist.h"
|
||||
|
||||
#include "lib/metrics/metrics_common.h"
|
||||
#include "lib/metrics/metrics_store_entry.h"
|
||||
|
||||
/* Stub. */
|
||||
typedef struct metrics_store_t metrics_store_t;
|
||||
|
||||
/* Allocators. */
|
||||
void metrics_store_free_(metrics_store_t *store);
|
||||
#define metrics_store_free(store) \
|
||||
FREE_AND_NULL(metrics_store_t, metrics_store_free_, (store))
|
||||
metrics_store_t *metrics_store_new(void);
|
||||
|
||||
/* Modifiers. */
|
||||
metrics_store_entry_t *metrics_store_add(metrics_store_t *store,
|
||||
metrics_type_t type,
|
||||
const char *name, const char *help);
|
||||
|
||||
/* Accessors. */
|
||||
smartlist_t *metrics_store_get_all(const metrics_store_t *store,
|
||||
const char *name);
|
||||
void metrics_store_get_output(const metrics_format_t fmt,
|
||||
const metrics_store_t *store, buf_t *data);
|
||||
|
||||
#ifdef METRICS_METRICS_STORE_PRIVATE
|
||||
|
||||
#endif /* METRICS_METRICS_STORE_PRIVATE. */
|
||||
|
||||
#endif /* !defined(TOR_LIB_METRICS_METRICS_STORE_H) */
|
129
src/lib/metrics/metrics_store_entry.c
Normal file
129
src/lib/metrics/metrics_store_entry.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file metrics_store_entry.c
|
||||
* @brief Metrics store entry which contains the gathered data.
|
||||
**/
|
||||
|
||||
#define METRICS_STORE_ENTRY_PRIVATE
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "orconfig.h"
|
||||
|
||||
#include "lib/container/smartlist.h"
|
||||
#include "lib/log/util_bug.h"
|
||||
#include "lib/malloc/malloc.h"
|
||||
|
||||
#include "lib/metrics/metrics_store_entry.h"
|
||||
|
||||
/*
|
||||
* Public API.
|
||||
*/
|
||||
|
||||
/** Return newly allocated store entry of type COUNTER. */
|
||||
metrics_store_entry_t *
|
||||
metrics_store_entry_new(const metrics_type_t type, const char *name,
|
||||
const char *help)
|
||||
{
|
||||
metrics_store_entry_t *entry = tor_malloc_zero(sizeof(*entry));
|
||||
|
||||
tor_assert(name);
|
||||
|
||||
entry->type = type;
|
||||
entry->name = tor_strdup(name);
|
||||
entry->labels = smartlist_new();
|
||||
if (help) {
|
||||
entry->help = tor_strdup(help);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** Free a store entry. */
|
||||
void
|
||||
metrics_store_entry_free_(metrics_store_entry_t *entry)
|
||||
{
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
SMARTLIST_FOREACH(entry->labels, char *, l, tor_free(l));
|
||||
smartlist_free(entry->labels);
|
||||
tor_free(entry->name);
|
||||
tor_free(entry->help);
|
||||
tor_free(entry);
|
||||
}
|
||||
|
||||
/** Update a store entry with value. */
|
||||
void
|
||||
metrics_store_entry_update(metrics_store_entry_t *entry, const int64_t value)
|
||||
{
|
||||
tor_assert(entry);
|
||||
|
||||
switch (entry->type) {
|
||||
case METRICS_TYPE_COUNTER:
|
||||
/* Counter can ONLY be positive. */
|
||||
if (BUG(value < 0)) {
|
||||
return;
|
||||
}
|
||||
entry->u.counter.value += value;
|
||||
break;
|
||||
case METRICS_TYPE_GAUGE:
|
||||
/* Gauge can increment or decrement. And can be positive or negative. */
|
||||
entry->u.gauge.value += value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset a store entry that is set its metric data to 0. */
|
||||
void
|
||||
metrics_store_entry_reset(metrics_store_entry_t *entry)
|
||||
{
|
||||
tor_assert(entry);
|
||||
/* Everything back to 0. */
|
||||
memset(&entry->u, 0, sizeof(entry->u));
|
||||
}
|
||||
|
||||
/** Return store entry value. */
|
||||
int64_t
|
||||
metrics_store_entry_get_value(const metrics_store_entry_t *entry)
|
||||
{
|
||||
tor_assert(entry);
|
||||
|
||||
switch (entry->type) {
|
||||
case METRICS_TYPE_COUNTER:
|
||||
if (entry->u.counter.value > INT64_MAX) {
|
||||
return INT64_MAX;
|
||||
}
|
||||
return entry->u.counter.value;
|
||||
case METRICS_TYPE_GAUGE:
|
||||
return entry->u.gauge.value;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
tor_assert_unreached();
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
/** Add a label into the given entry.*/
|
||||
void
|
||||
metrics_store_entry_add_label(metrics_store_entry_t *entry,
|
||||
const char *label)
|
||||
{
|
||||
tor_assert(entry);
|
||||
tor_assert(label);
|
||||
|
||||
smartlist_add(entry->labels, tor_strdup(label));
|
||||
}
|
||||
|
||||
/** Return true iff the given entry has the given label. */
|
||||
bool
|
||||
metrics_store_entry_has_label(const metrics_store_entry_t *entry,
|
||||
const char *label)
|
||||
{
|
||||
tor_assert(entry);
|
||||
tor_assert(label);
|
||||
|
||||
return smartlist_contains_string(entry->labels, label);
|
||||
}
|
68
src/lib/metrics/metrics_store_entry.h
Normal file
68
src/lib/metrics/metrics_store_entry.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file metrics_store_entry.h
|
||||
* @brief Header for lib/metrics/metrics_store_entry.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_LIB_METRICS_METRICS_STORE_ENTRY_H
|
||||
#define TOR_LIB_METRICS_METRICS_STORE_ENTRY_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
|
||||
#include "lib/metrics/metrics_common.h"
|
||||
|
||||
#ifdef METRICS_STORE_ENTRY_PRIVATE
|
||||
|
||||
/** Metrics store entry. They reside in a metrics_store_t object and are
|
||||
* opaque to the outside world. */
|
||||
typedef struct metrics_store_entry_t {
|
||||
/** Type of entry. */
|
||||
metrics_type_t type;
|
||||
|
||||
/** Name. */
|
||||
char *name;
|
||||
|
||||
/** Help comment string. */
|
||||
char *help;
|
||||
|
||||
/** Labels attached to that entry. If NULL, no labels.
|
||||
*
|
||||
* Labels are used to add extra context to a metrics. For example, a label
|
||||
* could be an onion address so the metrics can be differentiate. */
|
||||
smartlist_t *labels;
|
||||
|
||||
/* Actual data. */
|
||||
union {
|
||||
metrics_counter_t counter;
|
||||
metrics_gauge_t gauge;
|
||||
} u;
|
||||
} metrics_store_entry_t;
|
||||
|
||||
#endif /* METRICS_STORE_ENTRY_PRIVATE */
|
||||
|
||||
typedef struct metrics_store_entry_t metrics_store_entry_t;
|
||||
|
||||
/* Allocators. */
|
||||
metrics_store_entry_t *metrics_store_entry_new(const metrics_type_t type,
|
||||
const char *name,
|
||||
const char *help);
|
||||
|
||||
void metrics_store_entry_free_(metrics_store_entry_t *entry);
|
||||
#define metrics_store_entry_free(entry) \
|
||||
FREE_AND_NULL(metrics_store_entry_t, metrics_store_entry_free_, (entry));
|
||||
|
||||
/* Accessors. */
|
||||
int64_t metrics_store_entry_get_value(const metrics_store_entry_t *entry);
|
||||
bool metrics_store_entry_has_label(const metrics_store_entry_t *entry,
|
||||
const char *label);
|
||||
|
||||
/* Modifiers. */
|
||||
void metrics_store_entry_add_label(metrics_store_entry_t *entry,
|
||||
const char *label);
|
||||
void metrics_store_entry_reset(metrics_store_entry_t *entry);
|
||||
void metrics_store_entry_update(metrics_store_entry_t *entry,
|
||||
const int64_t value);
|
||||
|
||||
#endif /* !defined(TOR_LIB_METRICS_METRICS_STORE_ENTRY_H) */
|
56
src/lib/metrics/prometheus.c
Normal file
56
src/lib/metrics/prometheus.c
Normal file
@ -0,0 +1,56 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file prometheus.c
|
||||
* @brief Metrics format driver for Prometheus data model.
|
||||
**/
|
||||
|
||||
#define METRICS_STORE_ENTRY_PRIVATE
|
||||
|
||||
#include "orconfig.h"
|
||||
|
||||
#include "lib/container/smartlist.h"
|
||||
#include "lib/log/util_bug.h"
|
||||
#include "lib/malloc/malloc.h"
|
||||
#include "lib/string/printf.h"
|
||||
|
||||
#include "lib/metrics/prometheus.h"
|
||||
|
||||
/** Return a static buffer containing all the labels properly formatted
|
||||
* for the output as a string.
|
||||
*
|
||||
* Subsequent calls to this invalidates the previous result. */
|
||||
static const char *
|
||||
format_labels(smartlist_t *labels)
|
||||
{
|
||||
static char buf[1024];
|
||||
char *line = NULL;
|
||||
|
||||
if (smartlist_len(labels) == 0) {
|
||||
buf[0] = '\0';
|
||||
goto end;
|
||||
}
|
||||
|
||||
line = smartlist_join_strings(labels, ",", 0, NULL);
|
||||
tor_snprintf(buf, sizeof(buf), "{%s}", line);
|
||||
|
||||
end:
|
||||
tor_free(line);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Format the given entry in to the buffer data. */
|
||||
void
|
||||
prometheus_format_store_entry(const metrics_store_entry_t *entry, buf_t *data)
|
||||
{
|
||||
tor_assert(entry);
|
||||
tor_assert(data);
|
||||
|
||||
buf_add_printf(data, "# HELP %s %s\n", entry->name, entry->help);
|
||||
buf_add_printf(data, "# TYPE %s %s\n", entry->name,
|
||||
metrics_type_to_str(entry->type));
|
||||
buf_add_printf(data, "%s%s %" PRIi64 "\n", entry->name,
|
||||
format_labels(entry->labels),
|
||||
metrics_store_entry_get_value(entry));
|
||||
}
|
18
src/lib/metrics/prometheus.h
Normal file
18
src/lib/metrics/prometheus.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* Copyright (c) 2020, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file prometheus.h
|
||||
* @brief Header for feature/metrics/prometheus.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_LIB_METRICS_PROMETHEUS_H
|
||||
#define TOR_LIB_METRICS_PROMETHEUS_H
|
||||
|
||||
#include "lib/buf/buffers.h"
|
||||
#include "lib/metrics/metrics_store_entry.h"
|
||||
|
||||
void prometheus_format_store_entry(const metrics_store_entry_t *entry,
|
||||
buf_t *data);
|
||||
|
||||
#endif /* !defined(TOR_LIB_METRICS_PROMETHEUS_H) */
|
Loading…
Reference in New Issue
Block a user