metrics: Enable gauges with fully-static labels
This commit is contained in:
parent
958ffeafd3
commit
78b83fd6e9
|
@ -34,13 +34,20 @@ typedef struct MetricsKey MetricsKey;
|
||||||
|
|
||||||
/// Creates a metrics callsite.
|
/// Creates a metrics callsite.
|
||||||
///
|
///
|
||||||
|
/// This API supports labels that MUST have static values. For non-static label
|
||||||
|
/// values, use `metrics_key`.
|
||||||
|
///
|
||||||
/// You should usually call one of the helper macros such as `MetricsCounter`
|
/// You should usually call one of the helper macros such as `MetricsCounter`
|
||||||
/// instead of calling this directly.
|
/// instead of calling this directly.
|
||||||
///
|
///
|
||||||
/// This MUST ONLY be called to assign a `static MetricsCallsite*`, and all
|
/// This MUST ONLY be called to assign a `static MetricsCallsite*`, and all
|
||||||
/// string arguments MUST be static `const char*` constants, and MUST be valid
|
/// string arguments MUST be static `const char*` constants, and MUST be valid
|
||||||
/// UTF-8.
|
/// UTF-8.
|
||||||
MetricsCallsite* metrics_callsite(const char* name);
|
MetricsCallsite* metrics_callsite(
|
||||||
|
const char* name,
|
||||||
|
const char* const* label_names,
|
||||||
|
const char* const* label_values,
|
||||||
|
size_t labels_len);
|
||||||
|
|
||||||
/// Creates a metrics key.
|
/// Creates a metrics key.
|
||||||
///
|
///
|
||||||
|
@ -133,20 +140,26 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
// Constructs a metrics callsite.
|
// Constructs a metrics callsite.
|
||||||
//
|
//
|
||||||
// The 'static constexpr' hack ensures that name is a compile-time constant
|
// The 'static constexpr' hack ensures that all arguments are compile-time
|
||||||
// with static storage duration. The output of this macro MUST be stored as a
|
// constants with static storage duration. The output of this macro MUST be
|
||||||
// static MetricsCallsite*.
|
// stored as a static MetricsCallsite*.
|
||||||
#define M_CALLSITE(name) ([&] { \
|
#define M_CALLSITE(name, label_names, label_values) ([&] { \
|
||||||
static constexpr const char* _m_name = name; \
|
static constexpr const char* _m_name = name; \
|
||||||
return metrics_callsite(_m_name); \
|
static constexpr const char* const* _m_label_names = \
|
||||||
|
label_names; \
|
||||||
|
static constexpr const char* const* _m_label_values = \
|
||||||
|
label_values; \
|
||||||
|
return metrics_callsite( \
|
||||||
|
_m_name, _m_label_names, _m_label_values, \
|
||||||
|
T_ARRLEN(label_names)); \
|
||||||
}())
|
}())
|
||||||
#else
|
#else
|
||||||
// Constructs a metrics callsite.
|
// Constructs a metrics callsite.
|
||||||
//
|
//
|
||||||
// name MUST be a static constant, and the output of this macro MUST be stored
|
// All arguments MUST be static constants, and the output of this macro MUST be
|
||||||
// as a static MetricsCallsite*.
|
// stored as a static MetricsCallsite*.
|
||||||
#define M_CALLSITE(name) \
|
#define M_CALLSITE(name, label_names, label_values) \
|
||||||
metrics_callsite(name)
|
metrics_callsite(name, label_names, label_values, T_ARRLEN(label_names))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constructs a metrics key.
|
// Constructs a metrics key.
|
||||||
|
@ -171,7 +184,9 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
#define MetricsCounter(name, value, ...) \
|
#define MetricsCounter(name, value, ...) \
|
||||||
do { \
|
do { \
|
||||||
IFE(__VA_ARGS__) \
|
IFE(__VA_ARGS__) \
|
||||||
(static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
metrics_static_increment_counter(CALLSITE, value);) \
|
metrics_static_increment_counter(CALLSITE, value);) \
|
||||||
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
@ -200,7 +215,9 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
#define MetricsGauge(name, value, ...) \
|
#define MetricsGauge(name, value, ...) \
|
||||||
do { \
|
do { \
|
||||||
IFE(__VA_ARGS__) \
|
IFE(__VA_ARGS__) \
|
||||||
(static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
metrics_static_update_gauge(CALLSITE, value);) \
|
metrics_static_update_gauge(CALLSITE, value);) \
|
||||||
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
@ -211,6 +228,23 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
metrics_update_gauge(KEY, value);) \
|
metrics_update_gauge(KEY, value);) \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/// Updates a gauge with optional static labels.
|
||||||
|
///
|
||||||
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
/// starts out with an initial value of zero.
|
||||||
|
///
|
||||||
|
/// name MUST be a static constant, and all strings MUST be valid UTF-8.
|
||||||
|
#define MetricsStaticGauge(name, value, ...) \
|
||||||
|
do { \
|
||||||
|
static constexpr const char* M_LABELS[] = \
|
||||||
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
static constexpr const char* M_VALUES[] = \
|
||||||
|
{T_FIELD_VALUES(__VA_ARGS__)}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, M_LABELS, M_VALUES); \
|
||||||
|
metrics_static_update_gauge(CALLSITE, value); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/// Increments a gauge.
|
/// Increments a gauge.
|
||||||
///
|
///
|
||||||
/// Gauges represent a single value that can go up or down over time, and always
|
/// Gauges represent a single value that can go up or down over time, and always
|
||||||
|
@ -220,7 +254,9 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
#define MetricsIncrementGauge(name, value, ...) \
|
#define MetricsIncrementGauge(name, value, ...) \
|
||||||
do { \
|
do { \
|
||||||
IFE(__VA_ARGS__) \
|
IFE(__VA_ARGS__) \
|
||||||
(static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
metrics_static_increment_gauge(CALLSITE, value);) \
|
metrics_static_increment_gauge(CALLSITE, value);) \
|
||||||
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
@ -240,7 +276,9 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
#define MetricsDecrementGauge(name, value, ...) \
|
#define MetricsDecrementGauge(name, value, ...) \
|
||||||
do { \
|
do { \
|
||||||
IFE(__VA_ARGS__) \
|
IFE(__VA_ARGS__) \
|
||||||
(static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
metrics_static_decrement_gauge(CALLSITE, value);) \
|
metrics_static_decrement_gauge(CALLSITE, value);) \
|
||||||
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
@ -260,7 +298,9 @@ void metrics_record_histogram(MetricsKey* callsite, double value);
|
||||||
#define MetricsHistogram(name, value, ...) \
|
#define MetricsHistogram(name, value, ...) \
|
||||||
do { \
|
do { \
|
||||||
IFE(__VA_ARGS__) \
|
IFE(__VA_ARGS__) \
|
||||||
(static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
|
(static constexpr const char* const EMPTY[] = {}; \
|
||||||
|
static MetricsCallsite* CALLSITE = \
|
||||||
|
M_CALLSITE(name, EMPTY, EMPTY); \
|
||||||
metrics_static_record_histogram(CALLSITE, value);) \
|
metrics_static_record_histogram(CALLSITE, value);) \
|
||||||
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
IFN(__VA_ARGS__)(const char* M_LABELS[] = \
|
||||||
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
{T_FIELD_NAMES(__VA_ARGS__)}; \
|
||||||
|
|
|
@ -72,10 +72,33 @@ pub struct FfiCallsite {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn metrics_callsite(name: *const c_char) -> *mut FfiCallsite {
|
pub extern "C" fn metrics_callsite(
|
||||||
|
name: *const c_char,
|
||||||
|
label_names: *const *const c_char,
|
||||||
|
label_values: *const *const c_char,
|
||||||
|
labels_len: usize,
|
||||||
|
) -> *mut FfiCallsite {
|
||||||
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
|
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
|
||||||
|
let labels = unsafe { slice::from_raw_parts(label_names, labels_len) };
|
||||||
|
let values = unsafe { slice::from_raw_parts(label_values, labels_len) };
|
||||||
|
|
||||||
|
let stringify = |s: &[_]| {
|
||||||
|
s.iter()
|
||||||
|
.map(|&p| unsafe { CStr::from_ptr(p) })
|
||||||
|
.map(|cs| cs.to_string_lossy().into_owned())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
let labels = stringify(labels);
|
||||||
|
let values = stringify(values);
|
||||||
|
|
||||||
|
let labels: Vec<_> = labels
|
||||||
|
.into_iter()
|
||||||
|
.zip(values.into_iter())
|
||||||
|
.map(|(name, value)| Label::new(name, value))
|
||||||
|
.collect();
|
||||||
|
|
||||||
Box::into_raw(Box::new(FfiCallsite {
|
Box::into_raw(Box::new(FfiCallsite {
|
||||||
key_data: KeyData::from_name(name),
|
key_data: KeyData::from_parts(name, labels),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue