Skip to content

Commit

Permalink
Log provider version in addition to EF Core version
Browse files Browse the repository at this point in the history
Fixes #22906
  • Loading branch information
ajcvickers committed Aug 17, 2021
1 parent 1559216 commit bd7220d
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 37 deletions.
8 changes: 7 additions & 1 deletion src/EFCore/Diagnostics/CoreLoggerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -895,6 +896,7 @@ public static void ContextInitialized(
ProductInfo.GetVersion(),
context.GetType().ShortDisplayName(),
context.Database.ProviderName,
GetProviderVersion(context),
contextOptions.BuildOptionsFragment());
}

Expand All @@ -912,14 +914,18 @@ public static void ContextInitialized(

private static string ContextInitialized(EventDefinitionBase definition, EventData payload)
{
var d = (EventDefinition<string, string, string?, string>)definition;
var d = (EventDefinition<string, string, string?, string?, string>)definition;
var p = (ContextInitializedEventData)payload;
return d.GenerateMessage(
ProductInfo.GetVersion(),
p.Context.GetType().ShortDisplayName(),
p.Context.Database.ProviderName,
GetProviderVersion(p.Context),
p.ContextOptions.BuildOptionsFragment());
}

private static string? GetProviderVersion(DbContext context)
=> context.GetService<IEnumerable<IDatabaseProvider>>().FirstOrDefault()?.Version;

/// <summary>
/// Logs for the <see cref="CoreEventId.ExecutionStrategyRetrying" /> event.
Expand Down
10 changes: 5 additions & 5 deletions src/EFCore/Properties/CoreStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/EFCore/Properties/CoreStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -755,8 +755,8 @@
<comment>Debug CoreEventId.ContextDisposed string</comment>
</data>
<data name="LogContextInitialized" xml:space="preserve">
<value>Entity Framework Core {version} initialized '{contextType}' using provider '{provider}' with options: {options}</value>
<comment>Information CoreEventId.ContextInitialized string string string? string</comment>
<value>Entity Framework Core {version} initialized '{contextType}' using provider '{provider}:{providerVersion}' with options: {options}</value>
<comment>Information CoreEventId.ContextInitialized string string string? string? string</comment>
</data>
<data name="LogDetachedLazyLoading" xml:space="preserve">
<value>An attempt was made to lazy-load navigation '{navigation}' on a detached entity of type '{entityType}'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking'.</value>
Expand Down
9 changes: 9 additions & 0 deletions src/EFCore/Storage/DatabaseProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -52,6 +53,14 @@ public DatabaseProvider(DatabaseProviderDependencies dependencies)
public virtual string Name
=> typeof(TOptionsExtension).Assembly.GetName().Name!;

/// <summary>
/// The unique name used to identify the database provider. This should be the same as the NuGet package name
/// for the providers runtime.
/// </summary>
public virtual string? Version
=> typeof(TOptionsExtension).Assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

/// <summary>
/// Gets a value indicating whether this database provider has been selected for a given context.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions src/EFCore/Storage/IDatabaseProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Reflection;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;

Expand Down Expand Up @@ -29,6 +30,13 @@ public interface IDatabaseProvider
/// </summary>
string Name { get; }

/// <summary>
/// The value of the <see cref="AssemblyInformationalVersionAttribute.InformationalVersion" />
/// for the database provider assembly.
/// </summary>
string? Version
=> null;

/// <summary>
/// Gets a value indicating whether this database provider has been configured for a given context.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions test/EFCore.InMemory.FunctionalTests/LoggingInMemoryTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Reflection;
using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore
Expand All @@ -15,6 +17,10 @@ protected override DbContextOptionsBuilder CreateOptionsBuilder(IServiceCollecti
protected override string ProviderName
=> "Microsoft.EntityFrameworkCore.InMemory";

protected override string ProviderVersion
=> typeof(InMemoryOptionsExtension).Assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

protected override string DefaultOptions
=> "StoreName=LoggingInMemoryTest ";
}
Expand Down
3 changes: 3 additions & 0 deletions test/EFCore.Specification.Tests/LoggingTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ protected virtual string ExpectedMessage(string optionsFragment)
ProductInfo.GetVersion(),
nameof(LoggingContext),
ProviderName,
ProviderVersion,
optionsFragment ?? "None").Trim();

protected abstract DbContextOptionsBuilder CreateOptionsBuilder(IServiceCollection services);

protected abstract string ProviderName { get; }

protected abstract string ProviderVersion { get; }

protected virtual string DefaultOptions
=> null;

Expand Down
5 changes: 5 additions & 0 deletions test/EFCore.SqlServer.FunctionalTests/LoggingSqlServerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -20,5 +21,9 @@ protected override DbContextOptionsBuilder CreateOptionsBuilder(

protected override string ProviderName
=> "Microsoft.EntityFrameworkCore.SqlServer";

protected override string ProviderVersion
=> typeof(SqlServerOptionsExtension).Assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
}
}
5 changes: 5 additions & 0 deletions test/EFCore.Sqlite.FunctionalTests/LoggingSqliteTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Sqlite.Infrastructure.Internal;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -20,5 +21,9 @@ protected override DbContextOptionsBuilder CreateOptionsBuilder(

protected override string ProviderName
=> "Microsoft.EntityFrameworkCore.Sqlite";

protected override string ProviderVersion
=> typeof(SqliteOptionsExtension).Assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
}
}
58 changes: 29 additions & 29 deletions test/EFCore.Tests/DbContextLoggerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ namespace Microsoft.EntityFrameworkCore
public class DbContextLoggerTests
{
private const string ContextInitialized =
@"info: <Local Date> HH:mm:ss.fff CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ";
@"info: <Local Date> HH:mm:ss.fff CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure) " +
@" Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ";

private const string SaveChangesStarting =
@"dbug: <Local Date> HH:mm:ss.fff CoreEventId.SaveChangesStarting[10004] (Microsoft.EntityFrameworkCore.Update)
SaveChanges starting for 'LoggingContext'.";
@"dbug: <Local Date> HH:mm:ss.fff CoreEventId.SaveChangesStarting[10004] (Microsoft.EntityFrameworkCore.Update) " +
@" SaveChanges starting for 'LoggingContext'.";

private const string SaveChangesCompleted =
@"dbug: <Local Date> HH:mm:ss.fff CoreEventId.SaveChangesCompleted[10005] (Microsoft.EntityFrameworkCore.Update)
SaveChanges completed for 'LoggingContext' with 0 entities written to the database.";
@"dbug: <Local Date> HH:mm:ss.fff CoreEventId.SaveChangesCompleted[10005] (Microsoft.EntityFrameworkCore.Update) " +
@" SaveChanges completed for 'LoggingContext' with 0 entities written to the database.";

private const string ContextDisposed =
@"dbug: <Local Date> HH:mm:ss.fff CoreEventId.ContextDisposed[10407] (Microsoft.EntityFrameworkCore.Infrastructure)
'LoggingContext' disposed.";
@"dbug: <Local Date> HH:mm:ss.fff CoreEventId.ContextDisposed[10407] (Microsoft.EntityFrameworkCore.Infrastructure) " +
@" 'LoggingContext' disposed.";

[ConditionalTheory]
[InlineData(true)]
Expand Down Expand Up @@ -234,7 +234,7 @@ public async Task Log_with_raw_message(bool async)

AssertLog(
actual,
@"Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -248,7 +248,7 @@ public async Task Log_raw_single_line(bool async)

AssertLog(
actual,
@"Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -265,7 +265,7 @@ public async Task Log_default_single_line(bool async)

AssertLog(
actual,
@"info: <Local Date> HH:mm:ss.fff CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure) -> Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"info: <Local Date> HH:mm:ss.fff CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure) -> Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -279,8 +279,8 @@ public async Task Log_only_level(bool async)

AssertLog(
actual,
@"info:
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"info:
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -294,8 +294,8 @@ public async Task Log_only_local_time(bool async)

AssertLog(
actual,
@"<Local Date> HH:mm:ss.fff
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"<Local Date> HH:mm:ss.fff
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -309,8 +309,8 @@ public async Task Log_only_UTC_time(bool async)

AssertLog(
actual,
@"YYYY-MM-DDTHH:MM:SS.MMMMMMTZ
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"YYYY-MM-DDTHH:MM:SS.MMMMMMTZ
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -324,8 +324,8 @@ public async Task Log_only_ID(bool async)

AssertLog(
actual,
@"CoreEventId.ContextInitialized[10403]
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"CoreEventId.ContextInitialized[10403]
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -339,8 +339,8 @@ public async Task Log_only_category(bool async)

AssertLog(
actual,
@"(Microsoft.EntityFrameworkCore.Infrastructure)
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"(Microsoft.EntityFrameworkCore.Infrastructure) " +
@" Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -355,8 +355,8 @@ public async Task Log_level_and_ID(bool async)

AssertLog(
actual,
@"info: CoreEventId.ContextInitialized[10403]
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"info: CoreEventId.ContextInitialized[10403] " +
@" Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -374,8 +374,8 @@ public async Task Log_level_and_UTC(bool async)

AssertLog(
actual,
@"info: YYYY-MM-DDTHH:MM:SS.MMMMMMTZ
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"info: YYYY-MM-DDTHH:MM:SS.MMMMMMTZ " +
@" Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

[ConditionalTheory]
Expand All @@ -390,14 +390,14 @@ public async Task Log_default_UTC(bool async)

AssertLog(
actual,
@"info: YYYY-MM-DDTHH:MM:SS.MMMMMMTZ CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContextLoggerTests ");
@"info: YYYY-MM-DDTHH:MM:SS.MMMMMMTZ CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure) " +
@" Entity Framework Core X.X.X-any initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.InMemory:X.X.X-any' with options: StoreName=DbContextLoggerTests ");
}

private static void AssertLog(string actual, params string[] lines)
=> Assert.Equal(
string.Join(Environment.NewLine, lines) + Environment.NewLine,
actual,
string.Concat(lines).ReplaceLineEndings(""),
actual.ReplaceLineEndings(""),
ignoreLineEndingDifferences: true,
ignoreWhiteSpaceDifferences: true);

Expand Down

0 comments on commit bd7220d

Please sign in to comment.