Skip to content

Commit 64b5891

Browse files
author
Dillon George
committed
Add Support for Tracing
**Context** The [`tracing`](https://docs.rs/tracing/latest/tracing/index.html) crate enables more robust instrumentation of Rust programs compared to basic logging. With this patch, we introduce the `tracing` crate into AKD and only enable it when the `tracing` feature is specified. By default, the feature is disabled and we continue to leverage basic logging. In addition to adding `tracing` based logging and instrumentation throughout the `akd` lib (i.e. not `akd_core`), various grammatical and organizational improvements were made in areas where tracing was being added. Notably, the `log_metrics` functions which exist throughout the storage layer were updated to simply log with `info` level instead of taking an argument to specify the level. Rationale being that the `log_metrics` functions are only called when the `runtime_metrics` feature is enabled and `info` is a fair median to assume. **Testing** Since no major functional changes were made, the changes were tested via existing automated tests with various different feature flags being passed to toggle `tracing` on and off.
1 parent fcd665a commit 64b5891

File tree

13 files changed

+217
-120
lines changed

13 files changed

+217
-120
lines changed

Diff for: akd/Cargo.toml

+27-24
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,26 @@ readme = "../README.md"
1414
whatsapp_v1 = ["akd_core/whatsapp_v1"]
1515
experimental = ["akd_core/experimental"]
1616

17-
rand = ["dep:rand"]
17+
# Default features mix (experimental + audit-proof protobuf mgmt support)
18+
default = [
19+
"public_auditing",
20+
"parallel_vrf",
21+
"parallel_insert",
22+
"preload_history",
23+
"greedy_lookup_preload",
24+
"experimental",
25+
]
26+
1827
bench = ["experimental", "public_tests", "tokio/rt-multi-thread"]
28+
# Greedy loading of lookup proof nodes
29+
greedy_lookup_preload = []
30+
public_auditing = ["dep:protobuf", "akd_core/protobuf"]
31+
# Parallelize node insertion during publish
32+
parallel_insert = []
33+
# Parallelize VRF calculations during publish
34+
parallel_vrf = ["akd_core/parallel_vrf"]
35+
# Enable pre-loading of the nodes when generating history proofs
36+
preload_history = []
1937
public_tests = [
2038
"rand",
2139
"dep:colored",
@@ -25,30 +43,14 @@ public_tests = [
2543
"akd_core/rand",
2644
"dep:paste",
2745
]
28-
public_auditing = ["dep:protobuf", "akd_core/protobuf"]
29-
serde_serialization = ["dep:serde", "akd_core/serde_serialization"]
46+
rand = ["dep:rand"]
3047
# Collect runtime metrics on db access calls + timing
3148
runtime_metrics = []
32-
# Parallelize VRF calculations during publish
33-
parallel_vrf = ["akd_core/parallel_vrf"]
34-
# Parallelize node insertion during publish
35-
parallel_insert = []
36-
# Enable pre-loading of the nodes when generating history proofs
37-
preload_history = []
49+
serde_serialization = ["dep:serde", "akd_core/serde_serialization"]
3850
# TESTING ONLY: Artifically slow the in-memory database (for benchmarking)
3951
slow_internal_db = []
40-
# Greedy loading of lookup proof nodes
41-
greedy_lookup_preload = []
42-
43-
# Default features mix (experimental + audit-proof protobuf mgmt support)
44-
default = [
45-
"public_auditing",
46-
"parallel_vrf",
47-
"parallel_insert",
48-
"preload_history",
49-
"greedy_lookup_preload",
50-
"experimental",
51-
]
52+
# Tracing instrumentation
53+
tracing = ["dep:tracing"]
5254

5355
[dependencies]
5456
## Required dependencies ##
@@ -63,12 +65,13 @@ log = { version = "0.4", features = ["kv_unstable"] }
6365
tokio = { version = "1", features = ["sync", "time", "rt"] }
6466

6567
## Optional dependencies ##
66-
serde = { version = "1", features = ["derive"], optional = true }
67-
rand = { version = "0.8", optional = true }
6868
colored = { version = "2", optional = true }
6969
once_cell = { version = "1", optional = true }
70-
protobuf = { version = "3", optional = true }
7170
paste = { version = "1", optional = true }
71+
protobuf = { version = "3", optional = true }
72+
rand = { version = "0.8", optional = true }
73+
serde = { version = "1", features = ["derive"], optional = true }
74+
tracing = {version = "0.1.40", optional = true }
7275

7376
[dev-dependencies]
7477
criterion = "0.5"

Diff for: akd/src/append_only_zks.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
1010
use crate::hash::EMPTY_DIGEST;
1111
use crate::helper_structs::LookupInfo;
12+
use crate::log_shim::info;
1213
use crate::storage::manager::StorageManager;
1314
use crate::storage::types::StorageType;
1415
use crate::tree_node::{
@@ -22,15 +23,17 @@ use crate::{
2223
AppendOnlyProof, AzksElement, AzksValue, Digest, Direction, MembershipProof, NodeLabel,
2324
NonMembershipProof, PrefixOrdering, SiblingProof, SingleAppendOnlyProof, SizeOf, ARITY,
2425
};
26+
27+
2528
use async_recursion::async_recursion;
26-
use log::info;
2729
use std::cmp::Ordering;
2830
#[cfg(feature = "greedy_lookup_preload")]
2931
use std::collections::HashSet;
3032
use std::convert::TryFrom;
3133
use std::marker::Sync;
3234
use std::ops::Deref;
3335

36+
3437
/// The default azks key
3538
pub const DEFAULT_AZKS_KEY: u8 = 1u8;
3639

@@ -802,7 +805,7 @@ impl Azks {
802805
load_count
803806
);
804807
}
805-
storage.log_metrics(log::Level::Info).await;
808+
storage.log_metrics().await;
806809

807810
let (unchanged, leaves) = Self::get_append_only_proof_helper::<TC, _>(
808811
latest_epoch,

Diff for: akd/src/auditor.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::{
1818
};
1919

2020
/// Verifies an audit proof, given start and end hashes for a merkle patricia tree.
21+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
2122
pub async fn audit_verify<TC: Configuration>(
2223
hashes: Vec<Digest>,
2324
proof: AppendOnlyProof,
@@ -52,7 +53,8 @@ pub async fn audit_verify<TC: Configuration>(
5253
Ok(())
5354
}
5455

55-
/// Helper for audit, verifies an append-only proof
56+
/// Helper for audit, verifies an append-only proof.
57+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
5658
pub async fn verify_consecutive_append_only<TC: Configuration>(
5759
proof: &SingleAppendOnlyProof,
5860
start_hash: Digest,

Diff for: akd/src/directory.rs

+54-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::append_only_zks::{Azks, InsertMode};
1111
use crate::ecvrf::{VRFKeyStorage, VRFPublicKey};
1212
use crate::errors::{AkdError, DirectoryError, StorageError};
1313
use crate::helper_structs::LookupInfo;
14+
use crate::log_shim::{error, info};
1415
use crate::storage::manager::StorageManager;
1516
use crate::storage::types::{DbRecord, ValueState, ValueStateRetrievalFlag};
1617
use crate::storage::Database;
@@ -23,11 +24,12 @@ use crate::VersionFreshness;
2324
use akd_core::configuration::Configuration;
2425
use akd_core::utils::get_marker_versions;
2526
use akd_core::verify::history::HistoryParams;
26-
use log::{error, info};
2727
use std::collections::{HashMap, HashSet};
2828
use std::marker::PhantomData;
2929
use std::sync::Arc;
3030
use tokio::sync::RwLock;
31+
#[cfg(feature = "tracing")]
32+
use tracing::Instrument;
3133

3234
/// The representation of a auditable key directory
3335
pub struct Directory<TC, S: Database, V> {
@@ -64,6 +66,7 @@ where
6466
/// Creates a new (stateless) instance of a auditable key directory.
6567
/// Takes as input a pointer to the storage being used for this instance.
6668
/// The state is stored in the storage.
69+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
6770
pub async fn new(storage: StorageManager<S>, vrf: V) -> Result<Self, AkdError> {
6871
let azks = Directory::<TC, S, V>::get_azks_from_storage(&storage, false).await;
6972

@@ -90,8 +93,9 @@ where
9093
///
9194
/// Note that the vector of label-value pairs should not contain any entries with duplicate labels. This
9295
/// condition is explicitly checked, and an error will be returned if this is the case.
96+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all, fields(num_updates = updates.len())))]
9397
pub async fn publish(&self, updates: Vec<(AkdLabel, AkdValue)>) -> Result<EpochHash, AkdError> {
94-
// The guard will be dropped at the end of the publish
98+
// The guard will be dropped at the end of the publish operation
9599
let _guard = self.cache_lock.read().await;
96100

97101
// Check for duplicate labels and return an error if any are encountered
@@ -254,6 +258,7 @@ where
254258
///
255259
/// Returns [Ok((LookupProof, EpochHash))] upon successful generation for the latest version
256260
/// of the target label's state. [Err(_)] otherwise
261+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
257262
pub async fn lookup(&self, akd_label: AkdLabel) -> Result<(LookupProof, EpochHash), AkdError> {
258263
// The guard will be dropped at the end of the proof generation
259264
let _guard = self.cache_lock.read().await;
@@ -281,6 +286,7 @@ where
281286
/// from bulk lookup proof generation, as it has its own preloading operation
282287
///
283288
/// Returns [Ok(LookupProof)] if the proof generation succeeded, [Err(_)] otherwise
289+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
284290
async fn lookup_with_info(
285291
&self,
286292
current_azks: &Azks,
@@ -351,6 +357,7 @@ where
351357

352358
// TODO(eoz): Call proof generations async
353359
/// Allows efficient batch lookups by preloading necessary nodes for the lookups.
360+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
354361
pub async fn batch_lookup(
355362
&self,
356363
akd_labels: &[AkdLabel],
@@ -392,6 +399,7 @@ where
392399
Ok((lookup_proofs, root_hash))
393400
}
394401

402+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
395403
async fn build_lookup_info(&self, latest_st: &ValueState) -> Result<LookupInfo, AkdError> {
396404
let akd_label = &latest_st.username;
397405
// Need to account for the case where the latest state is
@@ -419,6 +427,7 @@ where
419427
})
420428
}
421429

430+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
422431
async fn get_lookup_info(
423432
&self,
424433
akd_label: AkdLabel,
@@ -449,13 +458,21 @@ where
449458
/// this function returns all the values ever associated with it,
450459
/// and the epoch at which each value was first committed to the server state.
451460
/// It also returns the proof of the latest version being served at all times.
461+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
452462
pub async fn key_history(
453463
&self,
454464
akd_label: &AkdLabel,
455465
params: HistoryParams,
456466
) -> Result<(HistoryProof, EpochHash), AkdError> {
457467
// The guard will be dropped at the end of the proof generation
468+
#[cfg(not(feature = "tracing"))]
458469
let _guard = self.cache_lock.read().await;
470+
#[cfg(feature = "tracing")]
471+
let _guard = self
472+
.cache_lock
473+
.read()
474+
.instrument(tracing::trace_span!("cache_lock.read"))
475+
.await;
459476

460477
let current_azks = self.retrieve_azks().await?;
461478
let current_epoch = current_azks.get_latest_epoch();
@@ -616,9 +633,24 @@ where
616633
{
617634
// acquire a singleton lock prior to flushing the cache to assert that no
618635
// cache accesses are underway (i.e. publish/proof generations/etc)
636+
#[cfg(not(feature = "tracing"))]
619637
let _guard = self.cache_lock.write().await;
638+
#[cfg(feature = "tracing")]
639+
let _guard = self
640+
.cache_lock
641+
.write()
642+
.instrument(tracing::trace_span!("cache_lock.write"))
643+
.await;
644+
620645
// flush the cache in its entirety
646+
#[cfg(not(feature = "tracing"))]
621647
self.storage.flush_cache().await;
648+
#[cfg(feature = "tracing")]
649+
self.storage
650+
.flush_cache()
651+
.instrument(tracing::trace_span!("flush_cache"))
652+
.await;
653+
622654
// re-fetch the azks to load it into cache so when we release the cache lock
623655
// others will see the new AZKS loaded up and ready
624656
last =
@@ -643,13 +675,21 @@ where
643675

644676
/// Returns an [AppendOnlyProof] for the leaves inserted into the underlying tree between
645677
/// the epochs `audit_start_ep` and `audit_end_ep`.
678+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all, fields(start_epoch = audit_start_ep, end_epoch = audit_end_ep)))]
646679
pub async fn audit(
647680
&self,
648681
audit_start_ep: u64,
649682
audit_end_ep: u64,
650683
) -> Result<AppendOnlyProof, AkdError> {
651684
// The guard will be dropped at the end of the proof generation
685+
#[cfg(not(feature = "tracing"))]
652686
let _guard = self.cache_lock.read().await;
687+
#[cfg(feature = "tracing")]
688+
let _guard = self
689+
.cache_lock
690+
.read()
691+
.instrument(tracing::trace_span!("cache_lock.read"))
692+
.await;
653693

654694
let current_azks = self.retrieve_azks().await?;
655695
let current_epoch = current_azks.get_latest_epoch();
@@ -673,10 +713,12 @@ where
673713
}
674714

675715
/// Retrieves the [Azks]
716+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
676717
pub(crate) async fn retrieve_azks(&self) -> Result<Azks, crate::errors::AkdError> {
677718
Directory::<TC, S, V>::get_azks_from_storage(&self.storage, false).await
678719
}
679720

721+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all, fields(ignore_cache = ignore_cache)))]
680722
async fn get_azks_from_storage(
681723
storage: &StorageManager<S>,
682724
ignore_cache: bool,
@@ -704,10 +746,12 @@ where
704746
/// HELPERS ///
705747
706748
/// Use this function to retrieve the [VRFPublicKey] for this AKD.
749+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
707750
pub async fn get_public_key(&self) -> Result<VRFPublicKey, AkdError> {
708751
Ok(self.vrf.get_vrf_public_key().await?)
709752
}
710753

754+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
711755
async fn create_single_update_proof(
712756
&self,
713757
akd_label: &AkdLabel,
@@ -770,6 +814,7 @@ where
770814
}
771815

772816
/// Gets the root hash at the current epoch.
817+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
773818
pub async fn get_epoch_hash(&self) -> Result<EpochHash, AkdError> {
774819
let current_azks = self.retrieve_azks().await?;
775820
let latest_epoch = current_azks.get_latest_epoch();
@@ -823,11 +868,13 @@ where
823868
}
824869

825870
/// Read-only access to [Directory::lookup](Directory::lookup).
871+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
826872
pub async fn lookup(&self, uname: AkdLabel) -> Result<(LookupProof, EpochHash), AkdError> {
827873
self.0.lookup(uname).await
828874
}
829875

830876
/// Read-only access to [Directory::batch_lookup](Directory::batch_lookup).
877+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
831878
pub async fn batch_lookup(
832879
&self,
833880
unames: &[AkdLabel],
@@ -836,6 +883,7 @@ where
836883
}
837884

838885
/// Read-only access to [Directory::key_history](Directory::key_history).
886+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
839887
pub async fn key_history(
840888
&self,
841889
uname: &AkdLabel,
@@ -845,6 +893,7 @@ where
845893
}
846894

847895
/// Read-only access to [Directory::poll_for_azks_changes](Directory::poll_for_azks_changes).
896+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
848897
pub async fn poll_for_azks_changes(
849898
&self,
850899
period: tokio::time::Duration,
@@ -854,6 +903,7 @@ where
854903
}
855904

856905
/// Read-only access to [Directory::audit](Directory::audit).
906+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
857907
pub async fn audit(
858908
&self,
859909
audit_start_ep: u64,
@@ -863,11 +913,13 @@ where
863913
}
864914

865915
/// Read-only access to [Directory::get_epoch_hash].
916+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
866917
pub async fn get_epoch_hash(&self) -> Result<EpochHash, AkdError> {
867918
self.0.get_epoch_hash().await
868919
}
869920

870921
/// Read-only access to [Directory::get_public_key](Directory::get_public_key).
922+
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
871923
pub async fn get_public_key(&self) -> Result<VRFPublicKey, AkdError> {
872924
self.0.get_public_key().await
873925
}

Diff for: akd/src/lib.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@
254254
//! First, it encodes a [`HistoryParams`]. Note that the same argument for [`HistoryParams`] that was used to generate
255255
//! the key history proof must also be used to verify the proof. Otherwise, verification may fail.
256256
//!
257-
//! [`HistoryVerificationParams`] also allows the consumer to specify whether or not a "tombstoned" value should be
257+
//! [`HistoryVerificationParams`] also allows the consumer to specify whether a "tombstoned" value should be
258258
//! accepted in place of a valid value for the corresponding entry. This is useful
259259
//! in scenarios where the consumer wishes to verify that a particular entry exists,
260260
//! but does not care about the value associated with it. The default behavior is to
@@ -499,6 +499,19 @@ pub mod helper_structs;
499499
pub mod storage;
500500
pub mod tree_node;
501501

502+
/// Shim module to group logging-related macros more easily
503+
/// when switching between [log] and [tracing].
504+
pub mod log_shim {
505+
#[cfg(feature = "tracing")]
506+
pub use {
507+
tracing::{debug, error, info, trace, warn},
508+
};
509+
#[cfg(not(feature = "tracing"))]
510+
pub use {
511+
log::{debug, error, info, trace, warn},
512+
};
513+
}
514+
502515
#[cfg(feature = "public_auditing")]
503516
pub mod local_auditing;
504517

0 commit comments

Comments
 (0)