-
Notifications
You must be signed in to change notification settings - Fork 33
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
Added {Hour} and {HalfHour} specifiers. #29
Conversation
Great! Thanks for the PR. It may take me a few days to work through it, just letting you know that it hasn't fallen off the radar :-) |
I'll be expecting it ! Thanks a lot. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great. Added a few comments. Thanks!
|
||
// We only take one attempt at it because repeated failures | ||
// to open log files REALLY slow an app down. | ||
_nextCheckpoint = date.AddDays(1); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra newline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still an extra newline hanging around here.
@@ -140,13 +141,13 @@ void OpenFile(DateTime now) | |||
} | |||
catch (DirectoryNotFoundException) { } | |||
|
|||
var latestForThisDate = _roller | |||
var latestForThisDateTime = _roller |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be clearer if we called this latestForThisCheckpoint
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to rename any field or constant.
const string DefaultSeparator = "-"; | ||
|
||
const string MatcherMarkSpecifier = "date"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea pulling these out as constants 👍
Just on the naming, could we perhaps use:
const string SpecifierMatchGroup = "specifier";
const string SequenceNumberMatchGroup" = "sequence";
readonly string _pathTemplate; | ||
readonly Regex _filenameMatcher; | ||
readonly SpecifierTypeEnum _specifierType = SpecifierTypeEnum.None; | ||
// Concret used Date or Hour specifier. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in this comment ("concret") - we could possibly drop the comment since the field names are pretty descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect.
readonly string _pathTemplate; | ||
readonly Regex _filenameMatcher; | ||
readonly SpecifierTypeEnum _specifierType = SpecifierTypeEnum.None; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Carrying both _specifierType
and _usedSpecifier
means the two could (potentially) be out-of-sync. What do you think about getting rid of the enum, and just using e.g. _usedSpecifier == HourSpecifier
etc. as comparisons?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other option that would work really well:
class Specifier
{
public string Name { get; }
public string Token { get; }
public string Format { get; }
public TimeSpan Interval { get; }
Specifier(string name, string format, string interval)
{
Name = name;
Token = "{" + Name + "}";
Format = format;
Interval = interval;
}
public static readonly Specifier Date = new Specifier("Date", "yyyyMMdd", TimeSpan.FromDays(1));
public static readonly Specifier Hour = new Specifier("Hour", "yyyyMMddhh", TimeSpan.FromHours(1));
public static readonly Specifier HalfHour = new Specifier("HalfHour", "yyyyMMddhhmm", TimeSpan.FromMinutes(30));
}
We could then have a field:
readonly Specifier _specifier;
Then, after construction, we could avoid checking the current specifier and just use fields like _specifier.Token
, _specifier.Interval
and so-on.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me it is great to encapsulate the fields in a class.
I didn't want to make so much changes from the original source so the merge should be easier.
Feel free to make any change with which you feel more confortable.
|
||
enum SpecifierTypeEnum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we decide to keep the enum (see comment above), we should drop the Enum
suffix. Just calling it Specifier
would be clear enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to use a class for the specifier. It is more OOP compliant.
} | ||
} | ||
} | ||
|
||
public DateTime GetCurrentCheckpoint(DateTime date) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we call the parameter name instant
or dateTime
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"instant" is nice for me. More descriptive than "datetime" or just "date".
return date.Date; | ||
} | ||
|
||
public DateTime GetNextCheckpoint(DateTime date) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameter naming here also.
Thanks for the replies @jose3m! In the PR workflow, you can push additional changes to your repository and they'll appear here in the PR. (As the code's still on your side, I can't make changes to it "on the way in".) Cheers, |
Hi Nick ! I have just commited the changes we talked about. Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we're getting close. Mostly stylistic feedback. There seem to be a few opportunities to encapsulate more in the Specifier
class - what do you think? Cheers!
|
||
// We only take one attempt at it because repeated failures | ||
// to open log files REALLY slow an app down. | ||
_nextCheckpoint = date.AddDays(1); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still an extra newline hanging around here.
|
||
namespace Serilog.Sinks.RollingFile.Sinks.RollingFile | ||
{ | ||
internal class Specifier |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick - the codebase doesn't use explicit internal
modifiers on types or private
modifiers on members.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
internal static readonly TimeSpan HourInterval = TimeSpan.FromHours(1); | ||
internal static readonly TimeSpan HalfHourInterval = TimeSpan.FromMinutes(30); | ||
|
||
//------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//----
and whitespace can probably go, not used through the rest of the Serilog codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
public string Format { get; } | ||
public TimeSpan Interval { get; } | ||
|
||
Specifier(SpecifierType type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like SpecifierType
only exists to use in this constructor. If the ctor took name, format and interval, we could get rid of SpecifierType
and save quite a few LOC (including the switch statement).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SpecifierType is used also in the getCurrentCheckpoint function. I'll remove this enum and I'll use the token to identify what kind of specifier is the instance.
{ | ||
internal const string OldStyleDateToken = "{0}"; | ||
|
||
internal const string DateToken = "{Date}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be tidier to expose the specifiers instead, so these can just be Specifier.Date.Token
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I change it.
throw new ArgumentException("The old-style date specifier " + OldStyleDateSpecifier + | ||
" is no longer supported, instead please use " + DateSpecifier); | ||
|
||
if (pathTemplate.Contains(Specifier.OldStyleDateToken)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The next 13 lines could be encapsulated in Specifier.TryGetSpecifier(pathTemplate, out specifier)
. If it returns false, _specifier
can be set to Specifier.Date
and the path modified. TryGetSpecifier()
could then also be used to avoid the chain of three if
statements to decide whether it's included in the directory name.
@@ -49,28 +65,42 @@ public TemplatedPathRoller(string pathTemplate) | |||
|
|||
directory = Path.GetFullPath(directory); | |||
|
|||
if (directory.Contains(DateSpecifier)) | |||
if (directory.Contains(Specifier.DateToken)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
E.g.
Specifier directorySpecifier;
if (Specifier.TryGetSpecifier(directory, out directorySpecifier)
{
throw new ArgumentException($"The {directorySpecifer.Token} specifier cannot form part of the directory name.");
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
@@ -81,12 +111,14 @@ public TemplatedPathRoller(string pathTemplate) | |||
|
|||
public void GetLogFilePath(DateTime date, int sequenceNumber, out string path) | |||
{ | |||
var tok = date.ToString(DateFormat, CultureInfo.InvariantCulture); | |||
DateTime currentCheckpoint = GetCurrentCheckpoint(date); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick, can use var
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Hi Nick ! Even more encapsulating, it could be created a new static method inside Specifier containing all validations on the TemplatedPathRoller constructor, from line 42 to line 72. Specifier.ValidateTemplate(string pathTemplate, out string directory) Regards |
Thanks Jose! I will merge it now and have a tinker with the encapsulated validation myself. Cheers! |
Thank you very much for your great work ! |
This PR corresponds to the issue #22 .
This development adds two new specifiers to the currently admitted {Date}: {Hour} and {HalfHour}
The behaviour is obvius.
Please, feel free to change the token {HalfHour} by the one you consider better (you only have to change the value of the constant TemplatedPathRoller.HalfHourSpecifier).
One thing to have in mind when using it is that the three specifiers shouldn't be used at the same or different time on the same path as it could be confusing with an unexpected result.
Thanks.
Jose