Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions playground/Stress/Stress.ApiService/ConsoleStresser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ public static void Stress()
for (var color = 40; color <= 47; color++)
{
Console.Write("\x1b[" + color + "m"); // Set background color
Console.WriteLine($"This is background color {color}");
Console.Write("\x1b[0m"); // Reset colors to default after each background to maintain readability
Console.Write($"This is background color {color}");
Console.WriteLine("\x1b[0m"); // Reset colors to default after each background to maintain readability
}
Console.Write("\x1b[0m"); // Reset all colors to default at the end

Expand Down
17 changes: 17 additions & 0 deletions playground/Stress/Stress.ApiService/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@

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

app.MapGet("/write-console", () =>
{
for (var i = 0; i < 5000; i++)
{
if (i % 500 == 0)
{
Console.Error.WriteLine($"{i} Error");
}
else
{
Console.Out.WriteLine($"{i} Out");
}
}

return "Console written";
});

app.MapGet("/increment-counter", (TestMetrics metrics) =>
{
metrics.IncrementCounter(1, new TagList([new KeyValuePair<string, object?>("add-tag", "1")]));
Expand Down
3 changes: 3 additions & 0 deletions src/Aspire.Dashboard/Aspire.Dashboard.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,8 @@
<Compile Include="$(SharedDir)TokenGenerator.cs" Link="Utils\TokenGenerator.cs" />
<Compile Include="$(SharedDir)LoggingHelpers.cs" Link="Utils\LoggingHelpers.cs" />
<Compile Include="$(SharedDir)StringUtils.cs" Link="Utils\StringUtils.cs" />
<Compile Include="$(SharedDir)ConsoleLogs\LogEntries.cs" Link="Utils\ConsoleLogs\LogEntries.cs" />
<Compile Include="$(SharedDir)ConsoleLogs\LogEntry.cs" Link="Utils\ConsoleLogs\LogEntry.cs" />
<Compile Include="$(SharedDir)ConsoleLogs\TimestampParser.cs" Link="Utils\ConsoleLogs\TimestampParser.cs" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/Aspire.Dashboard/Components/Controls/LogViewer.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@namespace Aspire.Dashboard.Components
@using Aspire.Dashboard.Model
@using Aspire.Hosting.ConsoleLogs
@inject IJSRuntime JS
@implements IAsyncDisposable

Expand Down
12 changes: 10 additions & 2 deletions src/Aspire.Dashboard/Components/Controls/LogViewer.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Aspire.Dashboard.Extensions;
using Aspire.Dashboard.Model;
using Aspire.Dashboard.Utils;
using Aspire.Hosting.ConsoleLogs;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
Expand All @@ -32,7 +33,7 @@ public sealed partial class LogViewer
[Inject]
public required IOptions<DashboardOptions> Options { get; set; }

public LogEntries LogEntries { get; set; } = null!;
internal LogEntries LogEntries { get; set; } = null!;

public string? ResourceName { get; set; }

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

foreach (var (lineNumber, content, isErrorOutput) in batch)
{
LogEntries.InsertSorted(logParser.CreateLogEntry(content, isErrorOutput), lineNumber);
// Set the base line number using the reported line number of the first log line.
if (LogEntries.EntriesCount == 0)
{
LogEntries.BaseLineNumber = lineNumber;
}

var logEntry = logParser.CreateLogEntry(content, isErrorOutput);
LogEntries.InsertSorted(logEntry);
}

StateHasChanged();
Expand Down
91 changes: 0 additions & 91 deletions src/Aspire.Dashboard/ConsoleLogs/LogEntries.cs

This file was deleted.

26 changes: 0 additions & 26 deletions src/Aspire.Dashboard/ConsoleLogs/LogEntry.cs

This file was deleted.

57 changes: 12 additions & 45 deletions src/Aspire.Dashboard/ConsoleLogs/LogParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,90 +2,57 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net;
using Aspire.Dashboard.Model;
using Aspire.Hosting.ConsoleLogs;

namespace Aspire.Dashboard.ConsoleLogs;

internal sealed class LogParser
{
private DateTimeOffset? _parentTimestamp;
private Guid? _parentId;
private int _lineIndex;
private AnsiParser.ParserState? _residualState;

public LogEntry CreateLogEntry(string rawText, bool isErrorOutput)
{
// Several steps to do here:
//
// 1. Parse the content to look for the timestamp
// 2. Parse the content to look for info/warn/dbug header
// 3. HTML Encode the raw text for security purposes
// 4. Parse the content to look for ANSI Control Sequences and color them if possible
// 5. Parse the content to look for URLs and make them links if possible
// 6. Create the LogEntry to get the ID
// 7. Set the relative properties of the log entry (parent/line index/etc)
// 8. Return the final result
// 2. HTML Encode the raw text for security purposes
// 3. Parse the content to look for ANSI Control Sequences and color them if possible
// 4. Parse the content to look for URLs and make them links if possible
// 5. Create the LogEntry

var content = rawText;

// 1. Parse the content to look for the timestamp
var isFirstLine = false;
DateTimeOffset? timestamp = null;
DateTime? timestamp = null;

if (TimestampParser.TryParseConsoleTimestamp(content, out var timestampParseResult))
{
isFirstLine = true;
content = timestampParseResult.Value.ModifiedText;
timestamp = timestampParseResult.Value.Timestamp;
}
// 2. Parse the content to look for info/warn/dbug header
// TODO extract log level and use here
else
{
if (LogLevelParser.StartsWithLogLevelHeader(content))
{
isFirstLine = true;
}
timestamp = timestampParseResult.Value.Timestamp.UtcDateTime;
}

// 3. HTML Encode the raw text for security purposes
// 2. HTML Encode the raw text for security purposes
content = WebUtility.HtmlEncode(content);

// 4. Parse the content to look for ANSI Control Sequences and color them if possible
// 3. Parse the content to look for ANSI Control Sequences and color them if possible
var conversionResult = AnsiParser.ConvertToHtml(content, _residualState);
content = conversionResult.ConvertedText;
_residualState = conversionResult.ResidualState;

// 5. Parse the content to look for URLs and make them links if possible
// 4. Parse the content to look for URLs and make them links if possible
if (UrlParser.TryParse(content, out var modifiedText))
{
content = modifiedText;
}

// 6. Create the LogEntry to get the ID
// 5. Create the LogEntry
var logEntry = new LogEntry
{
Timestamp = timestamp,
Content = content,
Type = isErrorOutput ? LogEntryType.Error : LogEntryType.Default,
IsFirstLine = isFirstLine
Type = isErrorOutput ? LogEntryType.Error : LogEntryType.Default
};

// 7. Set the relative properties of the log entry (parent/line index/etc)
if (isFirstLine)
{
_parentTimestamp = logEntry.Timestamp;
_parentId = logEntry.Id;
_lineIndex = 0;
}
else if (_parentId.HasValue)
{
logEntry.ParentTimestamp = _parentTimestamp;
logEntry.ParentId = _parentId;
logEntry.LineIndex = ++_lineIndex;
}

// 8. Return the final result
return logEntry;
}
}
77 changes: 0 additions & 77 deletions src/Aspire.Dashboard/ConsoleLogs/TimestampParser.cs

This file was deleted.

1 change: 1 addition & 0 deletions src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text.RegularExpressions;

namespace Aspire.Dashboard.ConsoleLogs;

public static partial class UrlParser
{
private static readonly Regex s_urlRegEx = GenerateUrlRegEx();
Expand Down
Loading