Skip to content

File retention policy by date/time #90

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

Merged
merged 5 commits into from
Feb 4, 2020
Merged

File retention policy by date/time #90

merged 5 commits into from
Feb 4, 2020

Conversation

thiagosgarcia
Copy link
Contributor

@thiagosgarcia thiagosgarcia commented Mar 14, 2019

Add configuration to discard files older than X time defined by a TimeSpan variable.

As discussed in issue #39, I think (and it did work for me) that would be nice to have a dateTime-driven file retention policy.
There are some security policies that, for example, demands that all log files should be wiped after a few days or weeks. At the same time, you can have as much as possible data in logs, so, for some cases, the strongest rule for deleting log files would be date, not file count or size.

In the example below, files older than 7 days are deleted by RollingFileSink.ApplyRetentionPolicy(_) at a maximum count of 100 files, rolling by day or at a limit of 50MB per file

  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "File",
        "Args": {
          "path": "App_Data\\Logs\\app_.log",
          "rollingInterval": "Day",
          "fileSizeLimitBytes": "52428800",
          "rollOnFileSizeLimit": "true",
          "retainedFileCountLimit": "100",
          "retainedFileTimeLimit": "7.00:00:00", //Deletes files older than 7 days
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
        }
      }
    ]
  },

@thiagosgarcia thiagosgarcia changed the title File retention policy by date File retention policy by date/time Mar 14, 2019
Copy link
Member

@nblumhardt nblumhardt left a comment

Choose a reason for hiding this comment

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

Sorry about the slow response, here! Thanks for taking the time to send this.

It seems like a nice, clean, change; there's a bit to digest. I can see how there could be some 'jitter' around the roll points if events are logged out-of-order and there's a very short/zero retention time; this issue is present with very small rolling sets, too, though.

One glitch is that if the app stops logging, the policy will not be triggered and the old files will be kept - may not be a major problem (the same thing occurs if the app is shut down :-)) but worth considering, perhaps with a note.

If you're keen to push ahead with this one, it'd be great also to include a couple of tests that exercise it.

Thanks again!

@nblumhardt nblumhardt mentioned this pull request Apr 22, 2019
@thiagosgarcia
Copy link
Contributor Author

Thanks a lot for your review @nblumhardt
I'm going to push the suggestions you made as soon as I can.

@thiagosgarcia
Copy link
Contributor Author

thiagosgarcia commented Apr 30, 2019

@nblumhardt, thanks again for the review and suggestions. I pushed the new code including your suggestions, but I just noticed that I didn't updated my forked code with the new FileLifecycleHooks parameter on the constructors. I'm going to fix it later tonight, then I push again.

@thiagosgarcia thiagosgarcia reopened this Apr 30, 2019
@thiagosgarcia
Copy link
Contributor Author

Just rebased my changes onto the upstream, fixed conflicts and ran unit and manual tests here.
If there's any other thoughts, I'll be glad to hear.
Cheers!

…der than X time

Fixed constructors for compatibility; Unified where clause to retain files
Adjust error messages
New test cases
Copy link
Member

@nblumhardt nblumhardt left a comment

Choose a reason for hiding this comment

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

Looking great! Thanks for the update, sorry it's taken so long to get some eyes on this.

Had a couple of points to consider - should be getting down to the last of it now :-)

.Where(n => StringComparer.OrdinalIgnoreCase.Compare(currentFileName, n) != 0)
.Skip(_retainedFileCountLimit.Value - 1)
.Where(n => StringComparer.OrdinalIgnoreCase.Compare(currentFileName, n.Filename) != 0)
.SkipWhile((x, i) => (i < (_retainedFileCountLimit - 1 ?? 0)) &&
Copy link
Member

Choose a reason for hiding this comment

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

The default of 0 for a null _retainedFileCountLimit seems wrong here, since i will never be less than it (null is intended to indicate "no limit").

Could pulling this expression out into a local function (with some locals, or structured return (true|false) make the logic a bit clearer?

Copy link
Contributor Author

@thiagosgarcia thiagosgarcia May 24, 2019

Choose a reason for hiding this comment

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

I put 0 there, thinking that if retainedFileCountLimit got there as null, then I'll ignore this condition. Do you think maybe 31 (the default value) would be better instead (in case of null)?

I'll extract a function to get this piece of code clearer. I also didn't really like it the way it is.

Copy link
Member

Choose a reason for hiding this comment

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

I think it'll be hard to get the logic right here without checking retainedFileCountLimit against null, but guessing this will all come out more clearly with some reorganisation :-)

@thiagosgarcia
Copy link
Contributor Author

No worries =)
Gonna push this changes as soon as I can.

@thiagosgarcia
Copy link
Contributor Author

@nblumhardt I was able to push the requested changes. If there's anything else, please, let me know and I'll correct right away.

I did give some thoughts on that SkipWhile filter, and tried to create a more self-explanatory function, hope it's good to ship now. =)

@iamandymcinnes
Copy link

Just wondered if there is any update on getting this PR merged?

@nblumhardt
Copy link
Member

Thanks for the nudge, @iamandymcinnes - I'm keen to merge this PR, I need to sanity check myself before pushing the button (there's a binary breaking change which might necessitate downstream changes, too), I'll try to loop back around ASAP, if no one else beats me to it :-)

@ericvb
Copy link

ericvb commented Sep 6, 2019

Same question as @iamandymcinnes, what is the status of this PR?

@pnstickne
Copy link

pnstickne commented Oct 31, 2019

Bump. The file-count-only stock retention policy for files is very limiting. Services / programs that restart many times in a short period of time (and create a new file each time without log sharing) run the risk of losing logs.

There is probably further consideration on how to handle 'groups of' log files in general, including PID/AppDomain-time distinction to avoid shared files.

@nblumhardt
Copy link
Member

@pnstickne @ericvb thanks for the bump; sorry again about the delay, @thiagosgarcia - I'll get there! 😅

Paul, check out https://github.com/serilog/serilog-sinks-map as one way to address the file-set-per-PID type scenarios (assuming you've tried and ruled out passing shared: true to your file sink).

@asalhani
Copy link

asalhani commented Feb 3, 2020

@thiagosgarcia Thank you for your effort to include this as a feature.

@nblumhardt Any update on this PR? Any expected time when it will be closed?

@nblumhardt nblumhardt merged commit 00e3e94 into serilog:dev Feb 4, 2020
@nblumhardt
Copy link
Member

Fixed my test breakage locally on the way through the works :-)

@nblumhardt
Copy link
Member

Out in the 5.0-dev build 🎉 - thanks @thiagosgarcia :-)

@thiagosgarcia
Copy link
Contributor Author

Thank you @nblumhardt! If there's anything else I can do, please let me know =)

@ThilinaJ
Copy link

ThilinaJ commented Nov 5, 2020

Hello,
With what release will this feature be released on NuGet?

@abrasat
Copy link

abrasat commented Dec 10, 2021

@thiagosgarcia @nblumhardt
Is this feature already available ? I would like to use serilog to log for lets say 30 days, but the daily files should be split in several files, each of them with a max size of for example 50 MB (yes, my application is logging a lot, especially during commissioning).
It is important that no log data gets lost. Is this behavior possible with the actual serilog file sink? If yes, can you please provide a c# configuration sample for .NET 6? Thanks!

@bartelink
Copy link
Member

@abrasat per https://www.nuget.org/packages/serilog.sinks.file it is released. If you're having trouble configuring it, the best thing to do is to raise an issue on stackoverflow.com tagged serilog showing what you've tried so far. In general, usage issues don't get covered via these GitHub Issues - one glance at the download numbers should convince you that this would never scale.

@Youssef-Ehab77
Copy link

Youssef-Ehab77 commented Oct 4, 2023

Hello,
I used retainedFileTimeLimit: TimeSpan.FromMinutes(10), but I'm facing weird behavior, it deletes the old file once it reaches its fileSizeLimitBytes: 10000 and creates a new file even thought I'm still inside the 10 minutes time frame and my retainedFileCountLimit: 50 and rollingInterval: RollingInterval.Day. But when I make retainedFileTimeLimit: TimeSpan.FromDays(10) it creates a new file once the file size limit exceeds and it doesn't delete the old file.
also posted at: Stack overflow Link
@bartelink Thanks for your comments and help ❤

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.

10 participants