Skip to content

[core] pipe logging in C++ - #49733

Merged
rynewang merged 10 commits into
ray-project:masterfrom
dentiny:hjiang/pipe-logging
Jan 11, 2025
Merged

[core] pipe logging in C++#49733
rynewang merged 10 commits into
ray-project:masterfrom
dentiny:hjiang/pipe-logging

Conversation

@dentiny

@dentiny dentiny commented Jan 9, 2025

Copy link
Copy Markdown
Contributor

Address @jjyao 's comment: #49548 (comment)

This PR implements the pipe logging in C++, instead of python.
The main motivation for reuse for other languages in the future.

One thing worth noticing is I use two backgrounds for read from pipe and dump to spdlog:

  • The motivation is to avoid any IO operation on read thread, thus blocking write thread due to limited pipe buffer size
  • The overhead of which is extra copy of logging message; we should merge into one thread if performance issue reported

Usage in core worker:

class CoreWorker {
  // Only assigned when rotation is requested; otherwise empty;
  // All handles' termination functors are invoked at core workers' destruction.
  std::vector<RotationFileHandle> rotation_file_handles_;
};

@dentiny
dentiny force-pushed the hjiang/pipe-logging branch from edf17ac to 7a0f7d4 Compare January 9, 2025 09:50
@dentiny dentiny added the go add ONLY when ready to merge, run all tests label Jan 9, 2025
@dentiny
dentiny force-pushed the hjiang/pipe-logging branch 2 times, most recently from 1803428 to f6edaff Compare January 9, 2025 09:55
Signed-off-by: dentiny <dentinyhao@gmail.com>
@dentiny
dentiny force-pushed the hjiang/pipe-logging branch from f6edaff to ff714c0 Compare January 9, 2025 10:47
Comment thread src/ray/util/pipe_logger.h Outdated
Comment thread src/ray/util/pipe_logger.h Outdated
struct PipeStreamToken {
// Used to write to.
//
// TODO(hjiang): I will followup with another PR to make a `FD` class, which is not

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what does this mean? Even if a fd as int is copied it does not automatically dup. Can you give an example of how do you plan to have the FD class?

See also: MEMFD_TYPE, INT2FD, FD2INT in compat.h

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you can just use MEMFD_TYPE and don't need the ifdef here

@dentiny dentiny Jan 9, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, I would like to wrap file descriptor in a class, which

  • Disallow copy
  • Allow move, which indicates resource ownership transfer
  • Close fd at dtor

The biggest motivation is to avoid manual dup from unintentional copy.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah we can do it in another pr

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See also: MEMFD_TYPE, INT2FD, FD2INT in compat.h

I leave a TODO for using MEMFD, because we don't have a separate target for compat.h, introducing which means pulling heavy dependencies.

Comment thread src/ray/util/pipe_logger.cc Outdated
Comment thread src/ray/util/tests/linux_test_utils.h Outdated
Comment thread src/ray/util/pipe_logger.h Outdated
Comment thread src/ray/util/pipe_logger.h
Signed-off-by: dentiny <dentinyhao@gmail.com>
Signed-off-by: dentiny <dentinyhao@gmail.com>
@dentiny
dentiny requested a review from rynewang January 9, 2025 19:49
Comment thread src/ray/util/pipe_logger.h Outdated
Comment thread src/ray/util/pipe_logger.h Outdated
struct PipeStreamToken {
// Used to write to.
//
// TODO(hjiang): I will followup with another PR to make a `FD` class, which is not

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah we can do it in another pr

Signed-off-by: dentiny <dentinyhao@gmail.com>
Signed-off-by: dentiny <dentinyhao@gmail.com>
@dentiny
dentiny requested a review from rynewang January 9, 2025 22:42
@dentiny dentiny changed the title pipe logging in C++ [core] pipe logging in C++ Jan 10, 2025
Signed-off-by: dentiny <dentinyhao@gmail.com>
…ang/pipe-logging

Signed-off-by: dentiny <dentinyhao@gmail.com>
@dentiny
dentiny force-pushed the hjiang/pipe-logging branch from 6606812 to 86f0481 Compare January 10, 2025 00:56

@rynewang rynewang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I find this design over engineered:

  1. It provides a on_completion callback which nobody uses other than the unit test.
  2. It spawns 2 threads: 1 to listen the fd and write to a buffer; 1 to dump the buffer content to spdlog. I think 1 thread can already do the work, only on some curated "log stress tests" where the user write megabytes of data to stdout will a single thread solution be blocked by the backend write-to-disk operation. And in this case, even a simple "stdout > 1.log" will block as well so the blocking should be expected by the user anyway.

That said, this PR is delayed for too long. I choose to merge it as long as a future maintainer can find the message in this PR, because its over-engineering is (mostly) contained within the library itself and it's not likely to change dramatically, so the pain is contained.

// Open the file with read-only access
int fd = open(fname.c_str(), O_RDONLY);
RAY_CHECK_GT(fd, 0);
BOOST_SCOPE_EXIT(&fd) { close(fd); }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can use absl::Cleanup ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah I think they are the same thing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

then let's prefer the non-macro one

@rynewang
rynewang merged commit c948741 into ray-project:master Jan 11, 2025
@dentiny

dentiny commented Jan 11, 2025

Copy link
Copy Markdown
Contributor Author

It provides a on_completion callback which nobody uses other than the unit test.

For the callback, I think it's needed in production;
During process termination, we need to make sure all log messages are flushed into disk.

@rynewang

Copy link
Copy Markdown
Contributor

the dtor itself should do the flushing?

@dentiny

dentiny commented Jan 11, 2025

Copy link
Copy Markdown
Contributor Author

the dtor itself should do the flushing?

dtor performs flushing, atexit perform flush synchronization, the callback is needed based on the async logging nature

srinathk10 pushed a commit that referenced this pull request Feb 2, 2025
This PR implements the pipe logging in C++, instead of python.
The main motivation for reuse for other languages in the future.

One thing worth noticing is I use two backgrounds for read from pipe and
dump to spdlog:
- The motivation is to avoid any IO operation on read thread, thus
blocking write thread due to limited pipe buffer size
- The overhead of which is extra copy of logging message; we should
merge into one thread if performance issue reported

Usage in core worker:
```
class CoreWorker {
  // Only assigned when rotation is requested; otherwise empty;
  // All handles' termination functors are invoked at core workers' destruction.
  std::vector<RotationFileHandle> rotation_file_handles_;
};
```

---------

Signed-off-by: dentiny <dentinyhao@gmail.com>
park12sj pushed a commit to park12sj/ray that referenced this pull request Mar 18, 2025
This PR implements the pipe logging in C++, instead of python.
The main motivation for reuse for other languages in the future.

One thing worth noticing is I use two backgrounds for read from pipe and
dump to spdlog:
- The motivation is to avoid any IO operation on read thread, thus
blocking write thread due to limited pipe buffer size
- The overhead of which is extra copy of logging message; we should
merge into one thread if performance issue reported

Usage in core worker:
```
class CoreWorker {
  // Only assigned when rotation is requested; otherwise empty;
  // All handles' termination functors are invoked at core workers' destruction.
  std::vector<RotationFileHandle> rotation_file_handles_;
};
```

---------

Signed-off-by: dentiny <dentinyhao@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-backlog go add ONLY when ready to merge, run all tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants