Logged .NET events with the time they happened (#1042)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-10-10 19:05:41 +02:00
1 parent ca6ad6b1f0
commit 4616d1a4b2
12 files changed
+354 -17

No files matched your search

@@ -1,5 +1,14 @@
namespace AIStudio.Tools.Rust;
/// <summary>
/// A log event the Rust runtime writes to the log file.
/// </summary>
/// <param name="Timestamp">When the event happened, in the round-trip format of TerminalLogger.FormatTransportTimestamp, e.g., 2026-10-09T17:53:54.5629130+00:00. The Rust runtime logs the event with this time; when it cannot read it, the event shows the time it arrived instead.</param>
/// <param name="Level">The log level.</param>
/// <param name="Category">The category of the log event.</param>
/// <param name="Message">The log message.</param>
/// <param name="Exception">Optional exception message.</param>
/// <param name="StackTrace">Optional exception stack trace.</param>
public readonly record struct LogEventRequest(
string Timestamp,
string Level,
@@ -16,7 +16,7 @@ public sealed partial class RustService
/// <summary>
/// Sends a log event to the Rust runtime.
/// </summary>
/// <param name="timestamp">The timestamp of the log event.</param>
/// <param name="timestamp">When the log event happened, formatted by TerminalLogger.FormatTransportTimestamp.</param>
/// <param name="level">The log level.</param>
/// <param name="category">The category of the log event.</param>
/// <param name="message">The log message.</param>
+19 -3
View File
@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.Globalization;
using AIStudio.Tools.Rust;
using AIStudio.Tools.Services;
@@ -59,7 +60,9 @@ public sealed class TerminalLogger() : ConsoleFormatter(FORMATTER_NAME)
public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter)
{
var message = logEntry.Formatter(logEntry.State, logEntry.Exception);
var timestamp = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
var now = DateTimeOffset.UtcNow;
var timestamp = now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
var transportTimestamp = FormatTransportTimestamp(now);
var logLevel = logEntry.LogLevel.ToString();
var category = logEntry.Category;
var exceptionMessage = logEntry.Exception?.Message;
@@ -85,13 +88,26 @@ public sealed class TerminalLogger() : ConsoleFormatter(FORMATTER_NAME)
// Send log event to Rust via API (fire-and-forget):
if (RUST_SERVICE is not null)
RUST_SERVICE.LogEvent(timestamp, logLevel, category, message, exceptionMessage, stackTrace);
RUST_SERVICE.LogEvent(transportTimestamp, logLevel, category, message, exceptionMessage, stackTrace);
// Buffer early log events until the RustService is available:
else
EARLY_LOG_BUFFER.Enqueue(new LogEventRequest(timestamp, logLevel, category, message, exceptionMessage, stackTrace));
EARLY_LOG_BUFFER.Enqueue(new LogEventRequest(transportTimestamp, logLevel, category, message, exceptionMessage, stackTrace));
}
/// <summary>
/// Formats the time of a log event for the Rust runtime.
/// </summary>
/// <remarks>
/// The round-trip format is ISO 8601 with seven fractional digits and the offset, e.g.,
/// 2026-10-09T17:53:54.5629130+00:00, and it is the same in every culture. The Rust runtime
/// reads it as RFC 3339, so it can log the event with the time it happened instead of the
/// time it arrived.
/// </remarks>
/// <param name="timestamp">The time of the log event.</param>
/// <returns>The time in the round-trip format.</returns>
public static string FormatTransportTimestamp(DateTimeOffset timestamp) => timestamp.ToString("O", CultureInfo.InvariantCulture);
private static string GetColorForLogLevel(LogLevel logLevel) => logLevel switch
{
LogLevel.Trace => ANSI_GRAY,