Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#5873] feat(gvfs-fuse): add debug log for FuseApiHandle #5905

Open
wants to merge 40 commits into
base: main
Choose a base branch
from

Conversation

unknowntpo
Copy link
Contributor

@unknowntpo unknowntpo commented Dec 18, 2024

What changes were proposed in this pull request?

Implement FuseApiHandleDebug so we can log all input arguments and return values of FuseApiHandle.
I use tracing::debug, tracing::error with structure logging to format the message in key value pair format, so we don't need to control format manually.

e.g.

        debug!(req.unique, ?req, parent = ?parent_stat.name, ?name, "lookup started");

And user can set fuse_debug = true in [fuse] section at config file like gvfs_fuse_memory.toml to decide whether they need fuse debug logging or not.

Fix: #5873

Does this PR introduce any user-facing change?

No.

How was this patch tested?

tested with fuse_test.rs, along with MemoryFileSystem.

Now, FuseApiHandleDebug will wrap FuseApiHandle and log all input arguments and returned values, if return value is Result, we use match to extract and log the status of result, note that error will be logged if occured.

To test this PR, set fuse_debug = true in gvfs_fuse_memory.toml and run:

cd ./clients/filesystem-fuse
RUST_LOG=gvfs_fuse::fuse_api_handle=debug make test

Here's some example logging generated by test_fuse_system_with_auto in fuse_test.rs:

2025-01-16T02:59:13.860193Z DEBUG gvfs_fuse::fuse_api_handle_debug: lookup started req.unique=4 req=Request { unique: 4, uid: 501, gid: 20, pid: 430 } parent="" name="._."
2025-01-16T02:59:13.860211Z ERROR gvfs_fuse::fuse_api_handle_debug: lookup failed req.unique=4 e=Errno(2)
2025-01-16T02:59:13.860371Z DEBUG gvfs_fuse::fuse_api_handle_debug: statfs started req.unique=5 req=Request { unique: 5, uid: 501, gid: 20, pid: 430 } filename=""
2025-01-16T02:59:13.860382Z DEBUG gvfs_fuse::fuse_api_handle_debug: statfs completed req.unique=5 reply=ReplyStatFs { blocks: 1000000, bfree: 1000000, bavail: 1000000, files: 1000000, ffree: 1000000, bsize: 4096, namelen: 255, frsize: 4096 }

...

2025-01-16T02:59:14.840096Z DEBUG gvfs_fuse::fuse_api_handle_debug: setattr started req.unique=2 req=Request { unique: 2, uid: 501, gid: 20, pid: 22343 } filename="test_create" fh=Some(1) set_attr=SetAttr { mode: None, uid: None, gid: None, size: Some(0), lock_owner: None, atime: None, mtime: None, ctime: None, crtime: None, chgtime: None, bkuptime: None, flags: None }
2025-01-16T02:59:14.840243Z DEBUG gvfs_fuse::fuse_api_handle_debug: setattr completed req.unique=2 reply=ttl: 1s, FileAttr: { ino: 10000, size: 0, blocks: 0, atime: "2025-01-16 02:59:14.840213", mtime: "2025-01-16 02:59:14.840213", ctime: "2025-01-16 02:59:14.840213", crtime: "2025-01-16 02:59:14.840213", kind: RegularFile, perm: 600, nlink: 1, uid: 501, gid: 20, rdev: 0, flags: 0, blksize: 8192 }

...

@unknowntpo unknowntpo force-pushed the feat-fuse-debug-log branch 2 times, most recently from 9ae9ea0 to 3574bce Compare December 19, 2024 22:48
@unknowntpo unknowntpo marked this pull request as ready for review December 19, 2024 22:52
Copy link
Contributor

@diqiu50 diqiu50 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally, we need to verify the log format to see if it meets expectations. This needs to be validated in the #5886, and you can wait for it to be merged.

}

impl<T: RawFileSystem> Filesystem for FuseApiHandleDebug<T> {
async fn init(&self, req: Request) -> fuse3::Result<ReplyInit> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to implement all interfaces of the Filesystem. If they are not implemented yet, an error log should be recorded.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you implement all the Filesystem interfaces?

@diqiu50
Copy link
Contributor

diqiu50 commented Dec 20, 2024

Please refer to other PRs for the format of PR titles and descriptions.

@unknowntpo unknowntpo changed the title Feat fuse debug log [#5873] feat(gvfs-fuse): add debug log for FuseApiHandle Dec 20, 2024
@unknowntpo
Copy link
Contributor Author

unknowntpo commented Dec 26, 2024

Finally, we need to verify the log format to see if it meets expectations. This needs to be validated in the #5886, and you can wait for it to be merged.

Since #5886 is done, I'll continue on my work.

@unknowntpo
Copy link
Contributor Author

close and reopen to run workflow

@unknowntpo unknowntpo closed this Dec 29, 2024
@unknowntpo unknowntpo reopened this Dec 29, 2024
@xunliu
Copy link
Member

xunliu commented Dec 30, 2024

@diqiu50 Please help review this PR, Thanks.

Copy link
Contributor

@diqiu50 diqiu50 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, there is no issue. The readability of the logs needs to be improved and made more concise. Unimportant information can be ignored.

Implement a few methods for printing commonly used structures, without having to print them in the struct format

@unknowntpo unknowntpo force-pushed the feat-fuse-debug-log branch from 1d9ff8a to d619db0 Compare January 3, 2025 02:39
@diqiu50
Copy link
Contributor

diqiu50 commented Jan 6, 2025

@unknowntpo All the code are merged to the main brach. you need to merge the pr to main

@unknowntpo
Copy link
Contributor Author

@diqiu50 Okay, (I'm still working this PR)

@unknowntpo unknowntpo force-pushed the feat-fuse-debug-log branch 2 times, most recently from d4627de to ec48523 Compare January 7, 2025 23:14
@unknowntpo unknowntpo changed the base branch from branch-gvfs-fuse-dev to main January 7, 2025 23:17
@unknowntpo unknowntpo force-pushed the feat-fuse-debug-log branch 2 times, most recently from 479e7be to 87e01ff Compare January 10, 2025 22:57
@unknowntpo
Copy link
Contributor Author

Note that I use tracing::debug, tracing::error with structure logging to format the message in key value pair format, so we don't need to control format manually.

e.g.

    debug!(req.unique, ?req, parent = ?parent_stat.name, ?name, "lookup started");

@unknowntpo
Copy link
Contributor Author

@diqiu50 Done, please take a look.

@unknowntpo unknowntpo force-pushed the feat-fuse-debug-log branch from 15ce08e to 256f49f Compare March 4, 2025 04:08
}
}
}};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between the macro of log_readdirplus and log_readdir, I think you can make a macro to instead them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The format function and return type is different (for readdir, we need ReplyDirectory, for readdirplus, we need ReplyDirectoryPlus`), if I make them use the same macro:

/// Log the result for readdir operations
macro_rules! log_readdir {
    ($method_call:expr, $req:ident, $reply_type:ident) => {{
        match $method_call.await {
            Ok(mut reply_dir) => {
                let mut entries = Vec::new();

                while let Some(entry_result) = reply_dir.entries.next().await {
                    match entry_result {
                        Ok(entry) => {
                            entries.push(entry);
                        }
                        Err(e) => {
                            return Err(e.into());
                        }
                    }
                }

                let format_fn = if stringify!($reply_type) == "ReplyDirectory" {
                    directory_entry_to_desc_str
                } else {
                    directory_entry_plus_to_desc_str
                };

                let entries_info = format!(
                    "[{}]",
                    entries
                        .iter()
                        .map(|entry| format_fn(entry))
                        .collect::<Vec<String>>()
                        .join(", ")
                );

                debug!($req.unique, entries = entries_info, "READDIR completed");

                if stringify!($reply_type) == "ReplyDirectory" {
                    Ok(ReplyDirectory {
                        entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
                    })
                } else {
                    Ok(ReplyDirectoryPlus {
                        entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
                    })
                }
            }
            Err(e) => {
                error!($req.unique, ?e, "READDIR failed");
                Err(e)
            }
        }
    }};
}

In readdir:

        log_readdir!(
            self.inner.readdir(req, parent, fh, offset),
            req,
            ReplyDirectory
        )

In readdirplus:

log_readdir!(
            self.inner.readdirplus(req, parent, fh, offset, lock_owner),
            req,
            ReplyDirectoryPlus
        )

I got mismatched type error:

   --> src/fuse_api_handle_debug.rs:134:24
    |
134 |                       Ok(ReplyDirectoryPlus {
    |  _____________________--_^
    | |                     |
    | |                     arguments to this enum variant are incorrect
135 | |                         entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
136 | |                     })
    | |_____________________^ expected `ReplyDirectory<Pin<Box<...>>>`, found `ReplyDirectoryPlus<Pin<Box<...>>>`
...
795 | /         log_readdir!(
796 | |             self.inner.readdir(req, parent, fh, offset),
797 | |             req,
798 | |             ReplyDirectory
799 | |         )
    | |_________- in this macro invocation
    |
    = note: expected struct `fuse3::raw::reply::ReplyDirectory<Pin<Box<dyn Stream<Item = std::result::Result<fuse3::raw::reply::DirectoryEntry, Errno>> + std::marker::Send>>>`
               found struct `fuse3::raw::reply::ReplyDirectoryPlus<Pin<Box<dyn Stream<Item = std::result::Result<fuse3::raw::reply::DirectoryEntry, _>> + std::marker::Send>>>`
help: the type constructed contains `fuse3::raw::reply::ReplyDirectoryPlus<Pin<Box<dyn Stream<Item = std::result::Result<fuse3::raw::reply::DirectoryEntry, _>> + std::marker::Send>>>` due to the type of the argument passed
   --> src/fuse_api_handle_debug.rs:134:21
    |
134 |                        Ok(ReplyDirectoryPlus {
    |   _____________________^  -
    |  |________________________|
135 | ||                         entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
136 | ||                     })
    | ||_____________________-^
    | |______________________|
    |                        this argument influences the type of `Ok`
...
795 |  /         log_readdir!(
796 |  |             self.inner.readdir(req, parent, fh, offset),
797 |  |             req,
798 |  |             ReplyDirectory
799 |  |         )
    |  |_________- in this macro invocation
note: tuple variant defined here
   --> /Users/unknowntpo/.rustup/toolchains/1.82.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:531:5
    |
531 |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^
    = note: this error originates in the macro `log_readdir` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: `if` and `else` have incompatible types
   --> src/fuse_api_handle_debug.rs:115:21
    |
112 |                   let format_fn = if stringify!($reply_type) == "ReplyDirectory" {
    |  _________________________________-
113 | |                     directory_entry_to_desc_str
    | |                     --------------------------- expected because of this
114 | |                 } else {
115 | |                     directory_entry_plus_to_desc_str
    | |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `fuse3::raw::reply::DirectoryEntry`, found `DirectoryEntryPlus`
116 | |                 };
    | |_________________- `if` and `else` have incompatible types
...
885 | /         log_readdir!(
886 | |             self.inner.readdirplus(req, parent, fh, offset, lock_owner),
887 | |             req,
888 | |             ReplyDirectoryPlus
889 | |         )
    | |_________- in this macro invocation
    |
    = note: expected fn item `for<'a> fn(&'a fuse3::raw::reply::DirectoryEntry) -> std::string::String {directory_entry_to_desc_str}`
               found fn item `for<'a> fn(&'a fuse3::raw::reply::DirectoryEntryPlus) -> std::string::String {directory_entry_plus_to_desc_str}`
    = note: this error originates in the macro `log_readdir` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0271]: type mismatch resolving `<Pin<Box<dyn Stream<Item = Result<DirectoryEntryPlus, _>> + Send>> as Stream>::Item == Result<DirectoryEntry, Errno>`
   --> src/fuse_api_handle_debug.rs:131:34
    |
131 |                           entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<DirectoryEntry, Errno>`, found `Result<DirectoryEntryPlus, _>`
...
885 | /         log_readdir!(
886 | |             self.inner.readdirplus(req, parent, fh, offset, lock_owner),
887 | |             req,
888 | |             ReplyDirectoryPlus
889 | |         )
    | |_________- in this macro invocation
    |
    = note: expected enum `std::result::Result<fuse3::raw::reply::DirectoryEntry, Errno>`
               found enum `std::result::Result<fuse3::raw::reply::DirectoryEntryPlus, _>`
note: required by a bound in `fuse3::raw::reply::ReplyDirectory`
   --> /Users/unknowntpo/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fuse3-0.8.1/src/raw/reply.rs:253:37
    |
253 | pub struct ReplyDirectory<S: Stream<Item = Result<DirectoryEntry>>> {
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ReplyDirectory`
    = note: this error originates in the macro `log_readdir` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
   --> src/fuse_api_handle_debug.rs:130:24
    |
130 |                       Ok(ReplyDirectory {
    |  _____________________--_^
    | |                     |
    | |                     arguments to this enum variant are incorrect
131 | |                         entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
132 | |                     })
    | |_____________________^ expected `ReplyDirectoryPlus<Pin<Box<...>>>`, found `ReplyDirectory<Pin<Box<...>>>`
...
885 | /         log_readdir!(
886 | |             self.inner.readdirplus(req, parent, fh, offset, lock_owner),
887 | |             req,
888 | |             ReplyDirectoryPlus
889 | |         )
    | |_________- in this macro invocation
    |
    = note: expected struct `fuse3::raw::reply::ReplyDirectoryPlus<Pin<Box<dyn Stream<Item = std::result::Result<fuse3::raw::reply::DirectoryEntryPlus, Errno>> + std::marker::Send>>>`
               found struct `fuse3::raw::reply::ReplyDirectory<Pin<Box<dyn Stream<Item = std::result::Result<fuse3::raw::reply::DirectoryEntryPlus, _>> + std::marker::Send>>>`
help: the type constructed contains `fuse3::raw::reply::ReplyDirectory<Pin<Box<dyn Stream<Item = std::result::Result<fuse3::raw::reply::DirectoryEntryPlus, _>> + std::marker::Send>>>` due to the type of the argument passed
   --> src/fuse_api_handle_debug.rs:130:21
    |
130 |                        Ok(ReplyDirectory {
    |   _____________________^  -
    |  |________________________|
131 | ||                         entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
132 | ||                     })
    | ||_____________________-^
    | |______________________|
    |                        this argument influences the type of `Ok`
...
885 |  /         log_readdir!(
886 |  |             self.inner.readdirplus(req, parent, fh, offset, lock_owner),
887 |  |             req,
888 |  |             ReplyDirectoryPlus
889 |  |         )
    |  |_________- in this macro invocation
note: tuple variant defined here
   --> /Users/unknowntpo/.rustup/toolchains/1.82.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:531:5
    |
531 |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^
    = note: this error originates in the macro `log_readdir` (in Nightly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try using this macro, it's ok:

/// Log the result for readdir operations
macro_rules! log_readdir {
    ($method_call:expr, $req:ident, $entry_to_desc_str:expr, $reply_type:ident) => {{
        match $method_call.await {
            Ok(mut reply_dir) => {
                let mut entries = Vec::new();

                while let Some(entry_result) = reply_dir.entries.next().await {
                    match entry_result {
                        Ok(entry) => {
                            entries.push(entry);
                        }
                        Err(e) => {
                            return Err(e.into());
                        }
                    }
                }

                let entries_info = format!(
                    "[{}]",
                    entries
                        .iter()
                        .map($entry_to_desc_str)
                        .collect::<Vec<String>>()
                        .join(", ")
                );

                debug!($req.unique, entries = entries_info, "READDIR operation completed");

                Ok($reply_type {
                    entries: stream::iter(entries.into_iter().map(Ok)).boxed(),
                })
            }
            Err(e) => {
                error!($req.unique, ?e, "READDIR operation failed");
                Err(e)
            }
        }
    }};
}

fn directory_entry_plus_to_desc_str(entry: &DirectoryEntryPlus) -> String {
let mut output = String::new();
write!(output, "{{ inode: {}, generation: {}, kind: {:?}, name: {}, offset: {}, attr: {}, entry_ttl: {:?}, attr_ttl: {:?} }}", entry.inode, entry.generation, entry.kind, entry.name.to_string_lossy(), entry.offset, file_attr_to_desc_str(&entry.attr), entry.entry_ttl, entry.attr_ttl).unwrap();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is too long

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I've split the code to multi lines.

}

async fn lookup(&self, req: Request, parent: Inode, name: &OsStr) -> fuse3::Result<ReplyEntry> {
let parent_path_name = self.inner.get_file_path(parent).await?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The get file path logic should not return an error. You need to wrap a function in this class so that if self.inner.get_file_path returns an error, this function returns an empty string ("").

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has this issue been changed?

@@ -193,6 +213,33 @@ fn main() -> Result<(), i32> {
path.to_string_lossy().to_string()
};

if env::var("RUST_LOG").is_ok() {
init_tracing_subscriber(LevelFilter::INFO, "");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not override the logging behavior controlled by RUST_LOG.

app_config.fuse.fuse_debug = debug > 0 || app_config.fuse.fuse_debug;
match debug {
0 => {
init_tracing_subscriber(LevelFilter::INFO, "");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The level 0 is default. same as using RUST_LOG

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What needs to be done here:
1. RUST_LOG should control the global logging behavior. We should not override RUST_LOG.
2. When the parameter debug != 0:
• If RUST_LOG is set, use its value and append gvfs_fuse::fuse_api_handle_debug=debug without overriding RUST_LOG.
• Example: If RUST_LOG=trace, keep the trace level and just enable FuseApiHandleDebug. If RUST_LOG=info, set gvfs_fuse::fuse_api_handle_debug=debug along with the original RUST_LOG setting, ensuring that FuseApiHandleDebug is enabled.

This ensures that RUST_LOG’s original behavior is preserved while dynamically enabling FuseApiHandleDebug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@diqiu50

I have a question:

  1. Does your statements implies that:
  • if debug == 0:
    • use RUST_LOG's value as directives.
  • if debug != 0:
    • if RUST_LOG has value, then the directive becomes: <RUST_LOG_value>,gvfs_fuse::fuse_api_handle_debug=debug ?
    • if RUST_LOG is not set, we simply set directives as gvfs_fuse::fuse_api_handle_debug=debug ?

What I not quite sure is:

  1. When the parameter debug != 0:
    • If RUST_LOG is set, use its value and append gvfs_fuse::fuse_api_handle_debug=debug without overriding RUST_LOG.

Does this means that if debug != 0, whatever RUST_LOG value is, we just set gvfs_fuse::fuse_api_handle_debug as debug level ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that if the user sets RUST_LOG='info' and debug=1, the log level is equivalent to RUST_LOG="info, gvfs_fuse=debug".

If RUST_LOG="info, open_dal=debug, s3=debug" and debug=1, the actual effect should be RUST_LOG="info, open_dal=debug, s3=debug, gvfs_fuse=debug".

If RUST_LOG="gvfs_fuse=debug" and debug=1, the actual effect should be RUST_LOG="gvfs_fuse=debug".

If RUST_LOG="gvfs_fuse=trace" and debug=1, the actual effect should be RUST_LOG="gvfs_fuse=trace".

Of course, debug=1 requires enabling FuseApiHandleDebug.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is to say, the default behavior of the Log module remains unchanged. When debug=1, if the log level of gvfs_fuse is higher than debug, gvfs_fuse=debug is appended, and FuseApiHandleDebug is enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the purpose of debug flag is for controlling the debug level of the whole gvfs_fuse package, right ? And for debug=1, we now enable gvfs_fuse::fuse_api_handle_debug=debug.

Copy link
Contributor Author

@unknowntpo unknowntpo Mar 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to list some examples to make sure my understanding is correct:

  1. When debug == 0 t, we use value of RUST_LOG as directives, the actual effect should be RUST_LOG="<original_rust_log_value>".
  2. when debug != 0, we particularly we need to append gvfs_fuse::fuse_api_handle_debug=debug to the value of RUST_LOG, the actual effect should be RUST_LOG="<original_rust_log_value>,gvfs_fuse::fuse_api_handle_debug=debug". This make sure that no matter which level is set by RUST_LOG for gvfs_fuse, gvfs_fuse::fuse_api_handle_debug still has debug level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ask this because at here,

  1. When the parameter debug != 0:
    • If RUST_LOG is set, use its value and append gvfs_fuse::fuse_api_handle_debug=debug without overriding RUST_LOG.

you use the words gvfs_fuse::fuse_api_handle_debug=debug.

but at here,

My point is that if the user sets RUST_LOG='info' and debug=1, the log level is equivalent to RUST_LOG="info, gvfs_fuse=debug".

you use the word gvfs_fuse=debug

you say gvfs_fuse=debug, does it mean the whole gvfs_fuse or just an abbreviation of gvfs_fuse::fuse_api_handle_debug ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the whole gvfs-fuse

@diqiu50
Copy link
Contributor

diqiu50 commented Mar 10, 2025

@unknowntpo Thank you ,this PR is almost ready, just a few minor issues left.
I'm sorry, I have been working on a project with a tight schedule. If the review is not timely, you can @ me on Slack.

@unknowntpo
Copy link
Contributor Author

@unknowntpo Thank you ,this PR is almost ready, just a few minor issues left. I'm sorry, I have been working on a project with a tight schedule. If the review is not timely, you can @ me on Slack.

Really appreciate that you spent time to review my code!
Ok~ I'll mention you in slack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Subtask] Add debug log for FUSE API handling.
3 participants