@page "/client-logs" @page "/admin/client-logs" @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false)) @attribute [Authorize] @using Microsoft.AspNetCore.Components.Web @inject HttpClient Http 클라이언트 로그
@if (_summary is not null) {
Total @_summary.Total
Error @_summary.ErrorCount
Warning @_summary.WarningCount
Info @_summary.InfoCount
Top Sources
    @foreach (var item in _summary.TopSources) {
  • @item.Key (@item.Value)
  • }
Top Routes
    @foreach (var item in _summary.TopRoutes) {
  • @item.Key (@item.Value)
  • }
}
새로고침
@if (_loading) {

불러오는 중...

} else if (_entries.Count == 0) {

최근 클라이언트 로그가 없습니다.

} else {
@foreach (var entry in _entries) {
@(entry.Level ?? "error") @entry.Timestamp @entry.Source

@entry.Message

@entry.Route
}
} @if (_groups.Count > 0) {
반복 오류 그룹 보기
@foreach (var group in _groups) {
@group.Count @group.Level @group.Source @group.Route

@group.Message

@group.LastSeen
}
}
@code { private readonly List _entries = []; private readonly List _groups = []; private bool _loading = true; private string _query = ""; private string _level = ""; private string _source = ""; private string _route = ""; private string _start = ""; private string _end = ""; private ClientLogSummaryDto? _summary; protected override async Task OnInitializedAsync() { await LoadAsync(); } private async Task LoadAsync() { _loading = true; _entries.Clear(); _groups.Clear(); try { _summary = await Http.GetFromJsonAsync("/api/client-logs/summary"); var url = $"/api/client-logs/recent?q={Uri.EscapeDataString(_query ?? string.Empty)}&level={Uri.EscapeDataString(_level ?? string.Empty)}&source={Uri.EscapeDataString(_source ?? string.Empty)}&route={Uri.EscapeDataString(_route ?? string.Empty)}&start={Uri.EscapeDataString(_start ?? string.Empty)}&end={Uri.EscapeDataString(_end ?? string.Empty)}"; var result = await Http.GetFromJsonAsync>(url); var grouped = await Http.GetFromJsonAsync>("/api/client-logs/groups"); if (result is not null) { _entries.AddRange(result); } if (grouped is not null) { _groups.AddRange(grouped); } } catch { } finally { _loading = false; StateHasChanged(); } } private async Task ApplyGroupFilter(ClientLogGroupDto group) { _query = group.Message ?? string.Empty; _level = group.Level ?? string.Empty; _source = group.Source ?? string.Empty; _route = group.Route ?? string.Empty; await LoadAsync(); } private async Task HandleGroupKeydown(KeyboardEventArgs e, ClientLogGroupDto group) { if (e.Key is "Enter" or " ") { await ApplyGroupFilter(group); } } private sealed class ClientLogDto { public string? Timestamp { get; set; } public string? Level { get; set; } public string? Source { get; set; } public string? Message { get; set; } public string? Route { get; set; } } private sealed class ClientLogSummaryDto { public int Total { get; set; } public int ErrorCount { get; set; } public int WarningCount { get; set; } public int InfoCount { get; set; } public List> TopSources { get; set; } = []; public List> TopRoutes { get; set; } = []; } private sealed class ClientLogGroupDto { public string? Key { get; set; } public string? Level { get; set; } public string? Source { get; set; } public string? Route { get; set; } public string? Message { get; set; } public int Count { get; set; } public string? LastSeen { get; set; } } }