rust: Implement FFI interface to metrics crate

This commit is contained in:
Jack Grigg 2020-10-17 00:53:04 +01:00
parent ccb26821df
commit 8482ed6356
5 changed files with 276 additions and 0 deletions

49
Cargo.lock generated
View File

@ -31,6 +31,15 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
@ -531,6 +540,7 @@ dependencies = [
"group",
"jubjub",
"libc",
"metrics",
"rand_core",
"subtle",
"tracing",
@ -566,6 +576,12 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "memoffset"
version = "0.5.6"
@ -575,6 +591,30 @@ dependencies = [
"autocfg",
]
[[package]]
name = "metrics"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58e285601dcfb9f3a8f37a7093b9956a0df730b50848c8ac0117406aff06c851"
dependencies = [
"metrics-macros",
"proc-macro-hack",
]
[[package]]
name = "metrics-macros"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11ac60cd4d3a869fd39d57baf0ed7f79fb677580d8d6655c4330d4f1126bc27b"
dependencies = [
"lazy_static",
"proc-macro-hack",
"proc-macro2",
"quote",
"regex",
"syn",
]
[[package]]
name = "num-bigint"
version = "0.3.2"
@ -649,6 +689,12 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.24"
@ -737,7 +783,10 @@ version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]

View File

@ -37,6 +37,9 @@ zcash_primitives = "0.5"
zcash_proofs = "0.5"
ed25519-zebra = "2.0.0"
# Metrics
metrics = "0.14.2"
# Temporary workaround for https://github.com/myrrlyn/funty/issues/3
funty = "=1.1.0"

View File

@ -0,0 +1,159 @@
// Copyright (c) 2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#ifndef ZCASH_RUST_INCLUDE_RUST_METRICS_H
#define ZCASH_RUST_INCLUDE_RUST_METRICS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct MetricsCallsite;
typedef struct MetricsCallsite MetricsCallsite;
/// Creates a metrics callsite.
///
/// You should usually call one of the helper macros such as `MetricsCounter`
/// instead of calling this directly.
///
/// This MUST ONLY be called to assign a `static MetricsCallsite*`, and all
/// string arguments MUST be static `const char*` constants, and MUST be valid
/// UTF-8.
MetricsCallsite* metrics_callsite(const char* name);
/// Increments a counter.
///
/// Counters represent a single monotonic value, which means the value can only
/// be incremented, not decremented, and always starts out with an initial value
/// of zero.
void metrics_increment_counter(const MetricsCallsite* callsite, uint64_t value);
/// Updates a gauge.
///
/// Gauges represent a single value that can go up or down over time, and always
/// starts out with an initial value of zero.
void metrics_update_gauge(const MetricsCallsite* callsite, double value);
/// Increments a gauge.
///
/// Gauges represent a single value that can go up or down over time, and always
/// starts out with an initial value of zero.
void metrics_increment_gauge(const MetricsCallsite* callsite, double value);
/// Decrements a gauge.
///
/// Gauges represent a single value that can go up or down over time, and always
/// starts out with an initial value of zero.
void metrics_decrement_gauge(const MetricsCallsite* callsite, double value);
/// Records a histogram.
///
/// Histograms measure the distribution of values for a given set of
/// measurements, and start with no initial values.
void metrics_record_histogram(const MetricsCallsite* callsite, double value);
#ifdef __cplusplus
}
#endif
//
// Helper macros
//
#ifdef __cplusplus
// Constructs a metrics callsite.
//
// The 'static constexpr' hack ensures that name is a compile-time constant
// with static storage duration. The output of this macro MUST be stored as a
// static MetricsCallsite*.
#define M_CALLSITE(name) ([&] { \
static constexpr const char* _m_name = name; \
return metrics_callsite(_m_name); \
}())
#else
// Constructs a metrics callsite.
//
// name MUST be a static constant, and the output of this macro MUST be stored
// as a static MetricsCallsite*.
#define M_CALLSITE(name) \
metrics_callsite(name)
#endif
//
// Metrics
//
/// Increments a counter.
///
/// Counters represent a single monotonic value, which means the value can only
/// be incremented, not decremented, and always starts out with an initial value
/// of zero.
///
/// name MUST be a static constant, and MUST be a valid UTF-8 string.
#define MetricsCounter(name, value) \
do { \
static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
metrics_increment_counter(CALLSITE, value); \
} while (0)
/// Increments a counter by one.
///
/// Counters represent a single monotonic value, which means the value can only
/// be incremented, not decremented, and always starts out with an initial value
/// of zero.
///
/// name MUST be a static constant, and MUST be a valid UTF-8 string.
#define MetricsIncrementCounter(name) MetricsCounter(name, 1)
/// Updates a gauge.
///
/// 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 MUST be a valid UTF-8 string.
#define MetricsGauge(name, value) \
do { \
static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
metrics_update_gauge(CALLSITE, value); \
} while (0)
/// Increments a gauge.
///
/// 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 MUST be a valid UTF-8 string.
#define MetricsIncrementGauge(name, value) \
do { \
static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
metrics_increment_gauge(CALLSITE, value); \
} while (0)
/// Decrements a gauge.
///
/// 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 MUST be a valid UTF-8 string.
#define MetricsDecrementGauge(name, value) \
do { \
static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
metrics_decrement_gauge(CALLSITE, value); \
} while (0)
/// Records a histogram.
///
/// Histograms measure the distribution of values for a given set of
/// measurements, and start with no initial values.
///
/// name MUST be a static constant, and MUST be a valid UTF-8 string.
#define MetricsHistogram(name, value) \
do { \
static MetricsCallsite* CALLSITE = M_CALLSITE(name); \
metrics_record_histogram(CALLSITE, value); \
} while (0)
#endif // ZCASH_RUST_INCLUDE_RUST_METRICS_H

View File

@ -0,0 +1,64 @@
use libc::{c_char, c_double};
use metrics::{try_recorder, GaugeValue, Key, KeyData};
use std::ffi::CStr;
pub struct FfiCallsite {
key_data: KeyData,
}
#[no_mangle]
pub extern "C" fn metrics_callsite(name: *const c_char) -> *mut FfiCallsite {
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
Box::into_raw(Box::new(FfiCallsite {
key_data: KeyData::from_name(name),
}))
}
#[no_mangle]
pub extern "C" fn metrics_increment_counter(callsite: *const FfiCallsite, value: u64) {
if let Some(recorder) = try_recorder() {
let callsite = unsafe { callsite.as_ref().unwrap() };
recorder.increment_counter(Key::Borrowed(&callsite.key_data), value);
}
}
#[no_mangle]
pub extern "C" fn metrics_update_gauge(callsite: *const FfiCallsite, value: c_double) {
if let Some(recorder) = try_recorder() {
let callsite = unsafe { callsite.as_ref().unwrap() };
recorder.update_gauge(
Key::Borrowed(&callsite.key_data),
GaugeValue::Absolute(value),
);
}
}
#[no_mangle]
pub extern "C" fn metrics_increment_gauge(callsite: *const FfiCallsite, value: c_double) {
if let Some(recorder) = try_recorder() {
let callsite = unsafe { callsite.as_ref().unwrap() };
recorder.update_gauge(
Key::Borrowed(&callsite.key_data),
GaugeValue::Increment(value),
);
}
}
#[no_mangle]
pub extern "C" fn metrics_decrement_gauge(callsite: *const FfiCallsite, value: c_double) {
if let Some(recorder) = try_recorder() {
let callsite = unsafe { callsite.as_ref().unwrap() };
recorder.update_gauge(
Key::Borrowed(&callsite.key_data),
GaugeValue::Decrement(value),
);
}
}
#[no_mangle]
pub extern "C" fn metrics_record_histogram(callsite: *const FfiCallsite, value: c_double) {
if let Some(recorder) = try_recorder() {
let callsite = unsafe { callsite.as_ref().unwrap() };
recorder.record_histogram(Key::Borrowed(&callsite.key_data), value);
}
}

View File

@ -63,6 +63,7 @@ use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree}
mod blake2b;
mod ed25519;
mod metrics_ffi;
mod tracing_ffi;
#[cfg(test)]