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

RotatingFileAppender #858

Open
CfirTsabari opened this issue Jul 28, 2020 · 13 comments · May be fixed by #2497 or #2904
Open

RotatingFileAppender #858

CfirTsabari opened this issue Jul 28, 2020 · 13 comments · May be fixed by #2497 or #2904
Labels
crate/appender Related to the `tracing-appender` crate. kind/feature New feature or request

Comments

@CfirTsabari
Copy link

Is your feature request related to a problem? Please describe.
I want to supply logs to the application that I write by using tracing, tracing-subscriber, and tracing-appender, but it's crucial to enforce small log files and a boundary to the total size of all the logs.
Small files - since its easier to read.
Total size - since disk space might be limited.

Describe the solution you'd like
I propose creating another Rotation
that will be based on size instead of time.
this rotation will be a configuration of two parameters:

  • The max size of each file
  • The maximum number of logs files to keep.

This rotation will create a new file every time the current file exceeds the allowed size and will bump all current old files indexes. In case the maximum number of files is reached it will delete the oldest file.

Describe alternatives you've considered
The current time-based rotation is not enough since it might vary a lot even in the apps.

Additional context
Python RotatingFileHandler

@hawkw hawkw transferred this issue from tokio-rs/tokio Jul 28, 2020
@hawkw hawkw added crate/appender Related to the `tracing-appender` crate. kind/feature New feature or request labels Jul 28, 2020
@hawkw
Copy link
Member

hawkw commented Jul 28, 2020

I transferred this to tokio-rs/tracing. Also, tagging @zekisherif, since it's related to the tracing-appender crate.

@CfirTsabari
Copy link
Author

I am intending on creating a PR for this.
I do wonder how exactly to design it.
my few first thought are:

  1. Change RotationKind to include parameters and different variants something like
#[derive(Clone, Eq, PartialEq, Debug)]
enum RotationKind {
    TimeBased(TimeBasedRotationKind),
    SizeBased(u64-max size),
}
enum TimeBasedRotationKind {
    Minutely,
    Hourly,
    Daily,
    Never,
}
  1. Change InnerAppender:
  • Move all time-based rotation to another struct, and leave only the base file rotation code.
  • create another struct for size-based rotation
  • Add another option to control the number of file backups to keep.

@zekisherif
Copy link
Contributor

PR #828 will likely change the public api a bit so we'll have to keep this into consideration for any work done here.

  1. Changing the RotationKind will be a breaking change as RollingFileAppender is public and people may be using it directly instead of one of the helper functions. Though I agree it is the correct way to define RotationKind as you've done here and better for extendible.

  2. Instead of using InnerAppender struct directly as we do today. RollingFileAppender should replace inner with a trait (InnerFileRotator?, even InnerAppender would work, we'd just have to move all implementations out of it) which you then can make structs which implement this trait and abstract the implementation of size-based and time based rotation.

Example trait definition which will look very similar to the current impl of InnerAppender. I don't think much has to really change here except the naming of the methods. But mayber there is something I'm overlooking here.

pub(crate) trait InnerAppender {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize>; // Handles writing to the log file
     fn refresh(&mut self); // Handles creating a new file to write to and modifying existing file names in the case of size based.
     fn should_rollover(&self) -> bool // Determines whether a rollover should occur or not based of the rotation criteria.
}

I don't envision many issues with what you are proposing outside of the changes to the api which are breaking changes.

@hawkw
Copy link
Member

hawkw commented Jul 29, 2020

@zekisherif

  1. Changing the RotationKind will be a breaking change as RollingFileAppender is public and people may be using it directly instead of one of the helper functions.

I don't think this a breaking change? The public Rotation type is represented internally by a RotationKind. We can change RotationKind as much as we like, as it is private. We would just add new constructors to Rotation for constructing a file-size based rotation, which would internally use the size-based RotationKind.

@CfirTsabari

#[derive(Clone, Eq, PartialEq, Debug)]
enum RotationKind {
    TimeBased(TimeBasedRotationKind),
    SizeBased(u64-max size),
}
enum TimeBasedRotationKind {
    Minutely,
    Hourly,
    Daily,
    Never,
}

IMO, it would probably be simpler to just write

#[derive(Clone, Eq, PartialEq, Debug)]
 enum RotationKind {
     Minutely,
     Hourly,
     Daily,
     Never,
     MaxSize(u64),
}

Unless I'm missing something? What does the inner enum get us here?

@zekisherif
Copy link
Contributor

@zekisherif

  1. Changing the RotationKind will be a breaking change as RollingFileAppender is public and people may be using it directly instead of one of the helper functions.

I don't think this a breaking change? The public Rotation type is represented internally by a RotationKind. We can change RotationKind as much as we like, as it is private. We would just add new constructors to Rotation for constructing a file-size based rotation, which would internally use the size-based RotationKind.

You're right. For some reason I thought RotationKind was public. It won't be a breaking change.

@CfirTsabari
Copy link
Author

CfirTsabari commented Jul 30, 2020

but RotationKind is not public, so it won't break the API.
sorry just saw that @hawkw already said that.

@CfirTsabari
Copy link
Author

@hawkw but grouping the time base rotation will enable easier group handling.
I do have a starting draft on the main design I thought about(that doesn't build yet).
Should I open a draft PR?

@hawkw
Copy link
Member

hawkw commented Jul 30, 2020

Should I open a draft PR?

If you like, please do!

CfirTsabari added a commit to CfirTsabari/tracing that referenced this issue Jul 30, 2020
also need to change this comment to explain the new design.
Left a few unimplemented but the main skeleton is ready.
Need to add documentation.
Addressing  tokio-rs#858

API Breaking changes:
Rotation consts (MINUTELY, HOURLY, DAILY) are now functions.
@CfirTsabari
Copy link
Author

So I just created a draft PR with the complete skeleton(and it does build).
I think I should do some work on the weekend.

CfirTsabari added a commit to CfirTsabari/tracing that referenced this issue Jul 31, 2020
also need to change this comment to explain the new design.
Left a few unimplemented but the main skeleton is ready.
Need to add documentation.
Addressing  tokio-rs#858
CfirTsabari added a commit to CfirTsabari/tracing that referenced this issue Jul 31, 2020
also need to change this comment to explain the new design.
Need to add documentation.
Addressing  tokio-rs#858
CfirTsabari added a commit to CfirTsabari/tracing that referenced this issue Aug 1, 2020
Motivation
Adding an appender with max size per log file and max number of log files.
Addressing  tokio-rs#858

Solution
Adding an appender very similar to the `RollingFileAppender`,
that will base the rotation on size of log file and number of log files.
@CfirTsabari
Copy link
Author

The PR is ready for review :-)

@brianjcj
Copy link

brianjcj commented Mar 3, 2021

actually we will need specify time and size at the same time. Whenever size limit or time limit exceed, the log will be rotated. That is the usual way log rotation being implemented in other languages and system.

@kevinhoffman
Copy link

@brianjcj - we had a similar need, with rotation conditions based on date/time and/or size, also to rotate based on the local time of the system rather than UTC, and to use a "Debian-style" log rotation scheme where the current logfile always has the same name.

Since this had some different design requirements than the RollingFileAppender here in tracing-appender, rather than add so many options/variants to RollingFileAppender here, we found it cleaner just to implement our own and then combine that with NonBlocking, which is working well. We were surprised there didn't seem to be another crate implementing such a thing (at least as far as we could find), so we've published this as the rolling-file crate. All feedback welcome.

@Christoph-AK
Copy link

Until tracing became a necessity for me I loved to use flexi_logger with

flexi_logger::Logger::with(LogSpecification::info())
    .use_windows_line_ending()
    .log_to_file(flexi_logger::FileSpec::default().directory("logs"))
    .duplicate_to_stdout(flexi_logger::Duplicate::Info)
    .append()
    .rotate(
        flexi_logger::Criterion::Size(100 * 1024_u64 * 1024_u64),
        flexi_logger::Naming::Timestamps,
        flexi_logger::Cleanup::KeepCompressedFiles(1000),
    )
    .cleanup_in_background_thread(true)

This enables async file compression, as long as you keep a token alive. Before exiting the program log_handle.shutdown(); needs to be called, which waits for the logging and compression to return from any open tasks.

Is something like this an option for the rolling appender?

CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
@CBenoit CBenoit linked a pull request Mar 4, 2023 that will close this issue
CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Mar 4, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Sep 5, 2023
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
CBenoit added a commit to CBenoit/tracing that referenced this issue Feb 13, 2024
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
@x3ccd4828 x3ccd4828 linked a pull request Mar 7, 2024 that will close this issue
dovahcrow pushed a commit to dovahcrow/tracing that referenced this issue May 11, 2024
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
dovahcrow pushed a commit to dovahcrow/tracing that referenced this issue May 11, 2024
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
dovahcrow pushed a commit to dovahcrow/tracing that referenced this issue Jun 17, 2024
This patch adds size-based rotation to tracing-appender.

In a constraint environment, we should be able to contain the logging
size and period.

Related issues:
- tokio-rs#1940
- tokio-rs#858
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crate/appender Related to the `tracing-appender` crate. kind/feature New feature or request
Projects
None yet
6 participants