For example, here's a normal usage of the log macros
#[async_trait]
impl HttpServer for LogtestActor {
async fn handle_request(
&self,
ctx: &Context,
req: &HttpRequest,
) -> std::result::Result<HttpResponse, RpcError> {
let text = form_urlencoded::parse(req.query_string.as_bytes())
.find(|(n, _)| n == "name")
.map(|(_, v)| v.to_string())
.unwrap_or_else(|| "World".to_string());
wasmcloud_interface_logging::info!("Neat! works fine"); /// <- here
Ok(HttpResponse {
body: format!("Hello {}", text).as_bytes().to_vec(),
..Default::default()
})
}
}
This works fine as expected, but as actors get larger it's usually desirable to split functionality off into helper functions. So when one tries to do this they get:
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> src/lib.rs:46:5
|
45 | fn foo() {
| --- this is not `async`
46 | info!("hey, why doesn't this work?");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
= note: this error originates in the macro `info` (in Nightly builds, run with -Z macro-backtrace for more info)
Then when they try to make it async:
error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/lib.rs:50:5
|
49 | async fn bar() {
| ________________-
50 | | info!("Woah, no compile?");
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in an async function that returns `()`
51 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Result<Infallible, wasmbus_rpc::error::RpcError>>` is not implemented for `()`
= note: this error originates in the macro `info` (in Nightly builds, run with -Z macro-backtrace for more info)
And then, if they forget async and do end up returning an RpcResult
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> src/lib.rs:54:5
|
53 | fn baz() -> RpcResult<()> {
| --- this is not `async`
54 | info!("Woah, not here either?");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
= note: this error originates in the macro `info` (in Nightly builds, run with -Z macro-backtrace for more info)
If they have their own result type that doesn't have an implementation from the error type to wasmbus_rpc::error::Error
, then the error shows as well (@mattgilbride ran into this)
This is mostly to provide a few examples where developers are commonly going to hit errors trying to log outside of the actor handlers itself. The following bit of code helps, but requires constructing a Struct and passing ctx
around.
let log_sender = LoggingSender::new();
log_sender
.write_log(
ctx,
&LogEntry {
level: "info".to_string(),
text: "my text".to_string(),
},
)
.await?;
Ideally, log macros should be able to be called from synchronous contexts that don't return results (a sync, void macro)