///|
async fn start_runtime_logging(
  directory : String,
) -> @logging.RuntimeLogging raise AppRunError {
  let config = @xlog.Config::from_env(level=@xlog.Warn) catch {
    error =>
      raise LoggingInitializationFailed(
        detail="invalid MOON_XLOG configuration: " +
          xlog_config_error_message(error),
      )
  }
  let packaged = packaged_application_manifest_path() is Some(_)
  let output = match @env.get_env_var("PROTON_LOG_OUTPUT") {
    None => if packaged { "file" } else { "stderr" }
    Some(value) => value.trim().to_owned().to_lower()
  }
  let selected = match output {
    "stderr" => @logging.Output::Stderr
    "file" => {
      guard packaged else {
        raise LoggingInitializationFailed(
          detail="file logging requires packaged application metadata",
        )
      }
      ensure_log_directory(directory)
      let filename = "proton-" +
        @logging.current_process_id().to_string() +
        ".log"
      @logging.Output::File(
        @mbpath.Path(directory).join(filename).normalize().to_string(),
      )
    }
    value =>
      raise LoggingInitializationFailed(
        detail="PROTON_LOG_OUTPUT must be stderr or file, got: " + value,
      )
  }
  @logging.RuntimeLogging(selected, config) catch {
    error =>
      raise LoggingInitializationFailed(detail=@debug.render(Repr(error)))
  }
}

///|
async fn ensure_log_directory(path : String) -> Unit raise AppRunError {
  if @mbfs.path_exists(path) {
    guard log_path_is_directory(path) else {
      raise LoggingInitializationFailed(
        detail="application log path is not a directory: " + path,
      )
    }
    return
  }
  let parent : String = @mbpath.Path(path).dirname().normalize().to_string()
  guard parent != path else {
    raise LoggingInitializationFailed(
      detail="cannot resolve parent of application log directory: " + path,
    )
  }
  ensure_log_directory(parent)
  @async_fs.mkdir(path) catch {
    error => {
      if @mbfs.path_exists(path) && log_path_is_directory(path) {
        return
      }
      raise LoggingInitializationFailed(
        detail="cannot create application log directory: " + error.to_string(),
      )
    }
  }
}

///|
fn log_path_is_directory(path : String) -> Bool {
  @mbfs.is_dir(path) catch {
    _ => false
  }
}

///|
fn xlog_config_error_message(error : @xlog.ConfigError) -> String {
  match error {
    @xlog.ConfigError::InvalidCategory(value) => "invalid category: " + value
    @xlog.ConfigError::InvalidDirective(value) => "invalid directive: " + value
    @xlog.ConfigError::InvalidLevel(value) => "invalid level: " + value
  }
}