mirror of https://github.com/ErsatzTV/ErsatzTV.git
15 changed files with 170 additions and 0 deletions
@ -0,0 +1,12 @@ |
|||||||
|
using System; |
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Logs |
||||||
|
{ |
||||||
|
public record LogEntryViewModel( |
||||||
|
int Id, |
||||||
|
DateTime Timestamp, |
||||||
|
string Level, |
||||||
|
string Exception, |
||||||
|
string RenderedMessage, |
||||||
|
string Properties); |
||||||
|
} |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Logs |
||||||
|
{ |
||||||
|
internal static class Mapper |
||||||
|
{ |
||||||
|
internal static LogEntryViewModel ProjectToViewModel(LogEntry logEntry) => |
||||||
|
new( |
||||||
|
logEntry.Id, |
||||||
|
logEntry.Timestamp, |
||||||
|
logEntry.Level, |
||||||
|
logEntry.Exception, |
||||||
|
logEntry.RenderedMessage, |
||||||
|
logEntry.Properties); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using MediatR; |
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Logs.Queries |
||||||
|
{ |
||||||
|
public record GetRecentLogEntries : IRequest<List<LogEntryViewModel>>; |
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using ErsatzTV.Core.Interfaces.Repositories; |
||||||
|
using LanguageExt; |
||||||
|
using MediatR; |
||||||
|
using static ErsatzTV.Application.Logs.Mapper; |
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Logs.Queries |
||||||
|
{ |
||||||
|
public class GetRecentLogEntriesHandler : IRequestHandler<GetRecentLogEntries, List<LogEntryViewModel>> |
||||||
|
{ |
||||||
|
private readonly ILogRepository _logRepository; |
||||||
|
|
||||||
|
public GetRecentLogEntriesHandler(ILogRepository logRepository) => _logRepository = logRepository; |
||||||
|
|
||||||
|
public Task<List<LogEntryViewModel>> Handle(GetRecentLogEntries request, CancellationToken cancellationToken) => |
||||||
|
_logRepository.GetRecentLogEntries().Map(list => list.Map(ProjectToViewModel).ToList()); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
using System; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Domain |
||||||
|
{ |
||||||
|
public record LogEntry( |
||||||
|
int Id, |
||||||
|
DateTime Timestamp, |
||||||
|
string Level, |
||||||
|
string Exception, |
||||||
|
string RenderedMessage, |
||||||
|
string Properties); |
||||||
|
} |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Interfaces.Repositories |
||||||
|
{ |
||||||
|
public interface ILogRepository |
||||||
|
{ |
||||||
|
public Task<List<LogEntry>> GetRecentLogEntries(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Data.Configurations |
||||||
|
{ |
||||||
|
public class LogEntryConfiguration : IEntityTypeConfiguration<LogEntry> |
||||||
|
{ |
||||||
|
public void Configure(EntityTypeBuilder<LogEntry> builder) => |
||||||
|
builder.ToTable("Logs"); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Data |
||||||
|
{ |
||||||
|
public class LogContext : DbContext |
||||||
|
{ |
||||||
|
public LogContext(DbContextOptions<LogContext> options) |
||||||
|
: base(options) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public DbSet<LogEntry> LogEntries { get; set; } |
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder) |
||||||
|
{ |
||||||
|
base.OnModelCreating(builder); |
||||||
|
builder.ApplyConfigurationsFromAssembly(typeof(LogContext).Assembly); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using ErsatzTV.Core.Interfaces.Repositories; |
||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Data.Repositories |
||||||
|
{ |
||||||
|
public class LogRepository : ILogRepository |
||||||
|
{ |
||||||
|
private readonly LogContext _logContext; |
||||||
|
|
||||||
|
public LogRepository(LogContext logContext) => _logContext = logContext; |
||||||
|
|
||||||
|
public Task<List<LogEntry>> GetRecentLogEntries() => |
||||||
|
_logContext.LogEntries.OrderByDescending(e => e.Id).Take(100).ToListAsync(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
@page "/system/logs" |
||||||
|
@using ErsatzTV.Application.Logs |
||||||
|
@using ErsatzTV.Application.Logs.Queries |
||||||
|
@inject IMediator Mediator |
||||||
|
|
||||||
|
<MudTable FixedHeader="true" Dense="true" Items="_logEntries"> |
||||||
|
<HeaderContent> |
||||||
|
<MudTh>Timestamp</MudTh> |
||||||
|
<MudTh>Level</MudTh> |
||||||
|
<MudTh>Message</MudTh> |
||||||
|
<MudTh>Properties</MudTh> |
||||||
|
</HeaderContent> |
||||||
|
<RowTemplate> |
||||||
|
<MudTd DataLabel="Timestamp">@context.Timestamp</MudTd> |
||||||
|
<MudTd DataLabel="Level">@context.Level</MudTd> |
||||||
|
<MudTd DataLabel="Message">@context.RenderedMessage</MudTd> |
||||||
|
<MudTd DataLabel="Message">@context.Properties</MudTd> |
||||||
|
</RowTemplate> |
||||||
|
<PagerContent> |
||||||
|
<MudTablePager/> |
||||||
|
</PagerContent> |
||||||
|
</MudTable> |
||||||
|
|
||||||
|
@code { |
||||||
|
private List<LogEntryViewModel> _logEntries; |
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync() => _logEntries = await Mediator.Send(new GetRecentLogEntries()); |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue