Trying to work with a mutable closure and warp

Hi,

I have a basic web server running warp, and I want to add a basic logging feature that can write to a logfile. However, this is proving much more difficult than I would expect, since the map function that comes with the Filter trait doesn't let you pass in a FnMut closure type.

Here's a piece of code that I would like to work, but doesn't

let mut log_file = OpenOptions::new()
        .write(true)
        .create(true)
        .open(log_file_path)
        .expect("couldn't open or create log file");

let pending_handler = warp::path("pending").and(warp::body::json()).map(
  |mut req_body: HashMap<String, String>| {

  // Do something here
  let log = "Some log".to_owned();
  // THIS DOES NOT WORK
  log_file.write_all(log.as_bytes()).unwrap();

  "OK".to_owned()
});

// Serve warp routes here

What am I missing? Are there any workarounds? Any help would be appreciated

You should never use std::fs in async code. Use tokio::fs instead. You should wrap the file in a tokio::sync::Mutex so that access to it is synchronized between tasks. Also you'll need and_then not map to allow you to use async operations.

I have a blog post that elaborates on why you shouldn't use std::fs in async code: Async: What is blocking?

Consider using a library like log or tracing instead of manually implementing logging. They will both allow you to log to a file I believe, and are well-supported in the ecosystem.

To add to @Kestrer, I often use simplelog if I just need to do some logging to a file. Very easy. And then you can use something like log::info!() in your program whenever you need to write to the log without needing to pass around a file handle.