Improve logging and async handling in ResourceServer

ResourceServer now defaults to using TraceLogger if no logger is provided and properly awaits FetchBlobConfig. FetchBlobConfig is refactored to return a Task and handle missing configuration more gracefully. TraceLogger now writes logs to a file named after its namespace and sets up a TextWriterTraceListener for persistent logging.
This commit is contained in:
Namhyeon Go 2025-08-17 20:12:38 +09:00
parent 8ecdf99d78
commit cc08c46886
2 changed files with 28 additions and 8 deletions

View File

@ -44,13 +44,13 @@ namespace WelsonJS.Launcher
public ResourceServer(string prefix, string resourceName, ICompatibleLogger logger = null)
{
_logger = logger;
_logger = logger ?? new TraceLogger();
_prefix = prefix;
_listener = new HttpListener();
_resourceName = resourceName;
// Fetch a blob config from Internet
FetchBlobConfig();
FetchBlobConfig().ConfigureAwait(false);
// Add resource tools
_tools.Add(new ResourceTools.Completion(this, _httpClient));
@ -167,7 +167,11 @@ namespace WelsonJS.Launcher
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.UserAgent.ParseAdd(context.Request.UserAgent);
var ua = context?.Request?.UserAgent;
if (!string.IsNullOrEmpty(ua))
{
request.Headers.UserAgent.ParseAdd(ua);
}
HttpResponseMessage response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
@ -430,24 +434,29 @@ namespace WelsonJS.Launcher
}
}
private async void FetchBlobConfig()
private async Task FetchBlobConfig()
{
try
{
string url = Program.GetAppConfig("BlobConfigUrl");
var response = await _httpClient.GetStreamAsync(url);
if (string.IsNullOrWhiteSpace(url))
{
_logger?.Warn("BlobConfigUrl is not configured.");
return;
}
var serializer = new XmlSerializer(typeof(BlobConfig));
using (var response = await _httpClient.GetStreamAsync(url))
using (var reader = new StreamReader(response))
{
_blobConfig = (BlobConfig)serializer.Deserialize(reader);
var serializer = new XmlSerializer(typeof(BlobConfig));
_blobConfig = (BlobConfig)serializer.Deserialize(reader);
}
_blobConfig?.Compile();
}
catch (Exception ex)
{
_logger?.Error($"Failed to fetch a blob config. Exception: {ex.Message}");
_logger?.Error($"Failed to fetch a blob config. Exception: {ex}");
}
}
}

View File

@ -12,6 +12,17 @@ namespace WelsonJS.Launcher
{
public class TraceLogger : ICompatibleLogger
{
private static readonly string _logFileName;
static TraceLogger()
{
_logFileName = typeof(TraceLogger).Namespace + ".log";
var textWriterTraceListener = new TextWriterTraceListener(_logFileName);
Trace.Listeners.Add(textWriterTraceListener);
Trace.AutoFlush = true;
}
public void Info(string message) => Trace.TraceInformation(message);
public void Warn(string message) => Trace.TraceWarning(message);
public void Error(string message) => Trace.TraceError(message);