Skip to content

Commit 4ee91ed

Browse files
authored
Logging ordering fixes and feedback (#5398)
1 parent b2f7eec commit 4ee91ed

File tree

25 files changed

+644
-546
lines changed

25 files changed

+644
-546
lines changed

playground/Stress/Stress.ApiService/ConsoleStresser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ public static void Stress()
9797
for (var color = 40; color <= 47; color++)
9898
{
9999
Console.Write("\x1b[" + color + "m"); // Set background color
100-
Console.WriteLine($"This is background color {color}");
101-
Console.Write("\x1b[0m"); // Reset colors to default after each background to maintain readability
100+
Console.Write($"This is background color {color}");
101+
Console.WriteLine("\x1b[0m"); // Reset colors to default after each background to maintain readability
102102
}
103103
Console.Write("\x1b[0m"); // Reset all colors to default at the end
104104

playground/Stress/Stress.ApiService/Program.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,23 @@
2222

2323
app.MapGet("/", () => "Hello world");
2424

25+
app.MapGet("/write-console", () =>
26+
{
27+
for (var i = 0; i < 5000; i++)
28+
{
29+
if (i % 500 == 0)
30+
{
31+
Console.Error.WriteLine($"{i} Error");
32+
}
33+
else
34+
{
35+
Console.Out.WriteLine($"{i} Out");
36+
}
37+
}
38+
39+
return "Console written";
40+
});
41+
2542
app.MapGet("/increment-counter", (TestMetrics metrics) =>
2643
{
2744
metrics.IncrementCounter(1, new TagList([new KeyValuePair<string, object?>("add-tag", "1")]));

src/Aspire.Dashboard/Aspire.Dashboard.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,5 +229,8 @@
229229
<Compile Include="$(SharedDir)TokenGenerator.cs" Link="Utils\TokenGenerator.cs" />
230230
<Compile Include="$(SharedDir)LoggingHelpers.cs" Link="Utils\LoggingHelpers.cs" />
231231
<Compile Include="$(SharedDir)StringUtils.cs" Link="Utils\StringUtils.cs" />
232+
<Compile Include="$(SharedDir)ConsoleLogs\LogEntries.cs" Link="Utils\ConsoleLogs\LogEntries.cs" />
233+
<Compile Include="$(SharedDir)ConsoleLogs\LogEntry.cs" Link="Utils\ConsoleLogs\LogEntry.cs" />
234+
<Compile Include="$(SharedDir)ConsoleLogs\TimestampParser.cs" Link="Utils\ConsoleLogs\TimestampParser.cs" />
232235
</ItemGroup>
233236
</Project>

src/Aspire.Dashboard/Components/Controls/LogViewer.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@namespace Aspire.Dashboard.Components
22
@using Aspire.Dashboard.Model
3+
@using Aspire.Hosting.ConsoleLogs
34
@inject IJSRuntime JS
45
@implements IAsyncDisposable
56

src/Aspire.Dashboard/Components/Controls/LogViewer.razor.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Aspire.Dashboard.Extensions;
99
using Aspire.Dashboard.Model;
1010
using Aspire.Dashboard.Utils;
11+
using Aspire.Hosting.ConsoleLogs;
1112
using Microsoft.AspNetCore.Components;
1213
using Microsoft.Extensions.Options;
1314
using Microsoft.JSInterop;
@@ -32,7 +33,7 @@ public sealed partial class LogViewer
3233
[Inject]
3334
public required IOptions<DashboardOptions> Options { get; set; }
3435

35-
public LogEntries LogEntries { get; set; } = null!;
36+
internal LogEntries LogEntries { get; set; } = null!;
3637

3738
public string? ResourceName { get; set; }
3839

@@ -85,7 +86,14 @@ internal async Task SetLogSourceAsync(string resourceName, IAsyncEnumerable<IRea
8586

8687
foreach (var (lineNumber, content, isErrorOutput) in batch)
8788
{
88-
LogEntries.InsertSorted(logParser.CreateLogEntry(content, isErrorOutput), lineNumber);
89+
// Set the base line number using the reported line number of the first log line.
90+
if (LogEntries.EntriesCount == 0)
91+
{
92+
LogEntries.BaseLineNumber = lineNumber;
93+
}
94+
95+
var logEntry = logParser.CreateLogEntry(content, isErrorOutput);
96+
LogEntries.InsertSorted(logEntry);
8997
}
9098

9199
StateHasChanged();

src/Aspire.Dashboard/ConsoleLogs/LogEntries.cs

Lines changed: 0 additions & 91 deletions
This file was deleted.

src/Aspire.Dashboard/ConsoleLogs/LogEntry.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/Aspire.Dashboard/ConsoleLogs/LogParser.cs

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,90 +2,57 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Net;
5-
using Aspire.Dashboard.Model;
5+
using Aspire.Hosting.ConsoleLogs;
66

77
namespace Aspire.Dashboard.ConsoleLogs;
88

99
internal sealed class LogParser
1010
{
11-
private DateTimeOffset? _parentTimestamp;
12-
private Guid? _parentId;
13-
private int _lineIndex;
1411
private AnsiParser.ParserState? _residualState;
1512

1613
public LogEntry CreateLogEntry(string rawText, bool isErrorOutput)
1714
{
1815
// Several steps to do here:
1916
//
2017
// 1. Parse the content to look for the timestamp
21-
// 2. Parse the content to look for info/warn/dbug header
22-
// 3. HTML Encode the raw text for security purposes
23-
// 4. Parse the content to look for ANSI Control Sequences and color them if possible
24-
// 5. Parse the content to look for URLs and make them links if possible
25-
// 6. Create the LogEntry to get the ID
26-
// 7. Set the relative properties of the log entry (parent/line index/etc)
27-
// 8. Return the final result
18+
// 2. HTML Encode the raw text for security purposes
19+
// 3. Parse the content to look for ANSI Control Sequences and color them if possible
20+
// 4. Parse the content to look for URLs and make them links if possible
21+
// 5. Create the LogEntry
2822

2923
var content = rawText;
3024

3125
// 1. Parse the content to look for the timestamp
32-
var isFirstLine = false;
33-
DateTimeOffset? timestamp = null;
26+
DateTime? timestamp = null;
3427

3528
if (TimestampParser.TryParseConsoleTimestamp(content, out var timestampParseResult))
3629
{
37-
isFirstLine = true;
3830
content = timestampParseResult.Value.ModifiedText;
39-
timestamp = timestampParseResult.Value.Timestamp;
40-
}
41-
// 2. Parse the content to look for info/warn/dbug header
42-
// TODO extract log level and use here
43-
else
44-
{
45-
if (LogLevelParser.StartsWithLogLevelHeader(content))
46-
{
47-
isFirstLine = true;
48-
}
31+
timestamp = timestampParseResult.Value.Timestamp.UtcDateTime;
4932
}
5033

51-
// 3. HTML Encode the raw text for security purposes
34+
// 2. HTML Encode the raw text for security purposes
5235
content = WebUtility.HtmlEncode(content);
5336

54-
// 4. Parse the content to look for ANSI Control Sequences and color them if possible
37+
// 3. Parse the content to look for ANSI Control Sequences and color them if possible
5538
var conversionResult = AnsiParser.ConvertToHtml(content, _residualState);
5639
content = conversionResult.ConvertedText;
5740
_residualState = conversionResult.ResidualState;
5841

59-
// 5. Parse the content to look for URLs and make them links if possible
42+
// 4. Parse the content to look for URLs and make them links if possible
6043
if (UrlParser.TryParse(content, out var modifiedText))
6144
{
6245
content = modifiedText;
6346
}
6447

65-
// 6. Create the LogEntry to get the ID
48+
// 5. Create the LogEntry
6649
var logEntry = new LogEntry
6750
{
6851
Timestamp = timestamp,
6952
Content = content,
70-
Type = isErrorOutput ? LogEntryType.Error : LogEntryType.Default,
71-
IsFirstLine = isFirstLine
53+
Type = isErrorOutput ? LogEntryType.Error : LogEntryType.Default
7254
};
7355

74-
// 7. Set the relative properties of the log entry (parent/line index/etc)
75-
if (isFirstLine)
76-
{
77-
_parentTimestamp = logEntry.Timestamp;
78-
_parentId = logEntry.Id;
79-
_lineIndex = 0;
80-
}
81-
else if (_parentId.HasValue)
82-
{
83-
logEntry.ParentTimestamp = _parentTimestamp;
84-
logEntry.ParentId = _parentId;
85-
logEntry.LineIndex = ++_lineIndex;
86-
}
87-
88-
// 8. Return the final result
8956
return logEntry;
9057
}
9158
}

src/Aspire.Dashboard/ConsoleLogs/TimestampParser.cs

Lines changed: 0 additions & 77 deletions
This file was deleted.

src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Text.RegularExpressions;
88

99
namespace Aspire.Dashboard.ConsoleLogs;
10+
1011
public static partial class UrlParser
1112
{
1213
private static readonly Regex s_urlRegEx = GenerateUrlRegEx();

0 commit comments

Comments
 (0)