Skip to content

Commit

Permalink
Fixed: Do not Qurery Db in DbUpdateException RehanSaeed#100
Browse files Browse the repository at this point in the history
  • Loading branch information
Joel Weiss committed Jun 28, 2019
1 parent 0e9fd59 commit acaa0e1
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 2 deletions.
7 changes: 7 additions & 0 deletions Serilog.Exceptions.sln
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Exceptions.Benchmark", "Benchmarks\Serilog.Exceptions.Benchmark\Serilog.Exceptions.Benchmark.csproj", "{5A82CFFC-EC33-4B7B-A6F6-7FADC0E2DDAA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Exceptions.EntityFrameworkCore", "Source\Serilog.Exceptions.EntityFrameworkCore\Serilog.Exceptions.EntityFrameworkCore.csproj", "{69C1004B-627D-4B90-8FAD-4B4069115A56}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -65,6 +67,10 @@ Global
{5A82CFFC-EC33-4B7B-A6F6-7FADC0E2DDAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A82CFFC-EC33-4B7B-A6F6-7FADC0E2DDAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A82CFFC-EC33-4B7B-A6F6-7FADC0E2DDAA}.Release|Any CPU.Build.0 = Release|Any CPU
{69C1004B-627D-4B90-8FAD-4B4069115A56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69C1004B-627D-4B90-8FAD-4B4069115A56}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69C1004B-627D-4B90-8FAD-4B4069115A56}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69C1004B-627D-4B90-8FAD-4B4069115A56}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -75,6 +81,7 @@ Global
{7C962929-2138-4787-ABA7-94E8D3F9C20C} = {D6E871A8-2DFF-4676-BED8-046B164919B9}
{F5BBB5C1-5920-40F3-8C44-01A54CC3D6B7} = {C5508012-7216-4ABE-AB2F-B166ED5FF94F}
{5A82CFFC-EC33-4B7B-A6F6-7FADC0E2DDAA} = {5CE72C42-F5C5-405B-BE8A-9AFDA7F43CB2}
{69C1004B-627D-4B90-8FAD-4B4069115A56} = {C5508012-7216-4ABE-AB2F-B166ED5FF94F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BE74AFAC-AC6F-4B80-860F-15C22BEE1A38}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace Serilog.Exceptions.SqlServer.Destructurers
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Serilog.Exceptions.Core;
using Serilog.Exceptions.Destructurers;

/// <summary>
/// A destructurer for <see cref="DbUpdateException"/>.
/// </summary>
/// <seealso cref="ExceptionDestructurer" />
public class DbUpdateExceptionDestructurer : ExceptionDestructurer
{
/// <inheritdoc />
public override Type[] TargetTypes => new[] { typeof(DbUpdateException), typeof(DbUpdateConcurrencyException) };

/// <inheritdoc />
public override void Destructure(
Exception exception,
IExceptionPropertiesBag propertiesBag,
Func<Exception, IReadOnlyDictionary<string, object>> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);

#pragma warning disable CA1062 // Validate arguments of public methods
var dbUpdateException = (DbUpdateException)exception;
var entriesValue = dbUpdateException.Entries?.Select(e => new
{
EntryProperties = e.Properties.Select(p => new
{
PropertyName = p.Metadata.Name,
p.OriginalValue,
p.CurrentValue,
p.IsTemporary,
p.IsModified
}),
e.State
}).ToList();
propertiesBag.AddProperty(nameof(DbUpdateException.Entries), entriesValue);
#pragma warning restore CA1062 // Validate arguments of public methods
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Serilog.Exceptions.Test, PublicKey=00240000048000009400000006020000002400005253413100040000010001007320f17cde01a37b8b3dff91961943f76893c63352544608de15974586e17739e0b232cdc8cc8762b40d988a21522024abca8116605ed1c8958f350bc6ca4594aa1ca61c1906d85ee76df8d9b404ffd65a5f6efeddd486bddd5b74ff9a7449af0dc9d43da753a3023b20ca616e8313e82a18719b6551f37c45c8d8e4e4cf9bac")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Label="Build">
<TargetFrameworks>netstandard2.0;net461;net472</TargetFrameworks>
<CodeAnalysisRuleSet>../../MinimumRecommendedRulesWithStyleCop.ruleset</CodeAnalysisRuleSet>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<PropertyGroup Label="Package">
<VersionPrefix>5.3.0</VersionPrefix>
<Authors>Muhammad Rehan Saeed (RehanSaeed.com)</Authors>
<Product>Serilog Exceptions</Product>
<Description>Log exception details and custom properties that are not output in Exception.ToString().</Description>
<Copyright>Copyright © Muhammad Rehan Saeed. All rights Reserved</Copyright>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/RehanSaeed/Serilog.Exceptions.EntityFrameworkCore</PackageProjectUrl>
<PackageIconUrl>https://raw.githubusercontent.com/RehanSaeed/Serilog.Exceptions/master/Images/Serilog%20Community%20256x256.png</PackageIconUrl>
<RepositoryUrl>https://github.com/RehanSaeed/Serilog.Exceptions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>Serilog;Exception;Log;Logging;Detail;Details</PackageTags>
<PackageReleaseNotes>https://github.com/RehanSaeed/Serilog.Exceptions/releases</PackageReleaseNotes>
</PropertyGroup>

<PropertyGroup Label="Signing">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../Key.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>

<PropertyGroup Label="Source Link">
<!-- Optional: Declare that the Repository URL can be published to NuSpec -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<!-- Optional: Embed source files that are not tracked by the source control manager to the PDB -->
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<!-- Optional: Include PDB in the built .nupkg -->
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>

<ItemGroup Label="Project References">
<ProjectReference Include="..\..\Source\Serilog.Exceptions\Serilog.Exceptions.csproj" />
</ItemGroup>

<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" PrivateAssets="all" Version="2.9.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0-preview.2" />
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0-beta2-19324-01" />
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.1.118" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
namespace Serilog.Exceptions.Test.Destructurers
{
using System;
using System.Collections.Generic;
using System.IO;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Serilog.Exceptions.Core;
using Serilog.Exceptions.SqlServer.Destructurers;
using Serilog.Formatting.Json;
using Xunit;
using static LogJsonOutputUtils;

public class DbUpdateExceptionDestructurerTest
{
[Fact]
public void WithoutDbUpdateExceptionDestructurerShouldLogDbValues()
{
// Arrange
var jsonWriter = new StringWriter();
ILogger logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder().WithDefaultDestructurers())
.WriteTo.Sink(new TestTextWriterSink(jsonWriter, new JsonFormatter()))
.CreateLogger();
var ctx = new TestContext();
ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();

var entry = ctx.Add(new User
{
UserId = Guid.NewGuid().ToString()
});

// Act
logger.Error(new TestDbUpdateException("DbUpdate Error", entry), "Error");

// Assert
var writtenJson = jsonWriter.ToString();
writtenJson.Should().Contain(TestContext.UserIdIDoNotWantToSee);
}

[Fact]
public void WithDbUpdateExceptionDestructurerShouldNotLogDbValues()
{
// Arrange
var jsonWriter = new StringWriter();
ILogger logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder().WithDefaultDestructurers().WithDestructurers(new[] { new TestDbUpdateExceptionDestructurer() }))
.WriteTo.Sink(new TestTextWriterSink(jsonWriter, new JsonFormatter()))
.CreateLogger();
var ctx = new TestContext();
ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();

var entry = ctx.Add(new User
{
UserId = Guid.NewGuid().ToString()
});

// Act
logger.Error(new TestDbUpdateException("DbUpdate Error", entry), "Error");

// Assert
var writtenJson = jsonWriter.ToString();
writtenJson.Should().NotContain(TestContext.UserIdIDoNotWantToSee);
}

public class User
{
public string UserId { get; set; }
}

public class TestContext : DbContext
{
public const string UserIdIDoNotWantToSee = "I Don't Want To See You";

public DbSet<User> Users { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseInMemoryDatabase(databaseName: "TestDebUpdateException");

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var users = new List<User>
{
new User
{
UserId = "FirstUser"
},
new User
{
UserId = UserIdIDoNotWantToSee
}
};

modelBuilder.Entity<User>().HasData(users);
}
}

internal class TestDbUpdateException : DbUpdateException
{
private readonly IReadOnlyList<EntityEntry> entityEntries;

public TestDbUpdateException(string message, EntityEntry entityEntry)
: base(message, (Exception)null) => this.entityEntries = new List<EntityEntry> { entityEntry }.AsReadOnly();

public override IReadOnlyList<EntityEntry> Entries => this.entityEntries;
}

internal class TestDbUpdateExceptionDestructurer : DbUpdateExceptionDestructurer
{
public override Type[] TargetTypes => new[] { typeof(TestDbUpdateException) };
}
}
}
6 changes: 4 additions & 2 deletions Tests/Serilog.Exceptions.Test/Serilog.Exceptions.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Label="Build">
<TargetFrameworks>netcoreapp2.2</TargetFrameworks>
Expand All @@ -14,12 +14,14 @@
</PropertyGroup>

<ItemGroup Label="Project References">
<ProjectReference Include="..\..\Source\Serilog.Exceptions.EntityFrameworkCore\Serilog.Exceptions.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\Source\Serilog.Exceptions.SqlServer\Serilog.Exceptions.SqlServer.csproj" />
<ProjectReference Include="..\..\Source\Serilog.Exceptions\Serilog.Exceptions.csproj" />
</ItemGroup>

<ItemGroup Label="Package References">
<PackageReference Include="FluentAssertions" Version="5.7.0" />
<PackageReference Include="FluentAssertions" Version="5.7.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0-preview.2" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
Expand Down

0 comments on commit acaa0e1

Please sign in to comment.