mirror of
https://github.com/fluencelabs/aquavm
synced 2025-04-24 14:52:15 +00:00
feat(cli): use eyre in air-cli (#808)
Instead of `anyhow`, use `eyre` to reduce number of deps. The `eyre` crate is already used in `avm-server` and `fluence-keypair`.
This commit is contained in:
parent
9bad40b3d7
commit
47420723bc
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -465,13 +465,13 @@ dependencies = [
|
|||||||
"air-interpreter-interface",
|
"air-interpreter-interface",
|
||||||
"air-interpreter-sede",
|
"air-interpreter-sede",
|
||||||
"air-test-utils",
|
"air-test-utils",
|
||||||
"anyhow",
|
|
||||||
"aquavm-air",
|
"aquavm-air",
|
||||||
"atty",
|
"atty",
|
||||||
"avm-data-store",
|
"avm-data-store",
|
||||||
"avm-interface",
|
"avm-interface",
|
||||||
"bs58 0.5.0",
|
"bs58 0.5.0",
|
||||||
"clap 4.4.11",
|
"clap 4.4.11",
|
||||||
|
"eyre",
|
||||||
"fluence-keypair",
|
"fluence-keypair",
|
||||||
"itertools",
|
"itertools",
|
||||||
"near-sdk",
|
"near-sdk",
|
||||||
|
@ -19,8 +19,8 @@ air-interpreter-data = { version = "0.17.0", path = "../../../crates/air-lib/int
|
|||||||
air-interpreter-sede = { version = "0.1.0", path = "../../../crates/air-lib/interpreter-sede", default-features = false }
|
air-interpreter-sede = { version = "0.1.0", path = "../../../crates/air-lib/interpreter-sede", default-features = false }
|
||||||
air-test-utils = { version = "0.15.1",path = "../../../crates/air-lib/test-utils", optional = true }
|
air-test-utils = { version = "0.15.1",path = "../../../crates/air-lib/test-utils", optional = true }
|
||||||
|
|
||||||
anyhow = "1.0.79"
|
|
||||||
clap = { version = "4.4.7", features = ["derive", "env"] }
|
clap = { version = "4.4.7", features = ["derive", "env"] }
|
||||||
|
eyre = "0.6.11"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
semver = "1.0.21"
|
semver = "1.0.21"
|
||||||
serde = { version = "1.0.190", features = ["derive"] }
|
serde = { version = "1.0.190", features = ["derive"] }
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use air_beautifier::Beautifier;
|
use air_beautifier::Beautifier;
|
||||||
use anyhow::{Context, Result};
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use eyre::{Context, Result};
|
||||||
|
|
||||||
use std::{io, path::PathBuf};
|
use std::{io, path::PathBuf};
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use eyre::Context;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ pub(crate) fn to_human_readable_data(args: Args) -> Result<(), Box<dyn std::erro
|
|||||||
let data: Vec<u8> = load_data(&args.input)?;
|
let data: Vec<u8> = load_data(&args.input)?;
|
||||||
|
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
Err(anyhow::anyhow!("empty input data: {:?}", args.input))?;
|
Err(eyre::eyre!("empty input data: {:?}", args.input))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut runner = create_runner(args.mode.into(), &args.air_interpreter_path)?;
|
let mut runner = create_runner(args.mode.into(), &args.air_interpreter_path)?;
|
||||||
@ -98,7 +98,7 @@ fn init_tracing(tracing_params: &str) {
|
|||||||
fn create_runner(
|
fn create_runner(
|
||||||
mode: Option<Mode>,
|
mode: Option<Mode>,
|
||||||
_air_interpreter_wasm_path: &Path,
|
_air_interpreter_wasm_path: &Path,
|
||||||
) -> anyhow::Result<Box<dyn DataToHumanReadable>> {
|
) -> eyre::Result<Box<dyn DataToHumanReadable>> {
|
||||||
#[cfg(not(feature = "wasm"))]
|
#[cfg(not(feature = "wasm"))]
|
||||||
let default_mode = Mode::Native;
|
let default_mode = Mode::Native;
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
|
@ -28,9 +28,9 @@ pub(crate) mod runner;
|
|||||||
use self::runner::AirRunner;
|
use self::runner::AirRunner;
|
||||||
use avm_interface::CallResults;
|
use avm_interface::CallResults;
|
||||||
|
|
||||||
use anyhow::Context as _;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
|
use eyre::Context as _;
|
||||||
use fluence_keypair::KeyPair;
|
use fluence_keypair::KeyPair;
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ struct Keys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Keys {
|
impl Keys {
|
||||||
fn get_keypair(&self) -> anyhow::Result<KeyPair> {
|
fn get_keypair(&self) -> eyre::Result<KeyPair> {
|
||||||
match (self.random_key, self.ed25519_key.as_ref()) {
|
match (self.random_key, self.ed25519_key.as_ref()) {
|
||||||
(true, None) => Ok(KeyPair::generate_ed25519()),
|
(true, None) => Ok(KeyPair::generate_ed25519()),
|
||||||
(false, Some(path)) => load_keypair_ed25519(path),
|
(false, Some(path)) => load_keypair_ed25519(path),
|
||||||
@ -168,7 +168,7 @@ enum Mode {
|
|||||||
Risc0,
|
Risc0,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run(args: Args) -> anyhow::Result<()> {
|
pub(crate) fn run(args: Args) -> eyre::Result<()> {
|
||||||
let tracing_json = (!args.json) as u8;
|
let tracing_json = (!args.json) as u8;
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
let global_tracing_params = if args.mode.wasm {
|
let global_tracing_params = if args.mode.wasm {
|
||||||
@ -235,7 +235,7 @@ fn create_runner(
|
|||||||
_air_interpreter_wasm_path: &Path,
|
_air_interpreter_wasm_path: &Path,
|
||||||
_air_contract_wasm_path: &Path,
|
_air_contract_wasm_path: &Path,
|
||||||
_max_heap_size: Option<u64>,
|
_max_heap_size: Option<u64>,
|
||||||
) -> anyhow::Result<Box<dyn AirRunner>> {
|
) -> eyre::Result<Box<dyn AirRunner>> {
|
||||||
#[cfg(not(feature = "wasm"))]
|
#[cfg(not(feature = "wasm"))]
|
||||||
let default_mode = Mode::Native;
|
let default_mode = Mode::Native;
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
@ -274,7 +274,7 @@ pub fn init_tracing(tracing_params: String, trace_mode: u8) {
|
|||||||
builder.init();
|
builder.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_call_results(call_results_path: Option<&Path>) -> anyhow::Result<CallResults> {
|
fn read_call_results(call_results_path: Option<&Path>) -> eyre::Result<CallResults> {
|
||||||
match call_results_path {
|
match call_results_path {
|
||||||
None => Ok(CallResults::default()),
|
None => Ok(CallResults::default()),
|
||||||
Some(call_results_path) => {
|
Some(call_results_path) => {
|
||||||
@ -291,18 +291,18 @@ fn read_call_results(call_results_path: Option<&Path>) -> anyhow::Result<CallRes
|
|||||||
fn load_data_or_default(
|
fn load_data_or_default(
|
||||||
data_path: Option<impl AsRef<Path>>,
|
data_path: Option<impl AsRef<Path>>,
|
||||||
default: &[u8],
|
default: &[u8],
|
||||||
) -> anyhow::Result<Vec<u8>> {
|
) -> eyre::Result<Vec<u8>> {
|
||||||
match data_path {
|
match data_path {
|
||||||
None => Ok(default.to_owned()),
|
None => Ok(default.to_owned()),
|
||||||
Some(data_path) => load_data(data_path.as_ref()),
|
Some(data_path) => load_data(data_path.as_ref()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn load_data(data_path: &Path) -> anyhow::Result<Vec<u8>> {
|
pub(crate) fn load_data(data_path: &Path) -> eyre::Result<Vec<u8>> {
|
||||||
std::fs::read(data_path).with_context(|| data_path.to_string_lossy().into_owned())
|
std::fs::read(data_path).with_context(|| data_path.to_string_lossy().into_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_keypair_ed25519(path: &PathBuf) -> Result<KeyPair, anyhow::Error> {
|
fn load_keypair_ed25519(path: &PathBuf) -> Result<KeyPair, eyre::Error> {
|
||||||
use fluence_keypair::KeyFormat;
|
use fluence_keypair::KeyFormat;
|
||||||
|
|
||||||
// It follows rust-peer format
|
// It follows rust-peer format
|
||||||
|
@ -19,8 +19,8 @@ use super::ExecutionData;
|
|||||||
use avm_data_store::AnomalyData;
|
use avm_data_store::AnomalyData;
|
||||||
use avm_interface::ParticleParameters;
|
use avm_interface::ParticleParameters;
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use eyre::Context;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ pub(crate) struct AnomalyDataArgs {
|
|||||||
anomaly_data_path: PathBuf,
|
anomaly_data_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn load(args: &AnomalyDataArgs) -> anyhow::Result<super::ExecutionData<'_>> {
|
pub(crate) fn load(args: &AnomalyDataArgs) -> eyre::Result<super::ExecutionData<'_>> {
|
||||||
let anomaly_json = load_data(&args.anomaly_data_path).context("Failed to read anomaly data")?;
|
let anomaly_json = load_data(&args.anomaly_data_path).context("Failed to read anomaly data")?;
|
||||||
let anomaly_data: AnomalyData<'_> =
|
let anomaly_data: AnomalyData<'_> =
|
||||||
serde_json::from_slice(&anomaly_json).context("Failed to parse anomaly data")?;
|
serde_json::from_slice(&anomaly_json).context("Failed to parse anomaly data")?;
|
||||||
|
@ -18,7 +18,7 @@ use super::super::super::utils::unix_timestamp_now;
|
|||||||
use super::ExecutionData;
|
use super::ExecutionData;
|
||||||
use avm_interface::ParticleParameters;
|
use avm_interface::ParticleParameters;
|
||||||
|
|
||||||
use anyhow::Context;
|
use eyre::Context;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ pub(crate) struct PlainDataArgs {
|
|||||||
particle_id: Option<String>,
|
particle_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn load(args: &PlainDataArgs) -> anyhow::Result<ExecutionData<'_>> {
|
pub(crate) fn load(args: &PlainDataArgs) -> eyre::Result<ExecutionData<'_>> {
|
||||||
use super::super::load_data_or_default;
|
use super::super::load_data_or_default;
|
||||||
|
|
||||||
let air_script = read_air_with_prompt(args.air_script_path.as_deref())
|
let air_script = read_air_with_prompt(args.air_script_path.as_deref())
|
||||||
@ -77,7 +77,7 @@ pub(crate) fn load(args: &PlainDataArgs) -> anyhow::Result<ExecutionData<'_>> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_air_with_prompt(air_input: Option<&Path>) -> anyhow::Result<String> {
|
fn read_air_with_prompt(air_input: Option<&Path>) -> eyre::Result<String> {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
let air_script = match air_input {
|
let air_script = match air_input {
|
||||||
|
@ -41,7 +41,7 @@ impl AirRunner for NativeAvmRunner {
|
|||||||
_tracing_output_mode: u8,
|
_tracing_output_mode: u8,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
particle_id: String,
|
particle_id: String,
|
||||||
) -> anyhow::Result<RawAVMOutcome> {
|
) -> eyre::Result<RawAVMOutcome> {
|
||||||
use air_interpreter_sede::ToSerialized;
|
use air_interpreter_sede::ToSerialized;
|
||||||
use avm_interface::into_raw_result;
|
use avm_interface::into_raw_result;
|
||||||
|
|
||||||
@ -79,6 +79,6 @@ impl DataToHumanReadable for NativeAvmRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create_native_avm_runner() -> anyhow::Result<Box<NativeAvmRunner>> {
|
pub(crate) fn create_native_avm_runner() -> eyre::Result<Box<NativeAvmRunner>> {
|
||||||
Ok(Box::new(NativeAvmRunner {}))
|
Ok(Box::new(NativeAvmRunner {}))
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ use super::runner::AirRunner;
|
|||||||
|
|
||||||
use air_interpreter_interface::InterpreterOutcome;
|
use air_interpreter_interface::InterpreterOutcome;
|
||||||
use air_interpreter_interface::RunParameters;
|
use air_interpreter_interface::RunParameters;
|
||||||
use anyhow::Context;
|
|
||||||
use avm_interface::raw_outcome::RawAVMOutcome;
|
use avm_interface::raw_outcome::RawAVMOutcome;
|
||||||
|
use eyre::Context;
|
||||||
use fluence_keypair::KeyPair;
|
use fluence_keypair::KeyPair;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -43,7 +43,7 @@ impl AirRunner for NearRunner {
|
|||||||
_tracing_output_mode: u8,
|
_tracing_output_mode: u8,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
particle_id: String,
|
particle_id: String,
|
||||||
) -> anyhow::Result<RawAVMOutcome> {
|
) -> eyre::Result<RawAVMOutcome> {
|
||||||
let key_format = keypair.key_format().into();
|
let key_format = keypair.key_format().into();
|
||||||
let secret_key_bytes = keypair.secret().expect("Failed to get secret key");
|
let secret_key_bytes = keypair.secret().expect("Failed to get secret key");
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ impl AirRunner for NearRunner {
|
|||||||
|
|
||||||
pub(crate) fn create_near_runner(
|
pub(crate) fn create_near_runner(
|
||||||
air_contract_wasm_path: &Path,
|
air_contract_wasm_path: &Path,
|
||||||
) -> anyhow::Result<Box<dyn AirRunner>> {
|
) -> eyre::Result<Box<dyn AirRunner>> {
|
||||||
let air_contract_wasm_path = air_contract_wasm_path.to_owned();
|
let air_contract_wasm_path = air_contract_wasm_path.to_owned();
|
||||||
|
|
||||||
Ok(Box::new(NearRunner {
|
Ok(Box::new(NearRunner {
|
||||||
@ -85,7 +85,7 @@ fn execute_on_near(
|
|||||||
current_data: Vec<u8>,
|
current_data: Vec<u8>,
|
||||||
run_parameters: RunParameters,
|
run_parameters: RunParameters,
|
||||||
call_results: avm_interface::CallResults,
|
call_results: avm_interface::CallResults,
|
||||||
) -> anyhow::Result<avm_interface::raw_outcome::RawAVMOutcome> {
|
) -> eyre::Result<avm_interface::raw_outcome::RawAVMOutcome> {
|
||||||
use avm_interface::into_raw_result;
|
use avm_interface::into_raw_result;
|
||||||
|
|
||||||
let run_parameters = serde_json::to_string(&run_parameters)?;
|
let run_parameters = serde_json::to_string(&run_parameters)?;
|
||||||
|
@ -53,7 +53,7 @@ impl AirRunner for Risc0Runner {
|
|||||||
_tracing_output_mode: u8,
|
_tracing_output_mode: u8,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
particle_id: String,
|
particle_id: String,
|
||||||
) -> anyhow::Result<RawAVMOutcome> {
|
) -> eyre::Result<RawAVMOutcome> {
|
||||||
let key_format = keypair.key_format().into();
|
let key_format = keypair.key_format().into();
|
||||||
let secret_key_bytes = keypair.secret().expect("Failed to get secret key");
|
let secret_key_bytes = keypair.secret().expect("Failed to get secret key");
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ impl AirRunner for Risc0Runner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_on_risc0(arguments: AquaVMProvingParameters) -> anyhow::Result<RawAVMOutcome> {
|
fn execute_on_risc0(arguments: AquaVMProvingParameters) -> eyre::Result<RawAVMOutcome> {
|
||||||
use risc0_zkvm::serde::from_slice;
|
use risc0_zkvm::serde::from_slice;
|
||||||
|
|
||||||
let env = ExecutorEnv::builder().write(&arguments)?.build()?;
|
let env = ExecutorEnv::builder().write(&arguments)?.build()?;
|
||||||
|
@ -36,7 +36,7 @@ pub(crate) trait AirRunner {
|
|||||||
tracing_output_mode: u8,
|
tracing_output_mode: u8,
|
||||||
key_pair: &KeyPair,
|
key_pair: &KeyPair,
|
||||||
particle_id: String,
|
particle_id: String,
|
||||||
) -> anyhow::Result<RawAVMOutcome>;
|
) -> eyre::Result<RawAVMOutcome>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait DataToHumanReadable {
|
pub(crate) trait DataToHumanReadable {
|
||||||
|
@ -39,7 +39,7 @@ impl AirRunner for WasmAvmRunner {
|
|||||||
tracing_output_mode: u8,
|
tracing_output_mode: u8,
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
particle_id: String,
|
particle_id: String,
|
||||||
) -> anyhow::Result<avm_interface::raw_outcome::RawAVMOutcome> {
|
) -> eyre::Result<avm_interface::raw_outcome::RawAVMOutcome> {
|
||||||
let call_tracing = self.0.call_tracing(
|
let call_tracing = self.0.call_tracing(
|
||||||
air,
|
air,
|
||||||
prev_data,
|
prev_data,
|
||||||
@ -71,7 +71,7 @@ impl DataToHumanReadable for WasmAvmRunner {
|
|||||||
pub(crate) fn create_wasm_avm_runner(
|
pub(crate) fn create_wasm_avm_runner(
|
||||||
air_interpreter_wasm_path: &Path,
|
air_interpreter_wasm_path: &Path,
|
||||||
max_heap_size: Option<u64>,
|
max_heap_size: Option<u64>,
|
||||||
) -> anyhow::Result<Box<WasmAvmRunner>> {
|
) -> eyre::Result<Box<WasmAvmRunner>> {
|
||||||
Ok(Box::new(WasmAvmRunner(AVMRunner::new(
|
Ok(Box::new(WasmAvmRunner(AVMRunner::new(
|
||||||
air_interpreter_wasm_path.to_owned(),
|
air_interpreter_wasm_path.to_owned(),
|
||||||
max_heap_size,
|
max_heap_size,
|
||||||
|
@ -33,7 +33,7 @@ pub(crate) struct Args {
|
|||||||
sort_stats_by_duration: bool,
|
sort_stats_by_duration: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn stats(mut args: Args) -> anyhow::Result<()> {
|
pub(crate) fn stats(mut args: Args) -> eyre::Result<()> {
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
if !args.pretty && !args.stats {
|
if !args.pretty && !args.stats {
|
||||||
@ -69,14 +69,14 @@ pub(crate) fn stats(mut args: Args) -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_logs<R: std::io::BufRead>(input: R) -> impl Iterator<Item = anyhow::Result<LogRecord>> {
|
fn read_logs<R: std::io::BufRead>(input: R) -> impl Iterator<Item = eyre::Result<LogRecord>> {
|
||||||
input.lines().filter_map(|r| match r {
|
input.lines().filter_map(|r| match r {
|
||||||
Ok(line) => {
|
Ok(line) => {
|
||||||
let line = line.trim();
|
let line = line.trim();
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(serde_json::from_str(line).map_err(anyhow::Error::from))
|
Some(serde_json::from_str(line).map_err(eyre::Error::from))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => Some(Err(err.into())),
|
Err(err) => Some(Err(err.into())),
|
||||||
|
@ -49,7 +49,7 @@ impl StatsReport {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn consider(&mut self, rec: LogRecord) -> anyhow::Result<()> {
|
pub(crate) fn consider(&mut self, rec: LogRecord) -> eyre::Result<()> {
|
||||||
if let Message::Close(close) = &rec.value.fields {
|
if let Message::Close(close) = &rec.value.fields {
|
||||||
let time_busy = parse_tracing_duration(&close.time_busy)?;
|
let time_busy = parse_tracing_duration(&close.time_busy)?;
|
||||||
*self.data.entry(rec.get_key()).or_default() += time_busy;
|
*self.data.entry(rec.get_key()).or_default() += time_busy;
|
||||||
|
@ -17,7 +17,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
// unfortunately, external crates don't seem to provide required functionality:
|
// unfortunately, external crates don't seem to provide required functionality:
|
||||||
// some do not handle floats, others do not handle suffixes
|
// some do not handle floats, others do not handle suffixes
|
||||||
pub(crate) fn parse_tracing_duration(input: &str) -> Result<Duration, anyhow::Error> {
|
pub(crate) fn parse_tracing_duration(input: &str) -> Result<Duration, eyre::Error> {
|
||||||
for (suffix, scale) in [("ns", 1e-9), ("µs", 1e-6), ("ms", 1e-3), ("s", 1e0)] {
|
for (suffix, scale) in [("ns", 1e-9), ("µs", 1e-6), ("ms", 1e-3), ("s", 1e0)] {
|
||||||
if let Some(num_str) = input.strip_suffix(suffix) {
|
if let Some(num_str) = input.strip_suffix(suffix) {
|
||||||
if let Ok(num) = num_str.parse::<f64>() {
|
if let Ok(num) = num_str.parse::<f64>() {
|
||||||
@ -28,7 +28,7 @@ pub(crate) fn parse_tracing_duration(input: &str) -> Result<Duration, anyhow::Er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(anyhow::anyhow!("malformed duration {:?}", input))
|
Err(eyre::eyre!("malformed duration {:?}", input))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn unix_timestamp_now() -> u64 {
|
pub(crate) fn unix_timestamp_now() -> u64 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user