Use lazy_init! macro to initialize all metrics at start up time

This translate the previous lazy_static::lazy_static! blocks of
metrics into lazy_init! blocks, which creates an initialization
function.  The initialization function guarantees all metrics are
created at start up time.

Where possible, the metric init function is called from within the
module where the metrics are defined.  Most modules have a handy
VeryImportantStruct::new() function near the top for this purpose.

The only metrics that break this pattern reside in the logger module.
For these metrics kbupd::logger::init_metrics() is called from the
main application module for both frontends and replicas.
This commit is contained in:
Curt Brune 2020-12-05 15:00:21 -08:00
parent 041b5bdfc7
commit 903f1e62cd
10 changed files with 94 additions and 69 deletions

1
service/Cargo.lock generated
View File

@ -666,6 +666,7 @@ dependencies = [
"kbupd_api",
"kbupd_client",
"kbupd_config",
"kbupd_macro",
"kbupd_util",
"kbuptlsd",
"lazy_static 1.4.0",

View File

@ -1,5 +1,5 @@
[workspace]
members = ["kbupd", "kbupd_api", "kbupd_api_client", "kbupd_client", "kbupd_config", "kbuptlsd", "rustunnel"]
members = ["kbupd", "kbupd_api", "kbupd_api_client", "kbupd_client", "kbupd_config", "kbupd_macro", "kbuptlsd", "rustunnel"]
[patch.crates-io]
openssl = { rev = "ea6761d5e7b63b415b7fda6ba5c5026f4218bcd0", git = "https://github.com/signalapp/rust-openssl.git" }

View File

@ -22,6 +22,7 @@ ias_client = { git = "https://github.com/signalapp/sgx_common.git", rev =
kbupd_api = { path = "../kbupd_api" }
kbupd_client = { path = "../kbupd_client" }
kbupd_config = { path = "../kbupd_config", default-features = false, features = [] }
kbupd_macro = { path = "../kbupd_macro" }
kbupd_util = { git = "https://github.com/signalapp/sgx_common.git", rev = "580489343a37517d96451a5c0950d462d3e86a3b" }
kbuptlsd = { path = "../kbuptlsd", features = ["hyper"] }
lazy_static = "1.3"

View File

@ -15,6 +15,7 @@ use http::header::HeaderValue;
use http::request;
use hyper::{Body, Chunk, Method, Request, Response, StatusCode};
use kbupd_api::entities::*;
use kbupd_macro::lazy_init;
use serde::{Deserialize, Serialize};
use try_future::TryFuture;
@ -44,17 +45,19 @@ pub struct SignalApiRateLimiters {
pub backup: actor::Sender<RateLimiter>,
}
lazy_static::lazy_static! {
static ref AUTHENTICATION_FAILED_METER: Meter = METRICS.metric(&metric_name!("authentication", "failed"));
static ref AUTHENTICATION_SUCCEEDED_METER: Meter = METRICS.metric(&metric_name!("authentication", "succeeded"));
static ref HTTP_OK_METER: Meter = METRICS.metric(&metric_name!("http_ok"));
static ref HTTP_4XX_METER: Meter = METRICS.metric(&metric_name!("http_4xx"));
static ref HTTP_5XX_METER: Meter = METRICS.metric(&metric_name!("http_5xx"));
static ref HANDLER_ERROR_METER: Meter = METRICS.metric(&metric_name!("handler_error"));
static ref GET_TOKEN_TIMER: Timer = METRICS.metric(&metric_name!("get_token"));
static ref GET_ATTESTATION_TIMER: Timer = METRICS.metric(&metric_name!("get_attestation"));
static ref PUT_BACKUP_REQUEST_TIMER: Timer = METRICS.metric(&metric_name!("put_backup_request"));
static ref DELETE_BACKUPS_TIMER: Timer = METRICS.metric(&metric_name!("delete_backups"));
lazy_init! {
fn init_metrics() {
static ref AUTHENTICATION_FAILED_METER: Meter = METRICS.metric(&metric_name!("authentication", "failed"));
static ref AUTHENTICATION_SUCCEEDED_METER: Meter = METRICS.metric(&metric_name!("authentication", "succeeded"));
static ref HTTP_OK_METER: Meter = METRICS.metric(&metric_name!("http_ok"));
static ref HTTP_4XX_METER: Meter = METRICS.metric(&metric_name!("http_4xx"));
static ref HTTP_5XX_METER: Meter = METRICS.metric(&metric_name!("http_5xx"));
static ref HANDLER_ERROR_METER: Meter = METRICS.metric(&metric_name!("handler_error"));
static ref GET_TOKEN_TIMER: Timer = METRICS.metric(&metric_name!("get_token"));
static ref GET_ATTESTATION_TIMER: Timer = METRICS.metric(&metric_name!("get_attestation"));
static ref PUT_BACKUP_REQUEST_TIMER: Timer = METRICS.metric(&metric_name!("put_backup_request"));
static ref DELETE_BACKUPS_TIMER: Timer = METRICS.metric(&metric_name!("delete_backups"));
}
}
impl<BackupManagerTy> SignalApiService<BackupManagerTy>
@ -67,6 +70,8 @@ where BackupManagerTy: BackupManager<User = SignalUser> + Clone + Send + 'static
rate_limiters: SignalApiRateLimiters,
) -> Self
{
init_metrics();
let mut router = route_recognizer::Router::new();
router.add(
@ -287,7 +292,7 @@ where BackupManagerTy: BackupManager<User = SignalUser> + Clone + Send + 'static
let mut response = Response::default();
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
Ok(Err(response))
},
}
}
});
@ -616,14 +621,10 @@ mod test {
Box::new(call_result.then(|result: Result<_, futures::Canceled>| result.unwrap()))
}
fn delete_backups(
&self,
user: &Self::User) -> Box<dyn Future<Item=(), Error=EnclaveTransactionError> + Send>
{
fn delete_backups(&self, user: &Self::User) -> Box<dyn Future<Item = (), Error = EnclaveTransactionError> + Send> {
let user = user.clone();
let call_result = self.sync_call(move |backup_manager: &mut BackupManagerMock<SignalUser>| {
Ok(backup_manager.delete_backups(&user))
});
let call_result =
self.sync_call(move |backup_manager: &mut BackupManagerMock<SignalUser>| Ok(backup_manager.delete_backups(&user)));
Box::new(call_result.then(|result: Result<_, futures::Canceled>| result.unwrap()))
}
}
@ -1349,9 +1350,7 @@ mod test {
#[test]
fn test_delete_backups_request_no_authorization() {
let mut test = SignalApiServiceTest::builder().build();
let request = Request::delete("http://invalid/v1/backup")
.body(Body::empty())
.unwrap();
let request = Request::delete("http://invalid/v1/backup").body(Body::empty()).unwrap();
let client = test.client();
let response = test.runtime.block_on(client.request(request)).unwrap();
@ -1414,11 +1413,8 @@ mod test {
fn test_delete_backups_request_valid() {
let mut test = SignalApiServiceTest::builder().build();
test.scenario.expect(
test.backup_manager
.delete_backups(ANY)
.and_return(Box::new(Ok(()).into_future())),
);
test.scenario
.expect(test.backup_manager.delete_backups(ANY).and_return(Box::new(Ok(()).into_future())));
let request = Request::delete("http://invalid/v1/backup")
.header(

View File

@ -11,16 +11,19 @@ use futures::future;
use futures::prelude::*;
use futures::sync::oneshot;
use ias_client::*;
use kbupd_macro::lazy_init;
use crate::intel_client::*;
use crate::metrics::*;
use crate::protobufs::kbupd::*;
use crate::*;
lazy_static::lazy_static! {
static ref GET_ATTESTATION_ATTEMPT_METER: Meter = METRICS.metric(&metric_name!("get_attestation", "attempts"));
static ref GET_ATTESTATION_OK_METER: Meter = METRICS.metric(&metric_name!("get_attestation", "ok"));
static ref GET_ATTESTATION_ERROR_METER: Meter = METRICS.metric(&metric_name!("get_attestation", "error"));
lazy_init! {
fn init_metrics() {
static ref GET_ATTESTATION_ATTEMPT_METER: Meter = METRICS.metric(&metric_name!("get_attestation", "attempts"));
static ref GET_ATTESTATION_OK_METER: Meter = METRICS.metric(&metric_name!("get_attestation", "ok"));
static ref GET_ATTESTATION_ERROR_METER: Meter = METRICS.metric(&metric_name!("get_attestation", "error"));
}
}
pub struct AttestationManager {
@ -31,6 +34,8 @@ pub struct AttestationManager {
impl AttestationManager {
pub fn new(enclave_tx: EnclaveManagerSender, intel_client: Option<KbupdIasClient>) -> Self {
init_metrics();
Self {
enclave_tx,
intel_client,

View File

@ -18,6 +18,7 @@ use futures::sync::oneshot;
use ias_client::*;
use kbupd_api::entities::BackupId;
use kbupd_api::entities::*;
use kbupd_macro::lazy_init;
use sgx_sdk_ffi::*;
use crate::metrics::*;
@ -61,28 +62,30 @@ struct PendingRequestMap<V> {
requests: HashMap<u64, V>,
}
lazy_static::lazy_static! {
static ref MEMORY_USED_GAUGE: Gauge = METRICS.metric(&metric_name!("memory", "used"));
static ref MEMORY_CHUNKS_GAUGE: Gauge = METRICS.metric(&metric_name!("memory", "chunks"));
static ref REPLICA_MIN_ATTESTATION_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "attestation", "min_timestamp"));
static ref REPLICA_TERM_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "term"));
static ref REPLICA_LOG_PREV_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "log", "prev"));
static ref REPLICA_LOG_APPLIED_METER: Meter = METRICS.metric(&metric_name!("replica", "log", "applied"));
static ref REPLICA_LOG_COMMITTED_METER: Meter = METRICS.metric(&metric_name!("replica", "log", "committed"));
static ref REPLICA_LOG_APPENDED_METER: Meter = METRICS.metric(&metric_name!("replica", "log", "appended"));
lazy_init! {
fn init_metrics() {
static ref MEMORY_USED_GAUGE: Gauge = METRICS.metric(&metric_name!("memory", "used"));
static ref MEMORY_CHUNKS_GAUGE: Gauge = METRICS.metric(&metric_name!("memory", "chunks"));
static ref REPLICA_MIN_ATTESTATION_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "attestation", "min_timestamp"));
static ref REPLICA_TERM_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "term"));
static ref REPLICA_LOG_PREV_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "log", "prev"));
static ref REPLICA_LOG_APPLIED_METER: Meter = METRICS.metric(&metric_name!("replica", "log", "applied"));
static ref REPLICA_LOG_COMMITTED_METER: Meter = METRICS.metric(&metric_name!("replica", "log", "committed"));
static ref REPLICA_LOG_APPENDED_METER: Meter = METRICS.metric(&metric_name!("replica", "log", "appended"));
static ref REPLICA_BACKUPS_COUNT_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "backups", "count"));
static ref REPLICA_BACKUPS_CREATE_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "create"));
static ref REPLICA_BACKUPS_BACKUP_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "backup"));
static ref REPLICA_BACKUPS_RESTORE_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "restore"));
static ref REPLICA_BACKUPS_DELETE_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "delete"));
static ref REPLICA_BACKUPS_XFER_IN_PROGRESS_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "xfer_in_progress"));
static ref REPLICA_BACKUPS_WRONG_PARTITION_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "wrong_partition"));
static ref REPLICA_BACKUPS_INVALID_REQUEST_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "invalid_request"));
static ref REPLICA_BACKUPS_INTERNAL_ERROR_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "internal_error"));
static ref REPLICA_BACKUPS_COUNT_GAUGE: Gauge = METRICS.metric(&metric_name!("replica", "backups", "count"));
static ref REPLICA_BACKUPS_CREATE_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "create"));
static ref REPLICA_BACKUPS_BACKUP_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "backup"));
static ref REPLICA_BACKUPS_RESTORE_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "restore"));
static ref REPLICA_BACKUPS_DELETE_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "delete"));
static ref REPLICA_BACKUPS_XFER_IN_PROGRESS_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "xfer_in_progress"));
static ref REPLICA_BACKUPS_WRONG_PARTITION_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "wrong_partition"));
static ref REPLICA_BACKUPS_INVALID_REQUEST_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "invalid_request"));
static ref REPLICA_BACKUPS_INTERNAL_ERROR_METER: Meter = METRICS.metric(&metric_name!("replica", "backups", "internal_error"));
static ref FRONTEND_REQUESTS_INFLIGHT_GAUGE: Gauge = METRICS.metric(&metric_name!("frontend", "requests", "inflight"));
static ref FRONTEND_REQUESTS_UNSENT_GAUGE: Gauge = METRICS.metric(&metric_name!("frontend", "requests", "unsent"));
static ref FRONTEND_REQUESTS_INFLIGHT_GAUGE: Gauge = METRICS.metric(&metric_name!("frontend", "requests", "inflight"));
static ref FRONTEND_REQUESTS_UNSENT_GAUGE: Gauge = METRICS.metric(&metric_name!("frontend", "requests", "unsent"));
}
}
//
@ -99,6 +102,8 @@ impl Enclave {
attestation_tx: actor::Sender<AttestationManager>,
) -> Result<Self, EnclaveError>
{
init_metrics();
let enclave_id = create_enclave(enclave_path, enclave_debug).sgxsd_context("sgx_create_enclave")?;
Ok(Self {

View File

@ -9,6 +9,7 @@ use std::time::{Duration, Instant};
use futures::prelude::*;
use ias_client::*;
use kbupd_macro::lazy_init;
use tokio::timer;
use try_future::TryFuture;
@ -30,13 +31,16 @@ enum RefreshAllError {
StaleRevocationList,
}
lazy_static::lazy_static! {
static ref GET_SIGNED_QUOTE_OK_METER: Meter = METRICS.metric(&metric_name!("get_signed_quote", "ok"));
static ref GET_SIGNED_QUOTE_ERROR_METER: Meter = METRICS.metric(&metric_name!("get_signed_quote", "error"));
lazy_init! {
fn init_metrics() {
static ref GET_SIGNED_QUOTE_OK_METER: Meter = METRICS.metric(&metric_name!("get_signed_quote", "ok"));
static ref GET_SIGNED_QUOTE_ERROR_METER: Meter = METRICS.metric(&metric_name!("get_signed_quote", "error"));
}
}
impl HandshakeManager {
pub fn new(enclave_tx: EnclaveManagerSender, intel_client: KbupdIasClient, accept_group_out_of_date: bool) -> Self {
init_metrics();
Self {
enclave_tx,
intel_client,

View File

@ -10,6 +10,7 @@ use std::fmt;
use std::io::{BufWriter, Stderr, Write};
use chrono::format::StrftimeItems;
use kbupd_macro::lazy_init;
use slog::{Drain, KV};
use slog_async::OverflowStrategy;
@ -49,10 +50,12 @@ const EMPTY_SLOG_LOCATION: slog::RecordLocation = slog::RecordLocation {
module: "",
};
lazy_static::lazy_static! {
static ref ERROR_METER: Meter = METRICS.metric(&metric_name!("error"));
static ref WARN_METER: Meter = METRICS.metric(&metric_name!("warn"));
static ref INFO_METER: Meter = METRICS.metric(&metric_name!("info"));
lazy_init! {
pub fn init_metrics() {
static ref ERROR_METER: Meter = METRICS.metric(&metric_name!("error"));
static ref WARN_METER: Meter = METRICS.metric(&metric_name!("warn"));
static ref INFO_METER: Meter = METRICS.metric(&metric_name!("info"));
}
}
impl Logger {

View File

@ -43,6 +43,10 @@ fn main() {
std::process::exit(1);
}
fn init_common_metrics() {
kbupd::logger::init_metrics();
}
#[rustfmt::skip]
fn run(arguments: clap::ArgMatches<'static>) -> Result<(), failure::Error> {
let (subcommand_name, subcommand_arguments) = arguments.subcommand();
@ -67,6 +71,8 @@ fn run(arguments: clap::ArgMatches<'static>) -> Result<(), failure::Error> {
let config_file =
fs::File::open(&config_file_path).with_context(|_| format_err!("error opening config file {}", config_file_path.display()))?;
init_common_metrics();
let service = match subcommand_name {
"replica" => {
let mut config: ReplicaConfig = serde_yaml::from_reader(config_file)

View File

@ -13,6 +13,7 @@ use std::time::Duration;
use futures::prelude::*;
use futures::sync::oneshot;
use kbupd_macro::lazy_init;
use tokio::prelude::*;
use super::connection::*;
@ -37,16 +38,18 @@ pub struct PeerManager {
tls_client: TlsClient,
}
lazy_static::lazy_static! {
static ref MESSAGES_SENT_COUNT_METER: Meter = METRICS.metric(&metric_name!("messages", "sent", "count"));
static ref MESSAGES_SENT_BYTES_METER: Meter = METRICS.metric(&metric_name!("messages", "sent", "bytes"));
pub static ref MESSAGES_RECEIVED_COUNT_METER: Meter = METRICS.metric(&metric_name!("messages", "received", "count"));
pub static ref MESSAGES_RECEIVED_BYTES_METER: Meter = METRICS.metric(&metric_name!("messages", "received", "bytes"));
pub static ref MESSAGES_PENDING_COUNT_COUNTER: Counter = METRICS.metric(&metric_name!("messages", "pending", "count"));
pub static ref MESSAGES_PENDING_BYTES_COUNTER: Counter = METRICS.metric(&metric_name!("messages", "pending", "bytes"));
pub static ref PEERS_CONNECTED_COUNTER: Counter = METRICS.metric(&metric_name!("peers", "connected"));
pub static ref PEERS_CONNECTING_COUNTER: Counter = METRICS.metric(&metric_name!("peers", "connecting"));
pub static ref PEERS_DISCONNECTED_COUNTER: Counter = METRICS.metric(&metric_name!("peers", "disconnected"));
lazy_init! {
fn init_metrics() {
static ref MESSAGES_SENT_COUNT_METER: Meter = METRICS.metric(&metric_name!("messages", "sent", "count"));
static ref MESSAGES_SENT_BYTES_METER: Meter = METRICS.metric(&metric_name!("messages", "sent", "bytes"));
pub static ref MESSAGES_RECEIVED_COUNT_METER: Meter = METRICS.metric(&metric_name!("messages", "received", "count"));
pub static ref MESSAGES_RECEIVED_BYTES_METER: Meter = METRICS.metric(&metric_name!("messages", "received", "bytes"));
pub static ref MESSAGES_PENDING_COUNT_COUNTER: Counter = METRICS.metric(&metric_name!("messages", "pending", "count"));
pub static ref MESSAGES_PENDING_BYTES_COUNTER: Counter = METRICS.metric(&metric_name!("messages", "pending", "bytes"));
pub static ref PEERS_CONNECTED_COUNTER: Counter = METRICS.metric(&metric_name!("peers", "connected"));
pub static ref PEERS_CONNECTING_COUNTER: Counter = METRICS.metric(&metric_name!("peers", "connecting"));
pub static ref PEERS_DISCONNECTED_COUNTER: Counter = METRICS.metric(&metric_name!("peers", "disconnected"));
}
}
impl PeerManager {
@ -58,6 +61,7 @@ impl PeerManager {
tls_client: TlsClient,
) -> Self
{
init_metrics();
let our_hello = Arc::new(RwLock::new(PeerConnectionHello {
node_id: node_id.to_vec(),
partition: None,