I wish to set slog-async logging level to a user-defined value upon execution of the application.
Is there a way to set slog-async to desired logging level at runtime?
today my slog-async setup looks like this:
extern crate slog;
extern crate slog_term;
extern crate slog_async;
use slog::{Drain};
/* Initiate slog the logger */
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::FullFormat::new(decorator).build().fuse();
let drain = slog_async::Async::new(drain).build().fuse();
let logger = slog::Logger::root(drain, slog::o!());
and logging is performed is through calling:
slog::debug!(logger, "SQLite database at {} already exists", &db_url);
but have no idea on how to make logging level only warning and more severe.
Related
I want to execute this Move script, e.g. at sources/top_up.move:
script {
use std::signer;
use aptos_framework::aptos_account;
use aptos_framework::aptos_coin;
use aptos_framework::coin;
fun main(src: &signer, dest: address, desired_balance: u64) {
let src_addr = signer::address_of(src);
let balance = coin::balance<aptos_coin::AptosCoin>(src_addr);
if (balance < desired_balance) {
aptos_account::transfer(src, dest, desired_balance - balance);
};
}
}
This is calling functions on the aptos_coin.move module, which is deployed on chain. What it does isn't so important for this question, but in short, it checks that the balance of the destination account is less than desired_balance, and if so, tops it up to desired_balance.
I can execute this Move script via the CLI easily like this:
aptos move compile
aptos move run-script --compiled-script-path build/MyModule/bytecode_scripts/main.mv
Or even just this:
aptos move run-script --script-path sources/top_up.move
What I want to know is whether I can do this using the Rust SDK?
First, you need to compile the script, as you did above. Imagine you have a project layout like this:
src/
main.rs
move/
Move.toml
sources/
top_up.mv
You would want to go in to move/ and run aptos move compile, like you said above. From there, you can depend on the compiled script in your code (see below).
With that complete, here is a minimal code example demonstrating how to execute a Move script using the Rust SDK.
Cargo.toml:
[package]
name = "my-example"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1"
aptos-sdk = { git = "https://github.com/aptos-labs/aptos-core", branch = "mainnet" }
src/main.rs:
use aptos_sdk::crypto::ed25519::Ed25519PublicKey;
use aptos_sdk::types::transaction::authenticator::AuthenticationKey;
use aptos_sdk::{
rest_client::Client,
transaction_builder::TransactionFactory,
types::{
account_address::AccountAddress,
chain_id::ChainId,
transaction::{Script, SignedTransaction, TransactionArgument},
LocalAccount,
},
};
static SCRIPT: &[u8] =
include_bytes!("../../move/build/MyModule/bytecode_scripts/main.mv");
fn main() -> anyhow::Result<()> {
// Prior to the follow code we assume you've already acquired the necessary
// information such as chain_id, the private key of the account submitting
// the transaction, arguments for the Move script, etc.
// Build a transaction factory.
let txn_factory = TransactionFactory::new(chain_id);
// Build a local representation of an account.
let account = LocalAccount::new(
AuthenticationKey::ed25519(&Ed25519PublicKey::from(&private_key)).derived_address()
private_key,
0,
);
// Build an API client.
let client = Client::new("https://fullnode.mainnet.aptoslabs.com");
// Create a builder where the payload is the script.
let txn_builder = transaction_factory.script(Script::new(
SCRIPT.to_vec(),
// type args
vec![],
// args
vec![
TransactionArgument::Address(dest_address),
TransactionArgument::U64(desired_balance),
],
)));
// Build the transaction request and sign it.
let signed_txn = account.sign_with_transaction_builder(
txn_builder
);
// Submit the transaction.
client.submit_and_wait_bcs(&signed_transaction).await?;
}
I am using the Rust Playground to test a piece of code, sample:
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let query = args.get(1).unwrap();
// do something ...
}
Playground link
How do I provide a command-line argument for running a program in Rust Playground? The sample drop-down next to the run button does not have any link or perhaps I am missing it?
Thanks!
You can't, there is an open issue for this feature
As #Stargateur correctly answered, it's currently impossible to provide input for the playground code itself. However, there's a little trick which can work in relatively simple cases: we can execute std::process::Command, which starts bash, which can execute arbitrary code - including cargo.
Here's how it can look like, for example:
// This is your real `fn main`, which would use the input.
// It can contain everything that's usually possible in the playground.
#[cfg(real_main)]
fn main() {
let args: Vec<String> = std::env::args().collect();
println!("Args: {:?}", args);
}
// This is the wrapper-function, directly executed by the playground.
#[cfg(not(real_main))]
fn main() {
// We're shelling out to `bash`, to execute `cargo run` with additional config.
let _ = std::process::Command::new("/bin/bash")
.args(&[
"-c",
concat!(
r##"{
"##,
// In case we have any kind of error, we want to exit loudly.
r##"
set -euo pipefail
"##,
// `cargo rustc` allows one to pass additional compiler flags.
// It's important that this will recompile the current crate only,
// since, if we had to build the whole dependency tree
// (which is quite large), playground will inevitably timeout.
r##"
cargo rustc -q -- --cfg real_main
"##,
// When building in release mode, replace `target/debug`
// with `target/release`.
r##"
./target/debug/playground arg1 arg2 arg3
"##,
// Finally, we rediirect the stderr of the whole script to stdout,
// to show it in the playground output.
r##"
} 2>&1"##
),
])
// On running `Command::status`, output is piped by default,
// so it will be shown as usual.
.status();
}
Playground link
I'm trying to use the Web3 JavaScript library from Rust and I'm stuck. The standard usage of the library starts with:
// In Node.js use: const Web3 = require('web3');
let web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");
The module you're supposed to import is a constructor, that also has some other properties. My Rust code that's supposed to bind this API looks like this:
#[wasm_bindgen(module = "web3")]
extern "C" {
type Web3;
#[wasm_bindgen(constructor)]
fn new(_: &Provider) -> Web3;
type Provider;
static givenProvider: Provider;
}
Which ends up outputting import { Web3, givenProvider } from 'web3'; and trying to run new Web3(...) which fails. It should be doing something like import * as Web3 from 'web3';, running new Web3(...) and referencing Web3.givenProvider.
How can I get wasm-bindgen to output code like that?
EDIT: The original answer is wrong. You can import things defined like that using wasm-bindgen, and they are legal ES6. Or at least the same concept is available in ES6 modules. They call them default exports/imports. It's a bit awkward, but the way to import them is to use js_name = "default". Like so:
#[wasm_bindgen(module = "web3")]
extern "C" {
#[wasm_bindgen(js_name = "default")]
type Web3;
#[wasm_bindgen(constructor, js_class = "default")]
fn new(_: &Provider) -> Web3;
#[wasm_bindgen(static_method_of = Web3, getter, js_class = "default")]
fn givenProvider() -> Provider;
type Provider;
}
You need the js_class parameter on methods, it doesn't remember that Web3's js_name is default.
Old, wrong answer:
The reason you can't get wasm-bindgen to generate code like that is because it's not legal ES6. ECMAScript modules use named exports for everything. Web3 is actually a CommonJS module, and those do support having a single anonymous export.
The reason it almost works is because I was using webpack, and webpack lets you import CommonJS modules using ES6 syntax, even though the semantics are slightly different.
The solution is to make a little shim, exporting the CommonJS module from an ES6 module:
export let Web3 = require('web3');
Then this binding will work:
#[wasm_bindgen(module = "/src/web3-wrapper.js")]
extern "C" {
type Web3;
#[wasm_bindgen(constructor)]
fn new(_: &Provider) -> Web3;
#[wasm_bindgen(static_method_of = Web3, getter)]
fn givenProvider() -> Provider;
type Provider;
}
If I call .to_path_buf() immediately after expect, the temporary directory will not be created. Is this a bug or a Rust feature?
extern crate mktemp;
use std::path::Path;
fn main() {
let temp_dir = mktemp::Temp::new_dir().expect("Failed to create a temp directory");
let temp_dir_path = temp_dir.to_path_buf();
println!("tmp path exists: {}", Path::exists(&temp_dir_path));
let temp_dir_path = mktemp::Temp::new_dir().expect("Failed to create a temp directory").to_path_buf();
println!("tmp path exists: {}", Path::exists(&temp_dir_path));
}
Which outputs:
tmp path exists: true
tmp path exists: false
I don't know, but I wonder if there's something in the mktemp documentation about this...
Once the variable goes out of scope, the underlying file system resource is removed.
You're not storing the Temp in a variable, so it goes out of scope immediately. It's creating the directory and then immediately destroying it.
I'm trying to build rustless on Windows:
This is my Cargo.toml:
[dependencies.rustless]
git = "https://github.com/rustless/rustless"
[package]
name = "ccampo_substancias_srv"
version = "0.0.1"
authors = [ "------------------------------" ]
[[bin]]
name = "Rest_test"
This is main.rs:
#![feature(plugin)]
#[plugin]
extern crate rustless;
extern crate hyper;
extern crate iron;
extern crate "rustc-serialize" as rustc_serialize;
extern crate valico;
use hyper::status::StatusCode;
use iron::Iron;
use rustless::{
Application, Api, Nesting, Versioning
};
use rustc_serialize::json::ToJson;
fn main() {
let api = Api::build(dsl!(|api| {
// Specify API version
version("v1", Versioning::AcceptHeader("chat"));
prefix("api");
// Create API for chats
mount(Api::build(dsl!(|chats_api| {
after(|client, _params| {
client.set_status(StatusCode::NotFound);
Ok(())
});
// Add namespace
namespace("chats/:id", dsl!(|chat_ns| {
// Valico settings for this namespace
params(|params| {
params.req_typed("id", valico::u64())
});
// Create endpoint for POST /chats/:id/users/:user_id
post("users/:user_id", dsl!(|endpoint| {
// Add description
desc("Update user");
// Valico settings for endpoint params
params(|params| {
params.req_typed("user_id", valico::u64());
params.req_typed("name", valico::string())
});
handle(|client, params| {
client.json(¶ms.to_json())
})
}));
}));
})));
}));
let app = Application::new(api);
Iron::new(app).listen("localhost:4000").unwrap();
println!("On 4000");
println!("Rustless server started!");
}
Building with "cargo build --verbose" and rust 1.5 (64bit) on Windows 10.
This is the error I'm getting, looks like it's related to some file path:
Fresh jsonway v0.3.5
Fresh conduit-mime-types v0.7.3
Fresh winapi v0.2.5
Build failed, waiting for other jobs to finish...
could not rename crate "C:\\Users\\Pedro\\workspace\\ccampo-substancias-srv\\target\\debug\\build\\advapi32-sys-cfef7a1f30f1e5f6\\build_script_build.exe"
Caused by: Acesso negado. (os error 5)
Do you have antivirus/anti-malware software on your computer? It might be trying to analyze your program, locking the file. Try disabling it temporarily or adding an exception on your project directory, then try building again.