Skip to content

Commit 7eecf8e

Browse files
Copilotdanegsta
andauthored
Add system log stream source and support timezone formats without colon (#11872)
* Initial plan * Add system log stream source support and update timestamp parser - Added StreamTypeSystem constant to Logs class in ModelCommon.cs - Updated ResourceLogSource.GetAsyncEnumerator to initialize system stream and task - Updated TimestampParser.GenerateRfc3339RegEx to make timezone colon optional - Updated DcpExecutorTests to handle system stream in GetStreamPipesAsync - Added tests for new timestamp format (optional colon in timezone) - All tests passing Co-authored-by: danegsta <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: danegsta <[email protected]>
1 parent 31a509c commit 7eecf8e

File tree

5 files changed

+18
-2
lines changed

5 files changed

+18
-2
lines changed

src/Aspire.Hosting/Dcp/Model/ModelCommon.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,5 +456,6 @@ internal static class Logs
456456
public const string StreamTypeStartupStdErr = "startup_stderr";
457457
public const string StreamTypeStdOut = "stdout";
458458
public const string StreamTypeStdErr = "stderr";
459+
public const string StreamTypeSystem = "system";
459460
public const string SubResourceName = "log";
460461
}

src/Aspire.Hosting/Dcp/ResourceLogSource.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public async IAsyncEnumerator<LogEntryList> GetAsyncEnumerator(CancellationToken
5252
var stderrStreamTask = Task.Run(() => StreamLogsAsync(stderrStream, isError: true), cancellationToken);
5353
streamTasks.Add(stderrStreamTask);
5454

55+
var systemStream = await kubernetesService.GetLogStreamAsync(resource, Logs.StreamTypeSystem, cancellationToken, follow: follow, timestamps: true).ConfigureAwait(false);
56+
57+
var systemStreamTask = Task.Run(() => StreamLogsAsync(systemStream, isError: false), cancellationToken);
58+
streamTasks.Add(systemStreamTask);
59+
5560
// End the enumeration when both streams have been read to completion.
5661
async Task WaitForStreamsToCompleteAsync()
5762
{

src/Shared/ConsoleLogs/TimestampParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public static bool TryParseConsoleTimestamp(string text, [NotNullWhen(true)] out
6565
: # Separator for the time
6666
([0-5][0-9]) # Two digits for the seconds, restricted to 00-59
6767
(\.\d{1,9})? # A period and up to nine digits for the partial seconds (optional)
68-
(Z|([Z+-]([01][0-9]|2[0-3]):([0-5][0-9])))? # Time Zone offset, in the form Z or ZHH:MM or +HH:MM or -HH:MM (optional)
68+
(Z|([Z+-]([01][0-9]|2[0-3]):?([0-5][0-9])))? # Time Zone offset, in the form Z or ZHH:MM or ZHHMM or +HH:MM or +HHMM or -HH:MM or -HHMM (optional)
6969
""",
7070
RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace)]
7171
private static partial Regex GenerateRfc3339RegEx();

tests/Aspire.Dashboard.Tests/ConsoleLogsTests/TimestampParserTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ public void TryColorizeTimestamp_ReturnsCorrectResult(string input, bool expecte
5757
[InlineData("2023-10-10T15:05:30.123456789+12:59")]
5858
[InlineData("2023-10-10T15:05:30.123456789-12:59")]
5959
[InlineData("2023-10-10T15:05:30.123456789")]
60+
[InlineData("2023-10-10T15:05:30.123456789+1259")]
61+
[InlineData("2023-10-10T15:05:30.123456789-1259")]
62+
[InlineData("2023-10-10T15:05:30+1259")]
63+
[InlineData("2023-10-10T15:05:30-1259")]
6064
public void TryColorizeTimestamp_SupportedTimestampFormats(string input)
6165
{
6266
var result = TimestampParser.TryParseConsoleTimestamp(input, out var _);

tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,8 @@ public async Task ResourceLogging_ReplayBacklog_SentInBatch()
672672
"2024-08-19T06:10:05.000Z Seventh" + Environment.NewLine +
673673
"2024-08-19T06:10:04.000Z Forth" + Environment.NewLine +
674674
"2024-08-19T06:10:04.000Z Fifth" + Environment.NewLine));
675+
case Logs.StreamTypeSystem:
676+
return new MemoryStream();
675677
default:
676678
throw new InvalidOperationException("Unexpected type: " + logStreamType);
677679
}
@@ -729,6 +731,7 @@ private sealed class LogStreamPipes
729731
public Pipe StandardErr { get; set; } = default!;
730732
public Pipe StartupOut { get; set; } = default!;
731733
public Pipe StartupErr { get; set; } = default!;
734+
public Pipe System { get; set; } = default!;
732735
}
733736

734737
private static async Task<LogStreamPipes> GetStreamPipesAsync(Channel<(string Type, Pipe Pipe)> logStreamPipesChannel)
@@ -752,12 +755,15 @@ private static async Task<LogStreamPipes> GetStreamPipesAsync(Channel<(string Ty
752755
case Logs.StreamTypeStartupStdErr:
753756
result.StartupErr = item.Pipe;
754757
break;
758+
case Logs.StreamTypeSystem:
759+
result.System = item.Pipe;
760+
break;
755761
default:
756762
throw new InvalidOperationException("Unexpected type: " + item.Type);
757763
}
758764

759765
pipeCount++;
760-
if (pipeCount == 4)
766+
if (pipeCount == 5)
761767
{
762768
logStreamPipesChannel.Writer.Complete();
763769
}

0 commit comments

Comments
 (0)