Add Serilog console logging across the API
Information at endpoint and service-method boundaries, Debug in deeper helpers, Warning before expected/recoverable failures (not-found, validation, agent tool errors), Error on caught exceptions. Serilog wraps the exception handler so request-completion logs report the resolved status code rather than the raw exception. Never logs prose bodies or the Anthropic API key.
This commit is contained in:
@@ -4,10 +4,13 @@ using Novelly.Api.Data;
|
||||
|
||||
namespace Novelly.Api.Projects;
|
||||
|
||||
public class ProjectService(INovelDbContext db)
|
||||
public class ProjectService(INovelDbContext db, ILogger<ProjectService> logger)
|
||||
{
|
||||
public async Task<IReadOnlyList<ProjectSummaryDto>> ListAsync(CancellationToken ct = default) =>
|
||||
await db.Projects
|
||||
public async Task<IReadOnlyList<ProjectSummaryDto>> ListAsync(CancellationToken ct = default)
|
||||
{
|
||||
logger.LogInformation("Listing projects");
|
||||
|
||||
return await db.Projects
|
||||
.OrderByDescending(p => p.UpdatedAt)
|
||||
.Select(p => new ProjectSummaryDto(
|
||||
p.Id,
|
||||
@@ -21,12 +24,18 @@ public class ProjectService(INovelDbContext db)
|
||||
p.Chapters.SelectMany(c => c.Scenes).Sum(s => (int?)s.WordCount) ?? 0,
|
||||
p.UpdatedAt))
|
||||
.ToListAsync(ct);
|
||||
}
|
||||
|
||||
public async Task<ProjectDto> GetAsync(Guid id, CancellationToken ct = default) =>
|
||||
(await FindAsync(id, ct)).ToDto();
|
||||
public async Task<ProjectDto> GetAsync(Guid id, CancellationToken ct = default)
|
||||
{
|
||||
logger.LogInformation("Getting project {ProjectId}", id);
|
||||
return (await FindAsync(id, ct)).ToDto();
|
||||
}
|
||||
|
||||
public async Task<ProjectDto> CreateAsync(CreateProjectRequest request, CancellationToken ct = default)
|
||||
{
|
||||
logger.LogInformation("Creating project {Title}", request.Title);
|
||||
|
||||
var project = new Project
|
||||
{
|
||||
Title = request.Title,
|
||||
@@ -45,6 +54,8 @@ public class ProjectService(INovelDbContext db)
|
||||
|
||||
public async Task<ProjectDto> UpdateAsync(Guid id, UpdateProjectRequest request, CancellationToken ct = default)
|
||||
{
|
||||
logger.LogInformation("Updating project {ProjectId}", id);
|
||||
|
||||
var project = await FindAsync(id, ct);
|
||||
|
||||
project.Title = Patch.Apply(project.Title, request.Title) ?? project.Title;
|
||||
@@ -62,12 +73,25 @@ public class ProjectService(INovelDbContext db)
|
||||
|
||||
public async Task DeleteAsync(Guid id, CancellationToken ct = default)
|
||||
{
|
||||
logger.LogInformation("Deleting project {ProjectId}", id);
|
||||
|
||||
var project = await FindAsync(id, ct);
|
||||
db.Projects.Remove(project);
|
||||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
private async Task<Project> FindAsync(Guid id, CancellationToken ct) =>
|
||||
await db.Projects.FirstOrDefaultAsync(p => p.Id == id, ct)
|
||||
?? throw new NotFoundException(nameof(Project), id);
|
||||
private async Task<Project> FindAsync(Guid id, CancellationToken ct)
|
||||
{
|
||||
logger.LogDebug("Finding project {ProjectId}", id);
|
||||
|
||||
var project = await db.Projects.FirstOrDefaultAsync(p => p.Id == id, ct);
|
||||
if (project is null)
|
||||
{
|
||||
logger.LogWarning("Project {ProjectId} not found", id);
|
||||
throw new NotFoundException(nameof(Project), id);
|
||||
}
|
||||
|
||||
logger.LogDebug("Found project {ProjectId}", id);
|
||||
return project;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user