Files
LazyBearWorks/LazyBear.MCP/TUI/Components/LogsTab.razor
Shahovalov MIkhail 879becadfe feat: внедрение RazorConsole TUI с runtime-управлением MCP-инструментами
- Добавлен RazorConsole.Core для интерактивного TUI-дашборда
- ToolRegistryService: живое включение/отключение модулей и отдельных методов
- InMemoryLogSink: кольцевой буфер логов с фильтрацией по модулю
- TUI: 3 таба (Overview, Logs, Settings)
- IToolModule: generic-интерфейс для легкого добавления новых MCP-модулей
- Guard-проверка TryCheckEnabled() во всех существующих инструментах
2026-04-13 17:31:28 +03:00

120 lines
3.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@using LazyBear.MCP.Services.Logging
@inject InMemoryLogSink LogSink
@implements IDisposable
<Rows>
<Markup Content=" " />
@* Фильтр по модулю *@
<Columns>
<Markup Content="Filter: " />
<Select TItem="string"
Options="@_filterOptions"
Value="@_selectedFilter"
ValueChanged="@OnFilterChanged"
FocusOrder="10" />
</Columns>
<Markup Content=" " />
@{
var entries = GetFilteredEntries();
}
@if (entries.Count == 0)
{
<Markup Content="[grey]No log entries yet...[/]" />
}
else
{
@* Показываем последние 20 строк с прокруткой *@
<ViewHeightScrollable LinesToRender="20"
ScrollOffset="@_scrollOffset"
ScrollOffsetChanged="@(v => { _scrollOffset = v; })" >
<Rows>
@foreach (var entry in entries)
{
var levelColor = entry.Level switch
{
LogLevel.Error or LogLevel.Critical => Spectre.Console.Color.Red,
LogLevel.Warning => Spectre.Console.Color.Yellow,
LogLevel.Information => Spectre.Console.Color.White,
_ => Spectre.Console.Color.Grey
};
var levelTag = entry.Level switch
{
LogLevel.Error => "ERR",
LogLevel.Critical => "CRT",
LogLevel.Warning => "WRN",
LogLevel.Information => "INF",
LogLevel.Debug => "DBG",
_ => "TRC"
};
var time = entry.Timestamp.ToString("HH:mm:ss");
var cat = entry.ShortCategory.Length > 18
? entry.ShortCategory[..18]
: entry.ShortCategory.PadRight(18);
var msg = entry.Message.Length > 80
? entry.Message[..80] + "..."
: entry.Message;
<Columns>
<Markup Content="@($"[grey]{time}[/]")" />
<Markup Content="@($" {levelTag} ")" Foreground="@levelColor" />
<Markup Content="@($"[grey]{cat}[/]")" />
<Markup Content="@($" {msg}")" />
</Columns>
}
</Rows>
</ViewHeightScrollable>
}
</Rows>
@code {
private string _selectedFilter = "All";
private int _scrollOffset = 0;
private string[] _filterOptions = ["All", "Jira", "Kubernetes", "Confluence", "MCP", "System"];
private static readonly Dictionary<string, string?> FilterPrefixes = new()
{
["All"] = null,
["Jira"] = "LazyBear.MCP.Services.Jira",
["Kubernetes"] = "LazyBear.MCP.Services.Kubernetes",
["Confluence"] = "LazyBear.MCP.Services.Confluence",
["MCP"] = "ModelContextProtocol",
["System"] = "Microsoft"
};
private IReadOnlyList<LogEntry> GetFilteredEntries()
{
FilterPrefixes.TryGetValue(_selectedFilter, out var prefix);
return LogSink.GetEntries(prefix);
}
private void OnFilterChanged(string value)
{
_selectedFilter = value;
_scrollOffset = 0;
StateHasChanged();
}
protected override void OnInitialized()
{
LogSink.OnLog += HandleNewLog;
}
private void HandleNewLog(LogEntry _)
{
InvokeAsync(StateHasChanged);
}
public void Dispose()
{
LogSink.OnLog -= HandleNewLog;
}
}