Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/LogExpert.Configuration/LegacyPreferencesMigrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ private static void MigrateToV1 (Settings settings)
}
#pragma warning restore CS0618
}

}
55 changes: 35 additions & 20 deletions src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public class RolloverFilenameBuilder
#region Fields

private string _condContent;
private Group _condGroup;
private string _currentFileName;

private Group _dateGroup;
Expand All @@ -41,6 +40,7 @@ public class RolloverFilenameBuilder

private bool _hideZeroIndex;
private Group _indexGroup;
private Group _indexPartGroup;
private Regex _regex;

#endregion
Expand Down Expand Up @@ -89,7 +89,7 @@ public void SetFileName (string fileName)
Index = _indexGroup.Value.Length > 0 ? int.Parse(_indexGroup.Value) : 0;
}

_condGroup = match.Groups["cond"];
_indexPartGroup = match.Groups["indexPart"];
}
}

Expand All @@ -116,15 +116,15 @@ public string BuildFileName ()

Comment thread
Hirogen marked this conversation as resolved.
if (_indexGroup != null && _indexGroup.Success)
{
fileName = fileName.Remove(_indexGroup.Index, _indexGroup.Length);
fileName = fileName.Remove(_indexPartGroup.Index, _indexPartGroup.Length);

if (!_hideZeroIndex || Index > 0)
{
var format = "D" + _indexGroup.Length;
fileName = fileName.Insert(_indexGroup.Index, Index.ToString(format));
fileName = fileName.Insert(_indexPartGroup.Index, Index.ToString(format));
if (_hideZeroIndex && _condContent != null)
{
fileName = fileName.Insert(_indexGroup.Index, _condContent);
fileName = fileName.Insert(_indexPartGroup.Index, _condContent);
}
}
}
Expand All @@ -141,14 +141,14 @@ public string BuildFileName ()
private void ParseFormatString (string formatString)
{
var fmt = EscapeNonvarRegions(formatString);
var datePos = formatString.IndexOf("$D(", StringComparison.Ordinal);
var datePos = fmt.IndexOf("$D(", StringComparison.Ordinal);

if (datePos != -1)
{
var endPos = formatString.IndexOf(')', datePos);
var endPos = fmt.IndexOf(')', datePos);
if (endPos != -1)
{
_dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3)
_dateTimeFormat = fmt.Substring(datePos + 3, endPos - datePos - 3)
.ToUpperInvariant()
.Replace('D', 'd')
.Replace('Y', 'y');
Expand Down Expand Up @@ -176,12 +176,17 @@ private void ParseFormatString (string formatString)
}
}

fmt = fmt.Replace("*", ".*", StringComparison.Ordinal);
fmt = fmt.Replace("*", ".*?", StringComparison.Ordinal);
Comment thread
Hirogen marked this conversation as resolved.
_hideZeroIndex = fmt.Contains("$J", StringComparison.Ordinal);
fmt = fmt.Replace("$I", "(?'index'[\\d]+)", StringComparison.Ordinal);
fmt = fmt.Replace("$J", "(?'index'[\\d]*)", StringComparison.Ordinal);

_regex = new Regex(fmt);
const string indexPattern = "(?'indexPart'(?'index'[\\d]+))";
const string hiddenZeroIndexPattern = "(?'indexPart'(?'index'[\\d]*))";
var conditionalIndexPattern = _condContent != null
? $"(?'indexPart'(?:{Regex.Escape(_condContent)}(?'index'[\\d]+)|(?'index')))"
: hiddenZeroIndexPattern;
fmt = fmt.Replace("$I", indexPattern, StringComparison.Ordinal);
fmt = fmt.Replace("$J", conditionalIndexPattern, StringComparison.Ordinal);

_regex = new Regex(fmt + @"\z");
Comment thread
Hirogen marked this conversation as resolved.
}

private string EscapeNonvarRegions (string formatString)
Expand All @@ -199,17 +204,15 @@ private string EscapeNonvarRegions (string formatString)
case 0: // looking for $
if (fmt[i] == '$')
{
_ = result.Append(Regex.Escape(segment.ToString()));
segment = new StringBuilder();
AppendEscapedSegment(result, segment);
state = 1;
}

_ = segment.Append(fmt[i]);
break;
case 1: // the char behind $
_ = segment.Append(fmt[i]);
_ = result.Append(segment);
segment = new StringBuilder();
AppendSegment(result, segment);
state = 2;
break;
case 2: // checking if ( or other char
Expand All @@ -229,18 +232,30 @@ private string EscapeNonvarRegions (string formatString)
_ = segment.Append(fmt[i]);
if (fmt[i] == ')')
{
_ = result.Append(segment);
segment = new StringBuilder();
AppendSegment(result, segment);
state = 0;
}

break;
}
}

AppendEscapedSegment(result, segment);
fmt = result.ToString().Replace('\xFFFD', '*');
return fmt;
}

private static void AppendEscapedSegment (StringBuilder result, StringBuilder segment)
{
_ = result.Append(Regex.Escape(segment.ToString()));
_ = segment.Clear();
}

private static void AppendSegment (StringBuilder result, StringBuilder segment)
{
_ = result.Append(segment);
_ = segment.Clear();
}

#endregion
}
}
12 changes: 8 additions & 4 deletions src/LogExpert.Resources/Resources.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1680,12 +1680,16 @@ Ein ausgewähltes Tool erscheint in der Iconbar. Alle anderen verfügbaren Tools
<value>Muster syntax:

* = alle Zeichen (wildcard)
$D(&amp;lt;date&amp;gt;) = Datumsmuster
$D(&lt;date&gt;) = Datumsmuster
$I = Dateiindexnummer
$J = Dateiindexnummer, versteckt wenn 09
$J(&amp;lt;prefix&amp;gt;) = Wie $J, jedoch wird ein &amp;lt;prefix&amp;gt; hinzugefügt when es nicht 0 ist
$J = Dateiindexnummer, versteckt wenn null
$J(&lt;prefix&gt;) = Wie $J, jedoch wird ein &lt;prefix&gt; hinzugefügt wenn es nicht 0 ist

&amp;lt;date&amp;gt;:
Beispiele:
*$J(.) → app.log, app.log.1, app.log.2
*$J(.).log → app.log, app.1.log, app.2.log

&lt;date&gt;:
DD = Tag
MM = Monat
YY[YY] = Jahr
Expand Down
10 changes: 7 additions & 3 deletions src/LogExpert.Resources/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1743,12 +1743,16 @@ Checked tools will appear in the icon bar. All other tools are available in the
<value>Pattern syntax:

* = any characters (wildcard)
$D(&amp;lt;date&amp;gt;) = Date pattern
$D(&lt;date&gt;) = Date pattern
$I = File index number
$J = File index number, hidden when zero
$J(&amp;lt;prefix&amp;gt;) = Like $J, but adding &amp;lt;prefix&amp;gt; when non-zero
$J(&lt;prefix&gt;) = Like $J, but adding &lt;prefix&gt; when non-zero

&amp;lt;date&amp;gt;:
Examples:
*$J(.) → app.log, app.log.1, app.log.2
*$J(.).log → app.log, app.1.log, app.2.log

&lt;date&gt;:
DD = day
MM = month
YY[YY] = year
Expand Down
4 changes: 4 additions & 0 deletions src/LogExpert.Resources/Resources.zh-CN.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1554,6 +1554,10 @@ $I = 文件索引编号
$J = 文件索引编号,为零时隐藏
$J(&lt;前缀&gt;) = 类似 $J,但在非零时添加 &lt;前缀&gt;

示例:
*$J(.) → app.log, app.log.1, app.log.2
*$J(.).log → app.log, app.1.log, app.2.log

&lt;日期&gt;:
DD = 日
MM = 月
Expand Down
6 changes: 6 additions & 0 deletions src/LogExpert.Tests/LogExpert.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@
<Content Include="TestData\app.log.1">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestData\app.1.log">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestData\app.2.log">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Update="TestData\organizations-1000.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
29 changes: 28 additions & 1 deletion src/LogExpert.Tests/RollingNameTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public void TestFilename1(string expectedResult, string formatString)
[TestCase("engine.log", "engine1.log","engine$J.log")]
[TestCase("engine1.log", "engine2.log","engine$J.log")]
[TestCase("engine.log", "engine.log.1","*$J(.)")]
[TestCase("engine.log", "engine.1.log", "*$J(.).log")]
[TestCase("engine.log.1", "engine.log.2", "*$J(.)")]
[TestCase("engine.1.log", "engine.2.log", "*$J(.).log")]
[TestCase("engine1.log", "engine2.log", "*$I.log")]
[TestCase("engine_2010-06-12.1.log", "engine_2010-06-12.2.log", "*$D(yyyy-MM-dd)$J(.).log")]
[TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")]
Comment thread
Hirogen marked this conversation as resolved.
Comment thread
Hirogen marked this conversation as resolved.
public void TestFilenameAnd1(string fileName, string expectedResult, string formatString)
{
Expand All @@ -45,6 +50,7 @@ public void TestFilenameAnd1(string fileName, string expectedResult, string form
[Test]
[TestCase("engine.log", "engine.log.2","*$J(.)")]
[TestCase("engine.log", "engine.log.2","*.log$J(.)")]
[TestCase("engine.log", "engine.2.log", "*$J(.).log")]
public void TestFilenameAnd2(string fileName, string expectedResult, string formatString)
{
RolloverFilenameBuilder fnb = new(formatString);
Expand All @@ -54,6 +60,27 @@ public void TestFilenameAnd2(string fileName, string expectedResult, string form
Assert.That(name, Is.EqualTo(expectedResult));
}

[Test]
public void TestFilenameDateAfterRegexMetacharacter ()
{
RolloverFilenameBuilder fnb = new("app.$D(yyyy-MM-dd).log");
fnb.SetFileName("app.2010-06-12.log");

fnb.IncrementDate();

Assert.That(fnb.BuildFileName(), Is.EqualTo("app.2010-06-13.log"));
}

[Test]
public void BuildFileName_FullPathWithNonWildcardMask_IncrementsIndex ()
{
RolloverFilenameBuilder fnb = new("engine$J.log");
fnb.SetFileName(@"C:\logs\engine1.log");

fnb.Index += 1;

Assert.That(fnb.BuildFileName(), Is.EqualTo(@"C:\logs\engine2.log"));
}

[Test]
[TestCase("engine1.log", "engine.log","engine$J.log")]
Expand All @@ -65,4 +92,4 @@ public void TestFilenameMinus1(string fileName, string expectedResult, string fo
var name = fnb.BuildFileName();
Assert.That(name, Is.EqualTo("engine.log"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ public void SingleFileCtor_MultiFileTrue_ExpandsRollover ()
});
}

[Test]
public void SingleFileCtor_MultiFileTrue_LoadsIndexBeforeExtension ()
{
var options = new MultiFileOptions { FormatPattern = "*$J(.).log" };
Comment thread
Hirogen marked this conversation as resolved.
File.Copy(Path.Combine(_testDataDirectory, "app.1.log"), Path.Combine(_testDirectory, "app.1.log"));
File.Copy(Path.Combine(_testDataDirectory, "app.2.log"), Path.Combine(_testDirectory, "app.2.log"));
using var reader = CreateSingleFileReader(multiFile: true, options);

reader.ReadFiles();

Assert.Multiple(() =>
{
Assert.That(reader.IsMultiFile, Is.True);
Assert.That(reader.GetLogFileInfoList().Select(file => Path.GetFileName(file.FullName)),
Is.EqualTo(new[] { "app.2.log", "app.1.log", "app.log" }));
});
}

[Test]
public void MultiFileCtor_AlwaysMultiFile ()
{
Expand All @@ -91,15 +109,15 @@ public void MultiFileCtor_AlwaysMultiFile ()
});
}

private LogfileReader CreateSingleFileReader (bool multiFile)
private LogfileReader CreateSingleFileReader (bool multiFile, MultiFileOptions? options = null)
{
return new LogfileReader(
_logFile,
new EncodingOptions { Encoding = Encoding.UTF8 },
Comment thread
Hirogen marked this conversation as resolved.
multiFile,
bufferCount: 40,
linesPerBuffer: 50,
new MultiFileOptions(),
options ?? new MultiFileOptions(),
ReaderType.System,
PluginRegistry.PluginRegistry.Instance,
maximumLineLength: 500,
Expand Down
1 change: 1 addition & 0 deletions src/LogExpert.Tests/TestData/app.1.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app.1.log
1 change: 1 addition & 0 deletions src/LogExpert.Tests/TestData/app.2.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app.2.log

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions src/LogExpert.UI/Dialogs/MultiFileMaskDialog.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading