feat(ui): color and acknowledge pinned log errors

Add independent AppLog message types and explicit Class 1/2 severity. Wrap and color log rows, pin Class 1 above Class 2, and let acknowledgement return entries to the current-launch timeline without changing file format or rotation.

Ref: https://logtape.org/manual/levels
This commit is contained in:
2026-11-02 18:17:18 -08:00
parent 01a3fcaaf7
commit a6aea5bf26
23 changed files with 365 additions and 100 deletions
+22 -10
View File
@@ -2,6 +2,8 @@ using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using ytLive.Models;
using AppLogErrorClass = ytLive.Helpers.AppLogErrorClass;
using AppLogMessageType = ytLive.Helpers.AppLogMessageType;
using AppLog = ytLive.Helpers.AppLog;
namespace ytLive.Services;
@@ -132,7 +134,8 @@ public class YouTubeStreamService
if (response.IsSuccessStatusCode) return null;
var body = await response.Content.ReadAsStringAsync();
AppLog.Write($"Broadcast update failed ({(int)response.StatusCode}): {body}");
AppLog.Write($"Broadcast update failed ({(int)response.StatusCode}): {body}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return $"YouTube rejected the update ({(int)response.StatusCode})";
}
@@ -170,7 +173,8 @@ public class YouTubeStreamService
if (response.IsSuccessStatusCode) return null;
var body = await response.Content.ReadAsStringAsync();
AppLog.Write($"Broadcast transition(complete) failed ({(int)response.StatusCode}): {body}");
AppLog.Write($"Broadcast transition(complete) failed ({(int)response.StatusCode}): {body}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return $"YouTube rejected the end transition ({(int)response.StatusCode})";
}
@@ -194,7 +198,8 @@ public class YouTubeStreamService
}
catch (Exception ex)
{
AppLog.Write($"Broadcast privacy read failed: {ex.Message}");
AppLog.Write($"Broadcast privacy read failed: {ex.Message}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return null;
}
}
@@ -220,16 +225,19 @@ public class YouTubeStreamService
var broadcast = await _http.DeleteAsync($"{ApiBase}/liveBroadcasts?id={id}");
if (broadcast.IsSuccessStatusCode) return null;
var bBody = await broadcast.Content.ReadAsStringAsync();
AppLog.Write($"liveBroadcasts.delete failed ({(int)broadcast.StatusCode}): {bBody}");
AppLog.Write($"liveBroadcasts.delete failed ({(int)broadcast.StatusCode}): {bBody}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return $"YouTube refused to delete the broadcast ({(int)broadcast.StatusCode})";
}
var body = await video.Content.ReadAsStringAsync();
AppLog.Write($"videos.delete failed ({(int)video.StatusCode}): {body}");
AppLog.Write($"videos.delete failed ({(int)video.StatusCode}): {body}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return $"YouTube refused to delete the video ({(int)video.StatusCode})";
}
catch (Exception ex)
{
AppLog.Write($"Broadcast delete failed: {ex.Message}");
AppLog.Write($"Broadcast delete failed: {ex.Message}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return ex.Message;
}
}
@@ -306,7 +314,8 @@ public class YouTubeStreamService
}
catch (Exception ex)
{
AppLog.Write($"Broadcast diag failed: {ex.Message}");
AppLog.Write($"Broadcast diag failed: {ex.Message}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return null;
}
}
@@ -341,7 +350,8 @@ public class YouTubeStreamService
var response = await _http.GetAsync($"{ApiBase}/{pathAndQuery}");
if (!response.IsSuccessStatusCode)
{
AppLog.Write($"Broadcast diag GET {pathAndQuery.Split('?')[0]} failed ({(int)response.StatusCode})");
AppLog.Write($"Broadcast diag GET {pathAndQuery.Split('?')[0]} failed ({(int)response.StatusCode})",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return default;
}
return JsonSerializer.Deserialize<JsonElement>(await response.Content.ReadAsStringAsync());
@@ -401,7 +411,8 @@ public class YouTubeStreamService
var body = await response.Content.ReadAsStringAsync();
var reason = ErrorReason(body);
AppLog.Write($"Broadcast bind failed ({(int)response.StatusCode}/{reason ?? "unknown"}) for {broadcastId} -> {streamId}: {body}");
AppLog.Write($"Broadcast bind failed ({(int)response.StatusCode}/{reason ?? "unknown"}) for {broadcastId} -> {streamId}: {body}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return BindFailureMessage((int)response.StatusCode, reason);
}
@@ -612,7 +623,8 @@ public class YouTubeStreamService
}
var errorBody = await response.Content.ReadAsStringAsync();
AppLog.Write($"Chat message insert failed ({(int)response.StatusCode}): {errorBody}");
AppLog.Write($"Chat message insert failed ({(int)response.StatusCode}): {errorBody}",
AppLogMessageType.Error, AppLogErrorClass.Class2);
return $"YouTube rejected the message ({(int)response.StatusCode})";
}