From 2782a55656b38ff31a64daca008cb663af17e099 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Mon, 29 May 2017 10:42:50 -0700 Subject: [PATCH] Add EventId, LogLevel, and message generation for event payloads Issue #7939 Also adds nominal types for all events other than those in the relational design assemblies. (Since these assemblies are currently being refactored.) Each event payload now contains all the information needed to create and log the message for the event, including overridden ToString that creates the message. --- .../Diagnostics/DesignEventId.cs | 165 +++++++++--- .../Diagnostics/MigrationDesignEventData.cs | 37 +++ .../Diagnostics/MigrationFileNameEventData.cs | 45 ++++ .../MigrationOperationsEventData.cs | 38 +++ .../ModelSnapshotFileNameEventData.cs | 45 ++++ .../Diagnostics/NamespaceEventData.cs | 36 +++ .../Diagnostics/ResourceReusedEventData.cs | 36 +++ .../ScaffoldedMigrationEventData.cs | 45 ++++ .../Diagnostics/SnapshotNameEventData.cs | 36 +++ .../Internal/DesignLoggerExtensions.cs | 212 +++++++++++----- .../Diagnostics/InMemoryEventId.cs | 22 +- .../Internal/InMemoryLoggerExtensions.cs | 24 +- .../Diagnostics/CommandEndEventData.cs | 11 +- .../Diagnostics/CommandErrorEventData.cs | 10 +- .../Diagnostics/CommandEventData.cs | 18 +- .../Diagnostics/CommandExecutedEventData.cs | 10 +- .../Diagnostics/ConnectionEndEventData.cs | 6 +- .../Diagnostics/ConnectionErrorEventData.cs | 6 +- .../Diagnostics/ConnectionEventData.cs | 7 +- .../DataReaderDisposingEventData.cs | 7 +- .../Diagnostics/EntityTypeSchemaEventData.cs | 45 ++++ .../Diagnostics/MigrationEventData.cs | 7 +- .../MigrationScriptingEventData.cs | 7 +- .../MigratorConnectionEventData.cs | 6 +- .../Diagnostics/MigratorEventData.cs | 11 +- .../Diagnostics/RelationalEventId.cs | 9 + .../Diagnostics/SequenceEventData.cs | 37 +++ .../Diagnostics/TransactionEndEventData.cs | 6 +- .../Diagnostics/TransactionErrorEventData.cs | 6 +- .../Diagnostics/TransactionEventData.cs | 7 +- .../Internal/RelationalLoggerExtensions.cs | 235 ++++++++++++++++-- src/EFCore.Specification.Tests/TestHelpers.cs | 24 +- .../Diagnostics/SqlServerEventId.cs | 22 +- .../Internal/SqlServerLoggerExtensions.cs | 35 ++- .../Diagnostics/SqliteEventId.cs | 22 +- .../Internal/SqliteLoggerExtensions.cs | 35 ++- src/EFCore/DbContext.cs | 4 +- .../Diagnostics/BinaryExpressionEventData.cs | 45 ++++ src/EFCore/Diagnostics/CoreEventId.cs | 169 +++++++++---- .../Diagnostics/DbContextErrorEventData.cs | 38 +++ src/EFCore/Diagnostics/DbContextEventData.cs | 36 +++ .../DbContextTypeErrorEventData.cs | 38 +++ .../Diagnostics/DbContextTypeEventData.cs | 36 +++ src/EFCore/Diagnostics/EventDataBase.cs | 48 ++++ src/EFCore/Diagnostics/EventDefinition.cs | 1 - src/EFCore/Diagnostics/EventDefinition`.cs | 1 - src/EFCore/Diagnostics/EventDefinition``.cs | 1 - src/EFCore/Diagnostics/EventDefinition```.cs | 1 - src/EFCore/Diagnostics/EventDefinition````.cs | 1 - .../Diagnostics/EventDefinition`````.cs | 1 - .../Diagnostics/EventDefinition``````.cs | 1 - src/EFCore/Diagnostics/IDiagnosticsLogger.cs | 1 - src/EFCore/Diagnostics/IncludeEventData.cs | 36 +++ .../Diagnostics/NavigationPathEventData.cs | 36 +++ src/EFCore/Diagnostics/PropertyEventData.cs | 37 +++ .../Diagnostics/QueryExpressionEventData.cs | 46 ++++ src/EFCore/Diagnostics/QueryModelEventData.cs | 37 +++ .../QueryModelExpressionEventData.cs | 39 +++ .../Diagnostics/SaveChangesEventData.cs | 46 ++++ .../Diagnostics/ServiceProviderEventData.cs | 36 +++ .../Diagnostics/ServiceProvidersEventData.cs | 37 +++ .../Diagnostics/WarningsConfiguration.cs | 1 - .../Internal/CoreLoggerExtensions.cs | 226 ++++++++++------- src/EFCore/Properties/CoreStrings.Designer.cs | 12 - src/EFCore/Properties/CoreStrings.resx | 4 - .../Infrastructure/CoreEventIdTest.cs | 1 + 66 files changed, 2009 insertions(+), 337 deletions(-) create mode 100644 src/EFCore.Design/Diagnostics/MigrationDesignEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/MigrationFileNameEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/MigrationOperationsEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/ModelSnapshotFileNameEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/NamespaceEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/ResourceReusedEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/ScaffoldedMigrationEventData.cs create mode 100644 src/EFCore.Design/Diagnostics/SnapshotNameEventData.cs create mode 100644 src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs create mode 100644 src/EFCore.Relational/Diagnostics/SequenceEventData.cs create mode 100644 src/EFCore/Diagnostics/BinaryExpressionEventData.cs create mode 100644 src/EFCore/Diagnostics/DbContextErrorEventData.cs create mode 100644 src/EFCore/Diagnostics/DbContextEventData.cs create mode 100644 src/EFCore/Diagnostics/DbContextTypeErrorEventData.cs create mode 100644 src/EFCore/Diagnostics/DbContextTypeEventData.cs create mode 100644 src/EFCore/Diagnostics/EventDataBase.cs create mode 100644 src/EFCore/Diagnostics/IncludeEventData.cs create mode 100644 src/EFCore/Diagnostics/NavigationPathEventData.cs create mode 100644 src/EFCore/Diagnostics/PropertyEventData.cs create mode 100644 src/EFCore/Diagnostics/QueryExpressionEventData.cs create mode 100644 src/EFCore/Diagnostics/QueryModelEventData.cs create mode 100644 src/EFCore/Diagnostics/QueryModelExpressionEventData.cs create mode 100644 src/EFCore/Diagnostics/SaveChangesEventData.cs create mode 100644 src/EFCore/Diagnostics/ServiceProviderEventData.cs create mode 100644 src/EFCore/Diagnostics/ServiceProvidersEventData.cs diff --git a/src/EFCore.Design/Diagnostics/DesignEventId.cs b/src/EFCore.Design/Diagnostics/DesignEventId.cs index a8a1c484c18..d0fc4f962ae 100644 --- a/src/EFCore.Design/Diagnostics/DesignEventId.cs +++ b/src/EFCore.Design/Diagnostics/DesignEventId.cs @@ -45,92 +45,197 @@ private enum Id private static EventId MakeMigrationsId(Id id) => new EventId((int)id, _migrationsPrefix + id); /// - /// Removing a migration without checking the database. - /// This event is in the category. + /// + /// Removing a migration without checking the database. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationForceRemove = MakeMigrationsId(Id.MigrationForceRemove); /// - /// Removing migration. - /// This event is in the category. + /// + /// Removing migration. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationRemoving = MakeMigrationsId(Id.MigrationRemoving); /// - /// A migration file was not found. - /// This event is in the category. + /// + /// A migration file was not found. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationFileNotFound = MakeMigrationsId(Id.MigrationFileNotFound); /// - /// A metadata file was not found. - /// This event is in the category. + /// + /// A metadata file was not found. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationMetadataFileNotFound = MakeMigrationsId(Id.MigrationMetadataFileNotFound); /// - /// A manual migration deletion was detected. - /// This event is in the category. + /// + /// A manual migration deletion was detected. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationManuallyDeleted = MakeMigrationsId(Id.MigrationManuallyDeleted); /// - /// Removing model snapshot. - /// This event is in the category. + /// + /// Removing model snapshot. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SnapshotRemoving = MakeMigrationsId(Id.SnapshotRemoving); /// - /// No model snapshot file named was found. - /// This event is in the category. + /// + /// No model snapshot file named was found. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SnapshotFileNotFound = MakeMigrationsId(Id.SnapshotFileNotFound); /// - /// Writing model snapshot to file. - /// This event is in the category. + /// + /// Writing model snapshot to file. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SnapshotWriting = MakeMigrationsId(Id.SnapshotWriting); /// - /// Reusing namespace of a type. - /// This event is in the category. + /// + /// Reusing namespace of a type. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId NamespaceReusing = MakeMigrationsId(Id.NamespaceReusing); /// - /// Reusing directory for a file. - /// This event is in the category. + /// + /// Reusing directory for a file. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId DirectoryReusing = MakeMigrationsId(Id.DirectoryReusing); /// - /// Reverting model snapshot. - /// This event is in the category. + /// + /// Reverting model snapshot. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SnapshotReverting = MakeMigrationsId(Id.SnapshotReverting); /// - /// Writing migration to file. - /// This event is in the category. + /// + /// Writing migration to file. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId MigrationWriting = MakeMigrationsId(Id.MigrationWriting); /// - /// Resuing model snapshot name. - /// This event is in the category. + /// + /// Resuing model snapshot name. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SnapshotNameReusing = MakeMigrationsId(Id.SnapshotNameReusing); /// - /// An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy. - /// This event is in the category. + /// + /// An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId DestructiveOperation = MakeMigrationsId(Id.DestructiveOperation); /// - /// The namespace contains migrations for a different context. - /// This event is in the category. + /// + /// The namespace contains migrations for a different context. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ForeignMigrations = MakeMigrationsId(Id.ForeignMigrations); } diff --git a/src/EFCore.Design/Diagnostics/MigrationDesignEventData.cs b/src/EFCore.Design/Diagnostics/MigrationDesignEventData.cs new file mode 100644 index 00000000000..b23b7ebe426 --- /dev/null +++ b/src/EFCore.Design/Diagnostics/MigrationDesignEventData.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an associated . + /// + public class MigrationDesignEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + public MigrationDesignEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] Migration migration) + : base(eventDefinition, messageGenerator) + { + Migration = migration; + } + + /// + /// The . + /// + public virtual Migration Migration { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Design/Diagnostics/MigrationFileNameEventData.cs b/src/EFCore.Design/Diagnostics/MigrationFileNameEventData.cs new file mode 100644 index 00000000000..1bb199cee10 --- /dev/null +++ b/src/EFCore.Design/Diagnostics/MigrationFileNameEventData.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an associated and file name. + /// + public class MigrationFileNameEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + /// The file name. + public MigrationFileNameEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] Migration migration, + [NotNull] string fileName) + : base(eventDefinition, messageGenerator) + { + Migration = migration; + FileName = fileName; + } + + /// + /// The . + /// + public virtual Migration Migration { get; } + + /// + /// The file name. + /// + public virtual string FileName { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Design/Diagnostics/MigrationOperationsEventData.cs b/src/EFCore.Design/Diagnostics/MigrationOperationsEventData.cs new file mode 100644 index 00000000000..f2e36df7c4d --- /dev/null +++ b/src/EFCore.Design/Diagnostics/MigrationOperationsEventData.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// associated s. + /// + public class MigrationOperationsEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The operations. + public MigrationOperationsEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] IEnumerable operations) + : base(eventDefinition, messageGenerator) + { + Operations = operations; + } + + /// + /// The operations. + /// + public virtual IEnumerable Operations { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Design/Diagnostics/ModelSnapshotFileNameEventData.cs b/src/EFCore.Design/Diagnostics/ModelSnapshotFileNameEventData.cs new file mode 100644 index 00000000000..60df6d3ad88 --- /dev/null +++ b/src/EFCore.Design/Diagnostics/ModelSnapshotFileNameEventData.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an associated and file name. + /// + public class ModelSnapshotFileNameEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + /// The file name. + public ModelSnapshotFileNameEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] ModelSnapshot snapshot, + [NotNull] string fileName) + : base(eventDefinition, messageGenerator) + { + Snapshot = snapshot; + FileName = fileName; + } + + /// + /// The . + /// + public virtual ModelSnapshot Snapshot { get; } + + /// + /// The file name. + /// + public virtual string FileName { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Design/Diagnostics/NamespaceEventData.cs b/src/EFCore.Design/Diagnostics/NamespaceEventData.cs new file mode 100644 index 00000000000..931155eda64 --- /dev/null +++ b/src/EFCore.Design/Diagnostics/NamespaceEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an associated namespace. + /// + public class NamespaceEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The namespace. + public NamespaceEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] string @namespace) + : base(eventDefinition, messageGenerator) + { + Namespace = @namespace; + } + + /// + /// The namespace. + /// + public virtual string Namespace { get; } + } +} diff --git a/src/EFCore.Design/Diagnostics/ResourceReusedEventData.cs b/src/EFCore.Design/Diagnostics/ResourceReusedEventData.cs new file mode 100644 index 00000000000..b63bbc1a808 --- /dev/null +++ b/src/EFCore.Design/Diagnostics/ResourceReusedEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that identify + /// a resource such as a name or filename that is being re-used. + /// + public class ResourceReusedEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The resource name. + public ResourceReusedEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] string resourceName) + : base(eventDefinition, messageGenerator) + { + ResourceName = resourceName; + } + + /// + /// The resource name. + /// + public virtual string ResourceName { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Design/Diagnostics/ScaffoldedMigrationEventData.cs b/src/EFCore.Design/Diagnostics/ScaffoldedMigrationEventData.cs new file mode 100644 index 00000000000..0c1bf972557 --- /dev/null +++ b/src/EFCore.Design/Diagnostics/ScaffoldedMigrationEventData.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Migrations.Design; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an associated and file name. + /// + public class ScaffoldedMigrationEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + /// The file name. + public ScaffoldedMigrationEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] ScaffoldedMigration scaffoldedMigration, + [NotNull] string fileName) + : base(eventDefinition, messageGenerator) + { + ScaffoldedMigration = scaffoldedMigration; + FileName = fileName; + } + + /// + /// The . + /// + public virtual ScaffoldedMigration ScaffoldedMigration { get; } + + /// + /// The file name. + /// + public virtual string FileName { get; } + } +} \ No newline at end of file diff --git a/src/EFCore.Design/Diagnostics/SnapshotNameEventData.cs b/src/EFCore.Design/Diagnostics/SnapshotNameEventData.cs new file mode 100644 index 00000000000..1810a68e68b --- /dev/null +++ b/src/EFCore.Design/Diagnostics/SnapshotNameEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an associated snapshot name. + /// + public class SnapshotNameEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The snapshot name. + public SnapshotNameEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] string snapshotName) + : base(eventDefinition, messageGenerator) + { + SnapshotName = snapshotName; + } + + /// + /// The snapshot name. + /// + public virtual string SnapshotName { get; } + } +} diff --git a/src/EFCore.Design/Internal/DesignLoggerExtensions.cs b/src/EFCore.Design/Internal/DesignLoggerExtensions.cs index bef55942a5e..bbbcf493b01 100644 --- a/src/EFCore.Design/Internal/DesignLoggerExtensions.cs +++ b/src/EFCore.Design/Internal/DesignLoggerExtensions.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -38,13 +37,20 @@ public static void ForeignMigrations( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - MigrationNamespace = migrationNamespace - }); + new NamespaceEventData( + definition, + ForeignMigrations, + migrationNamespace)); } } + private static string ForeignMigrations(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (NamespaceEventData)payload; + return d.GenerateMessage(p.Namespace); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -63,13 +69,20 @@ public static void SnapshotNameReusing( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - LastModelSnapshotName = lastModelSnapshotName - }); + new SnapshotNameEventData( + definition, + SnapshotNameReusing, + lastModelSnapshotName)); } } + private static string SnapshotNameReusing(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (SnapshotNameEventData)payload; + return d.GenerateMessage(p.SnapshotName); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -86,10 +99,10 @@ public static void DestructiveOperation( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Operations = (ICollection)operations.ToList() - }); + new MigrationOperationsEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), + operations)); } } @@ -115,13 +128,20 @@ public static void MigrationForceRemove( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Migration = migration - }); + new MigrationDesignEventData( + definition, + MigrationForceRemove, + migration)); } } + private static string MigrationForceRemove(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationDesignEventData)payload; + return d.GenerateMessage(p.Migration.GetId()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -144,13 +164,20 @@ public static void MigrationRemoving( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Migration = migration - }); + new MigrationDesignEventData( + definition, + MigrationRemoving, + migration)); } } + private static string MigrationRemoving(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationDesignEventData)payload; + return d.GenerateMessage(p.Migration.GetId()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -175,14 +202,21 @@ public static void MigrationFileNotFound( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Migration = migration, - FileName = fileName - }); + new MigrationFileNameEventData( + definition, + MigrationFileNotFound, + migration, + fileName)); } } + private static string MigrationFileNotFound(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationFileNameEventData)payload; + return d.GenerateMessage(p.FileName, p.Migration.GetType().ShortDisplayName()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -200,14 +234,21 @@ public static void MigrationMetadataFileNotFound( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Migration = migration, - FileName = fileName - }); + new MigrationFileNameEventData( + definition, + MigrationMetadataFileNotFound, + migration, + fileName)); } } + private static string MigrationMetadataFileNotFound(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationFileNameEventData)payload; + return d.GenerateMessage(p.FileName); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -224,10 +265,10 @@ public static void MigrationManuallyDeleted( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Migration = migration - }); + new MigrationDesignEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), + migration)); } } @@ -248,11 +289,11 @@ public static void SnapshotRemoving( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ModelSnapshot = modelSnapshot, - FileName = fileName - }); + new ModelSnapshotFileNameEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), + modelSnapshot, + fileName)); } } @@ -280,14 +321,21 @@ public static void SnapshotFileNotFound( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ModelSnapshot = modelSnapshot, - FileName = fileName - }); + new ModelSnapshotFileNameEventData( + definition, + SnapshotFileNotFound, + modelSnapshot, + fileName)); } } + private static string SnapshotFileNotFound(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ModelSnapshotFileNameEventData)payload; + return d.GenerateMessage(p.FileName, p.Snapshot.GetType().ShortDisplayName()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -305,11 +353,11 @@ public static void SnapshotReverting( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ModelSnapshot = modelSnapshot, - FileName = fileName - }); + new ModelSnapshotFileNameEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), + modelSnapshot, + fileName)); } } @@ -330,14 +378,21 @@ public static void MigrationWriting( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ScaffoldedMigration = scaffoldedMigration, - FileName = fileName - }); + new ScaffoldedMigrationEventData( + definition, + MigrationWriting, + scaffoldedMigration, + fileName)); } } + private static string MigrationWriting(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ScaffoldedMigrationEventData)payload; + return d.GenerateMessage(p.FileName); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -355,14 +410,21 @@ public static void SnapshotWriting( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ScaffoldedMigration = scaffoldedMigration, - FileName = fileName - }); + new ScaffoldedMigrationEventData( + definition, + SnapshotWriting, + scaffoldedMigration, + fileName)); } } + private static string SnapshotWriting(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ScaffoldedMigrationEventData)payload; + return d.GenerateMessage(p.FileName); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -383,13 +445,20 @@ public static void NamespaceReusing( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Type = type - }); + new ResourceReusedEventData( + definition, + NamespaceReusing, + type.ShortDisplayName())); } } + private static string NamespaceReusing(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ResourceReusedEventData)payload; + return d.GenerateMessage(p.ResourceName); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -406,11 +475,18 @@ public static void DirectoryReusing( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - FileName = fileName - }); + new ResourceReusedEventData( + definition, + DirectoryReusing, + fileName)); } } + + private static string DirectoryReusing(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ResourceReusedEventData)payload; + return d.GenerateMessage(p.ResourceName); + } } } diff --git a/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs b/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs index 6b656f1c4c6..6f5878efcd1 100644 --- a/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs +++ b/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs @@ -34,8 +34,15 @@ private enum Id private static EventId MakeTransactionId(Id id) => new EventId((int)id, _transactionPrefix + id); /// - /// Changes were saved to the database. - /// This event is in the category. + /// + /// Changes were saved to the database. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId TransactionIgnoredWarning = MakeTransactionId(Id.TransactionIgnoredWarning); @@ -43,8 +50,15 @@ private enum Id private static EventId MakeUpdateId(Id id) => new EventId((int)id, _updatePrefix + id); /// - /// A transaction operation was requested, but ignored because in-memory does not support transactions. - /// This event is in the category. + /// + /// A transaction operation was requested, but ignored because in-memory does not support transactions. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ChangesSaved = MakeUpdateId(Id.ChangesSaved); } diff --git a/src/EFCore.InMemory/Extensions/Internal/InMemoryLoggerExtensions.cs b/src/EFCore.InMemory/Extensions/Internal/InMemoryLoggerExtensions.cs index 70e9c8c3358..c7bbb250bff 100644 --- a/src/EFCore.InMemory/Extensions/Internal/InMemoryLoggerExtensions.cs +++ b/src/EFCore.InMemory/Extensions/Internal/InMemoryLoggerExtensions.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Update; // ReSharper disable once CheckNamespace @@ -29,7 +28,11 @@ public static void TransactionIgnoredWarning( if (diagnostics.DiagnosticSource.IsEnabled(definition.EventId.Name)) { - diagnostics.DiagnosticSource.Write(definition.EventId.Name, null); + diagnostics.DiagnosticSource.Write( + definition.EventId.Name, + new EventDataBase( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage())); } } @@ -50,12 +53,19 @@ public static void ChangesSaved( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Entries = entries, - RowsAffected = rowsAffected - }); + new SaveChangesEventData( + definition, + ChangesSaved, + entries, + rowsAffected)); } } + + private static string ChangesSaved(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (SaveChangesEventData)payload; + return d.GenerateMessage(p.RowsAffected); + } } } diff --git a/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs b/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs index 731f5f937f3..ab24c1c7b98 100644 --- a/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs @@ -5,7 +5,6 @@ using System.Data.Common; using System.Diagnostics; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.Diagnostics { @@ -18,6 +17,8 @@ public class CommandEndEventData : CommandEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -33,6 +34,9 @@ public class CommandEndEventData : CommandEventData /// /// Indicates whether or not the command was executed asyncronously. /// + /// + /// Indicates whether or not the application allows logging of parameter values. + /// /// /// The start time of this event. /// @@ -40,14 +44,17 @@ public class CommandEndEventData : CommandEventData /// The duration this event. /// public CommandEndEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, + bool logParameterValues, DateTimeOffset startTime, TimeSpan duration) - : base(command, executeMethod, commandId, connectionId, async, startTime) + : base(eventDefinition, messageGenerator, command, executeMethod, commandId, connectionId, async, logParameterValues, startTime) => Duration = duration; /// diff --git a/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs b/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs index dc70d04d7a7..e473ecef053 100644 --- a/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs @@ -16,6 +16,8 @@ public class CommandErrorEventData : CommandEndEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The that was executing when it failed. /// @@ -34,6 +36,9 @@ public class CommandErrorEventData : CommandEndEventData /// /// Indicates whether or not the command was executed asyncronously. /// + /// + /// Indicates whether or not the application allows logging of parameter values. + /// /// /// The start time of this event. /// @@ -41,15 +46,18 @@ public class CommandErrorEventData : CommandEndEventData /// The duration this event. /// public CommandErrorEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, [NotNull] Exception exception, bool async, + bool logParameterValues, DateTimeOffset startTime, TimeSpan duration) - : base(command, executeMethod, commandId, connectionId, async, startTime, duration) + : base(eventDefinition, messageGenerator, command, executeMethod, commandId, connectionId, async, logParameterValues, startTime, duration) => Exception = exception; /// diff --git a/src/EFCore.Relational/Diagnostics/CommandEventData.cs b/src/EFCore.Relational/Diagnostics/CommandEventData.cs index bb2c5f8baa8..b088fe1b631 100644 --- a/src/EFCore.Relational/Diagnostics/CommandEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandEventData.cs @@ -5,7 +5,6 @@ using System.Data.Common; using System.Diagnostics; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.Diagnostics { @@ -13,11 +12,13 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// command events. /// - public class CommandEventData + public class CommandEventData : EventDataBase { /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -33,22 +34,30 @@ public class CommandEventData /// /// Indicates whether or not the command was executed asyncronously. /// + /// + /// Indicates whether or not the application allows logging of parameter values. + /// /// /// The start time of this event. /// public CommandEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, + bool logParameterValues, DateTimeOffset startTime) + : base(eventDefinition, messageGenerator) { Command = command; CommandId = commandId; ConnectionId = connectionId; ExecuteMethod = executeMethod; IsAsync = async; + LogParameterValues = logParameterValues; StartTime = startTime; } @@ -77,6 +86,11 @@ public CommandEventData( /// public virtual bool IsAsync { get; } + /// + /// Indicates whether or not the application allows logging of parameter values. + /// + public virtual bool LogParameterValues { get; } + /// /// The start time of this event. /// diff --git a/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs b/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs index c56c69d37dd..cc4b9e7d6ee 100644 --- a/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs @@ -16,6 +16,8 @@ public class CommandExecutedEventData : CommandEndEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The that was executing when it failed. /// @@ -34,6 +36,9 @@ public class CommandExecutedEventData : CommandEndEventData /// /// Indicates whether or not the command was executed asyncronously. /// + /// + /// Indicates whether or not the application allows logging of parameter values. + /// /// /// The start time of this event. /// @@ -41,15 +46,18 @@ public class CommandExecutedEventData : CommandEndEventData /// The duration this event. /// public CommandExecutedEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, [CanBeNull] object result, bool async, + bool logParameterValues, DateTimeOffset startTime, TimeSpan duration) - : base(command, executeMethod, commandId, connectionId, async, startTime, duration) + : base(eventDefinition, messageGenerator, command, executeMethod, commandId, connectionId, async, logParameterValues, startTime, duration) => Result = result; /// diff --git a/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs b/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs index d6e8b0beac1..71a995be551 100644 --- a/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs +++ b/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs @@ -17,6 +17,8 @@ public class ConnectionEndEventData : ConnectionEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -33,12 +35,14 @@ public class ConnectionEndEventData : ConnectionEventData /// The duration this event. /// public ConnectionEndEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbConnection connection, Guid connectionId, bool async, DateTimeOffset startTime, TimeSpan duration) - : base(connection, connectionId, async, startTime) + : base(eventDefinition, messageGenerator, connection, connectionId, async, startTime) => Duration = duration; /// diff --git a/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs b/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs index 49c4210b5ec..18ff827b034 100644 --- a/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs @@ -16,6 +16,8 @@ public class ConnectionErrorEventData : ConnectionEndEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -35,13 +37,15 @@ public class ConnectionErrorEventData : ConnectionEndEventData /// The duration this event. /// public ConnectionErrorEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbConnection connection, Guid connectionId, [NotNull] Exception exception, bool async, DateTimeOffset startTime, TimeSpan duration) - : base(connection, connectionId, async, startTime, duration) + : base(eventDefinition, messageGenerator, connection, connectionId, async, startTime, duration) => Exception = exception; /// diff --git a/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs b/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs index fe039861347..9397b34f6c5 100644 --- a/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs +++ b/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs @@ -12,11 +12,13 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// connection events. /// - public class ConnectionEventData + public class ConnectionEventData : EventDataBase { /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -30,10 +32,13 @@ public class ConnectionEventData /// The start time of this event. /// public ConnectionEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbConnection connection, Guid connectionId, bool async, DateTimeOffset startTime) + : base(eventDefinition, messageGenerator) { Connection = connection; ConnectionId = connectionId; diff --git a/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs b/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs index 88e8191295c..96c371dc74a 100644 --- a/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs +++ b/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs @@ -11,11 +11,13 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// event payload for . /// - public class DataReaderDisposingEventData + public class DataReaderDisposingEventData : EventDataBase { /// /// Constructs a event payload for . /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The that created the reader. /// @@ -38,6 +40,8 @@ public class DataReaderDisposingEventData /// The duration this event. /// public DataReaderDisposingEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbCommand command, [NotNull] DbDataReader dataReader, Guid commandId, @@ -45,6 +49,7 @@ public DataReaderDisposingEventData( int recordsAffected, DateTimeOffset startTime, TimeSpan duration) + : base(eventDefinition, messageGenerator) { Command = command; DataReader = dataReader; diff --git a/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs b/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs new file mode 100644 index 00000000000..7cb60e5a47b --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload base class for events that + /// reference an entity type and a schema + /// + public class EntityTypeSchemaEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The entity type. + /// The schema. + public EntityTypeSchemaEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] IEntityType entityType, + [NotNull] string schema) + : base(eventDefinition, messageGenerator) + { + EntityType = entityType; + Schema = schema; + } + + /// + /// The entity type. + /// + public virtual IEntityType EntityType { get; } + + /// + /// The schema. + /// + public virtual string Schema { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/MigrationEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationEventData.cs index 9f53f0a01b7..45aef77f895 100644 --- a/src/EFCore.Relational/Diagnostics/MigrationEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigrationEventData.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Diagnostics; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Migrations; @@ -16,6 +17,8 @@ public class MigrationEventData : MigratorEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The in use. /// @@ -23,9 +26,11 @@ public class MigrationEventData : MigratorEventData /// The being processed. /// public MigrationEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] IMigrator migrator, [NotNull] Migration migration) - : base(migrator) + : base(eventDefinition, messageGenerator, migrator) { Migration = migration; } diff --git a/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs index 5af47cbfee1..7e31a0d8bcf 100644 --- a/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Diagnostics; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Migrations; @@ -16,6 +17,8 @@ public class MigrationScriptingEventData : MigrationEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The in use. /// @@ -32,12 +35,14 @@ public class MigrationScriptingEventData : MigrationEventData /// Indicates whether or not the script is idempotent. /// public MigrationScriptingEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] IMigrator migrator, [NotNull] Migration migration, [CanBeNull] string fromMigration, [CanBeNull] string toMigration, bool idempotent) - : base(migrator, migration) + : base(eventDefinition, messageGenerator, migrator, migration) { FromMigration = fromMigration; ToMigration = toMigration; diff --git a/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs b/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs index c7007b19586..bd31dec717e 100644 --- a/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs @@ -18,6 +18,8 @@ public class MigratorConnectionEventData : MigratorEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The in use. /// @@ -28,10 +30,12 @@ public class MigratorConnectionEventData : MigratorEventData /// A correlation ID that identifies the instance being used. /// public MigratorConnectionEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] IMigrator migrator, [NotNull] DbConnection connection, Guid connectionId) - : base(migrator) + : base(eventDefinition, messageGenerator, migrator) { Connection = connection; ConnectionId = connectionId; diff --git a/src/EFCore.Relational/Diagnostics/MigratorEventData.cs b/src/EFCore.Relational/Diagnostics/MigratorEventData.cs index 784127dd002..844d04895f9 100644 --- a/src/EFCore.Relational/Diagnostics/MigratorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigratorEventData.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Diagnostics; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Migrations; @@ -11,15 +12,21 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// migration events. /// - public class MigratorEventData + public class MigratorEventData : EventDataBase { /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The in use. /// - public MigratorEventData([NotNull] IMigrator migrator) + public MigratorEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] IMigrator migrator) + : base(eventDefinition, messageGenerator) { Migrator = migrator; } diff --git a/src/EFCore.Relational/Diagnostics/RelationalEventId.cs b/src/EFCore.Relational/Diagnostics/RelationalEventId.cs index 3e19ab3df8a..ea1df092d94 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalEventId.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalEventId.cs @@ -357,6 +357,9 @@ private enum Id /// /// This event is in the category. /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId QueryClientEvaluationWarning = MakeQueryId(Id.QueryClientEvaluationWarning); @@ -367,6 +370,9 @@ private enum Id /// /// This event is in the category. /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId QueryPossibleUnintendedUseOfEqualsWarning = MakeQueryId(Id.QueryPossibleUnintendedUseOfEqualsWarning); @@ -380,6 +386,9 @@ private enum Id /// /// This event is in the category. /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ModelValidationKeyDefaultValueWarning = MakeValidationId(Id.ModelValidationKeyDefaultValueWarning); } diff --git a/src/EFCore.Relational/Diagnostics/SequenceEventData.cs b/src/EFCore.Relational/Diagnostics/SequenceEventData.cs new file mode 100644 index 00000000000..39da05e8052 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/SequenceEventData.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload base class for events that + /// reference a sequence. + /// + public class SequenceEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The sequence. + public SequenceEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] ISequence sequence) + : base(eventDefinition, messageGenerator) + { + Sequence = sequence; + } + + /// + /// The sequence. + /// + public virtual ISequence Sequence { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs index f213cb19428..0d4fedc551a 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs @@ -17,6 +17,8 @@ public class TransactionEndEventData : TransactionEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -33,12 +35,14 @@ public class TransactionEndEventData : TransactionEventData /// The duration this event. /// public TransactionEndEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbTransaction transaction, Guid transactionId, Guid connectionId, DateTimeOffset startTime, TimeSpan duration) - : base(transaction, transactionId, connectionId, startTime) + : base(eventDefinition, messageGenerator, transaction, transactionId, connectionId, startTime) => Duration = duration; /// diff --git a/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs index 8623b51c121..d207f3e23d9 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs @@ -14,6 +14,8 @@ public class TransactionErrorEventData : TransactionEndEventData /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -36,6 +38,8 @@ public class TransactionErrorEventData : TransactionEndEventData /// The duration this event. /// public TransactionErrorEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbTransaction transaction, Guid transactionId, Guid connectionId, @@ -43,7 +47,7 @@ public TransactionErrorEventData( [NotNull] Exception exception, DateTimeOffset startTime, TimeSpan duration) - : base(transaction, transactionId, connectionId, startTime, duration) + : base(eventDefinition, messageGenerator, transaction, transactionId, connectionId, startTime, duration) { Action = action; Exception = exception; diff --git a/src/EFCore.Relational/Diagnostics/TransactionEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionEventData.cs index 8c294bc1c44..53d8ec95dfc 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionEventData.cs @@ -12,11 +12,13 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// transaction events. /// - public class TransactionEventData + public class TransactionEventData : EventDataBase { /// /// Constructs the event payload. /// + /// The event definition. + /// A delegate that generates a log message for this event. /// /// The . /// @@ -30,10 +32,13 @@ public class TransactionEventData /// The start time of this event. /// public TransactionEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, [NotNull] DbTransaction transaction, Guid transactionId, Guid connectionId, DateTimeOffset startTime) + : base(eventDefinition, messageGenerator) { Transaction = transaction; TransactionId = transactionId; diff --git a/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs b/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs index da746bf4605..e02651327ff 100644 --- a/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs +++ b/src/EFCore.Relational/Internal/RelationalLoggerExtensions.cs @@ -2,12 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Data; using System.Data.Common; using System.Globalization; using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Migrations; @@ -56,15 +56,30 @@ public static void CommandExecuting( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new CommandEventData( + definition, + CommandExecuting, command, executeMethod, commandId, connectionId, async, + ShouldLogParameterValues(diagnostics, command), startTime)); } } + private static string CommandExecuting(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (CommandEventData)payload; + return d.GenerateMessage( + p.Command.Parameters.FormatParameters(p.LogParameterValues), + p.Command.CommandType, + p.Command.CommandTimeout, + Environment.NewLine, + p.Command.CommandText.TrimEnd()); + } + private static bool ShouldLogParameterValues( IDiagnosticsLogger diagnostics, DbCommand command) @@ -106,17 +121,33 @@ public static void CommandExecuted( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new CommandExecutedEventData( + definition, + CommandExecuted, command, executeMethod, commandId, connectionId, methodResult, async, + ShouldLogParameterValues(diagnostics, command), startTime, duration)); } } + private static string CommandExecuted(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (CommandExecutedEventData)payload; + return d.GenerateMessage( + string.Format(CultureInfo.InvariantCulture, "{0:N0}", p.Duration.Milliseconds), + p.Command.Parameters.FormatParameters(p.LogParameterValues), + p.Command.CommandType, + p.Command.CommandTimeout, + Environment.NewLine, + p.Command.CommandText.TrimEnd()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -153,17 +184,34 @@ public static void CommandError( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new CommandErrorEventData( + definition, + CommandError, command, executeMethod, commandId, connectionId, exception, async, + ShouldLogParameterValues(diagnostics, command), startTime, duration)); } } + private static string CommandError(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (CommandErrorEventData)payload; + return d.GenerateMessage( + string.Format(CultureInfo.InvariantCulture, "{0:N0}", p.Duration.Milliseconds), + p.Command.Parameters.FormatParameters(p.LogParameterValues), + p.Command.CommandType, + p.Command.CommandTimeout, + Environment.NewLine, + p.Command.CommandText.TrimEnd(), + p.Exception); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -190,6 +238,8 @@ public static void ConnectionOpening( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new ConnectionEventData( + definition, + ConnectionOpening, connection.DbConnection, connection.ConnectionId, async, @@ -197,6 +247,15 @@ public static void ConnectionOpening( } } + private static string ConnectionOpening(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ConnectionEventData)payload; + return d.GenerateMessage( + p.Connection.Database, + p.Connection.DataSource); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -224,6 +283,8 @@ public static void ConnectionOpened( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new ConnectionEndEventData( + definition, + ConnectionOpened, connection.DbConnection, connection.ConnectionId, async, @@ -232,6 +293,15 @@ public static void ConnectionOpened( } } + private static string ConnectionOpened(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ConnectionEndEventData)payload; + return d.GenerateMessage( + p.Connection.Database, + p.Connection.DataSource); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -257,6 +327,8 @@ public static void ConnectionClosing( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new ConnectionEventData( + definition, + ConnectionClosing, connection.DbConnection, connection.ConnectionId, false, @@ -264,6 +336,15 @@ public static void ConnectionClosing( } } + private static string ConnectionClosing(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ConnectionEventData)payload; + return d.GenerateMessage( + p.Connection.Database, + p.Connection.DataSource); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -290,6 +371,8 @@ public static void ConnectionClosed( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new ConnectionEndEventData( + definition, + ConnectionClosed, connection.DbConnection, connection.ConnectionId, false, @@ -298,6 +381,15 @@ public static void ConnectionClosed( } } + private static string ConnectionClosed(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ConnectionEndEventData)payload; + return d.GenerateMessage( + p.Connection.Database, + p.Connection.DataSource); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -327,6 +419,8 @@ public static void ConnectionError( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new ConnectionErrorEventData( + definition, + ConnectionError, connection.DbConnection, connection.ConnectionId, exception, @@ -336,6 +430,15 @@ public static void ConnectionError( } } + private static string ConnectionError(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (ConnectionErrorEventData)payload; + return d.GenerateMessage( + p.Connection.Database, + p.Connection.DataSource); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -358,6 +461,8 @@ public static void TransactionStarted( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new TransactionEventData( + definition, + TransactionStarted, transaction, transactionId, connection.ConnectionId, @@ -365,6 +470,14 @@ public static void TransactionStarted( } } + private static string TransactionStarted(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (TransactionEventData)payload; + return d.GenerateMessage( + p.Transaction.IsolationLevel.ToString("G")); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -387,6 +500,8 @@ public static void TransactionUsed( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new TransactionEventData( + definition, + TransactionUsed, transaction, transactionId, connection.ConnectionId, @@ -394,6 +509,14 @@ public static void TransactionUsed( } } + private static string TransactionUsed(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (TransactionEventData)payload; + return d.GenerateMessage( + p.Transaction.IsolationLevel.ToString("G")); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -415,6 +538,8 @@ public static void TransactionCommitted( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new TransactionEndEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), transaction, transactionId, connection.ConnectionId, @@ -444,6 +569,8 @@ public static void TransactionRolledBack( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new TransactionEndEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), transaction, transactionId, connection.ConnectionId, @@ -472,6 +599,8 @@ public static void TransactionDisposed( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new TransactionEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), transaction, transactionId, connection.ConnectionId, @@ -502,6 +631,8 @@ public static void TransactionError( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new TransactionErrorEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), transaction, connection.ConnectionId, transactionId, @@ -530,6 +661,8 @@ public static void AmbientTransactionWarning( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new ConnectionEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), connection.DbConnection, connection.ConnectionId, false, @@ -560,6 +693,8 @@ public static void DataReaderDisposing( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new DataReaderDisposingEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), command, dataReader, commandId, @@ -597,12 +732,23 @@ public static void MigrateUsingConnection( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new MigratorConnectionEventData( + definition, + MigrateUsingConnection, migrator, connection.DbConnection, connection.ConnectionId)); } } + private static string MigrateUsingConnection(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigratorConnectionEventData)payload; + return d.GenerateMessage( + p.Connection.Database, + p.Connection.DataSource); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -627,11 +773,20 @@ public static void MigrationReverting( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new MigrationEventData( + definition, + MigrationReverting, migrator, migration)); } } + private static string MigrationReverting(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationEventData)payload; + return d.GenerateMessage(p.Migration.GetId()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -656,11 +811,20 @@ public static void MigrationApplying( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new MigrationEventData( + definition, + MigrationApplying, migrator, migration)); } } + private static string MigrationApplying(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationEventData)payload; + return d.GenerateMessage(p.Migration.GetId()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -688,6 +852,8 @@ public static void MigrationGeneratingDownScript( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new MigrationScriptingEventData( + definition, + MigrationGeneratingDownScript, migrator, migration, fromMigration, @@ -696,6 +862,13 @@ public static void MigrationGeneratingDownScript( } } + private static string MigrationGeneratingDownScript(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationScriptingEventData)payload; + return d.GenerateMessage(p.Migration.GetId()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -723,6 +896,8 @@ public static void MigrationGeneratingUpScript( diagnostics.DiagnosticSource.Write( definition.EventId.Name, new MigrationScriptingEventData( + definition, + MigrationGeneratingUpScript, migrator, migration, fromMigration, @@ -731,6 +906,13 @@ public static void MigrationGeneratingUpScript( } } + private static string MigrationGeneratingUpScript(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (MigrationScriptingEventData)payload; + return d.GenerateMessage(p.Migration.GetId()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -748,14 +930,21 @@ public static void QueryClientEvaluationWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - QueryModel = queryModel, - Expression = expression - }); + new QueryModelExpressionEventData( + definition, + QueryClientEvaluationWarning, + queryModel, + expression)); } } + private static string QueryClientEvaluationWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (QueryModelExpressionEventData)payload; + return d.GenerateMessage(p.Expression); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -776,14 +965,21 @@ public static void QueryPossibleUnintendedUseOfEqualsWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - MethodCallExpression = methodCallExpression, - Argument = argument - }); + new BinaryExpressionEventData( + definition, + QueryPossibleUnintendedUseOfEqualsWarning, + methodCallExpression.Object, + argument)); } } + private static string QueryPossibleUnintendedUseOfEqualsWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (BinaryExpressionEventData)payload; + return d.GenerateMessage(p.Left, p.Right); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -807,11 +1003,20 @@ public static void ModelValidationKeyDefaultValueWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Property = property - }); + new PropertyEventData( + definition, + ModelValidationKeyDefaultValueWarning, + property)); } } + + private static string ModelValidationKeyDefaultValueWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (PropertyEventData)payload; + return d.GenerateMessage( + p.Property.Name, + p.Property.DeclaringEntityType.DisplayName()); + } } } diff --git a/src/EFCore.Specification.Tests/TestHelpers.cs b/src/EFCore.Specification.Tests/TestHelpers.cs index 5e4defecb73..1daad1191fa 100644 --- a/src/EFCore.Specification.Tests/TestHelpers.cs +++ b/src/EFCore.Specification.Tests/TestHelpers.cs @@ -87,7 +87,9 @@ public void TestEventLogging( .ToList(); var declaredMethods = loggerExtensionsType.GetTypeInfo() - .DeclaredMethods.OrderBy(e => e.Name) + .DeclaredMethods + .Where(m => m.IsPublic) + .OrderBy(e => e.Name) .ToList(); var loggerMethods = declaredMethods @@ -150,7 +152,7 @@ public void TestEventLogging( { testLogger.EnabledFor = logLevel; testLogger.LoggedAt = null; - testDiagnostics.Logged = null; + testDiagnostics.LoggedEventName = null; loggerMethod.Invoke(null, args); @@ -162,11 +164,15 @@ public void TestEventLogging( if (enableFor == eventId.Name) { - Assert.Equal(eventId.Name, testDiagnostics.Logged); + Assert.Equal(eventId.Name, testDiagnostics.LoggedEventName); + if (testDiagnostics.LoggedMessage != null) + { + Assert.Equal(testLogger.Message, testDiagnostics.LoggedMessage); + } } else { - Assert.Null(testDiagnostics.Logged); + Assert.Null(testDiagnostics.LoggedEventName); } } @@ -178,10 +184,9 @@ public void TestEventLogging( private class TestLoggerBase { public LogLevel EnabledFor { get; set; } - public LogLevel? LoggedAt { get; set; } - public EventId LoggedEvent { get; set; } + public string Message { get; set; } public DiagnosticSource DiagnosticSource { get; } = new TestDiagnosticSource(); } @@ -205,6 +210,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except { LoggedAt = logLevel; Assert.Equal(LoggedEvent, eventId); + Message = formatter(state, exception); } public bool ShouldLogSensitiveData() => false; @@ -215,11 +221,13 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except private class TestDiagnosticSource : DiagnosticSource { public string EnableFor { get; set; } - public string Logged { get; set; } + public string LoggedEventName { get; set; } + public string LoggedMessage { get; set; } public override void Write(string name, object value) { - Logged = name; + LoggedEventName = name; + LoggedMessage = (value as EventDataBase)?.ToString(); } public override bool IsEnabled(string name) => name == EnableFor; diff --git a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs index f18d5fe1ba4..9199648dd17 100644 --- a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs +++ b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs @@ -32,14 +32,28 @@ private enum Id private static EventId MakeValidationId(Id id) => new EventId((int)id, _validationPrefix + id); /// - /// No explicit type for a decimal column. - /// This event is in the category. + /// + /// No explicit type for a decimal column. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId DecimalTypeDefaultWarning = MakeValidationId(Id.DecimalTypeDefaultWarning); /// - /// A byte property is set up to use a SQL Server identity column. - /// This event is in the category. + /// + /// A byte property is set up to use a SQL Server identity column. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ByteIdentityColumnWarning = MakeValidationId(Id.ByteIdentityColumnWarning); } diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerLoggerExtensions.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerLoggerExtensions.cs index 501e0e0a828..88e321f7fa5 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerLoggerExtensions.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerLoggerExtensions.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -35,13 +34,22 @@ public static void DecimalTypeDefaultWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Property = property - }); + new PropertyEventData( + definition, + DecimalTypeDefaultWarning, + property)); } } + private static string DecimalTypeDefaultWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (PropertyEventData)payload; + return d.GenerateMessage( + p.Property.Name, + p.Property.DeclaringEntityType.DisplayName()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -62,11 +70,20 @@ public static void ByteIdentityColumnWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Property = property - }); + new PropertyEventData( + definition, + ByteIdentityColumnWarning, + property)); } } + + private static string ByteIdentityColumnWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (PropertyEventData)payload; + return d.GenerateMessage( + p.Property.Name, + p.Property.DeclaringEntityType.DisplayName()); + } } } diff --git a/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs b/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs index 82686ff2aac..381dcf2b23e 100644 --- a/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs +++ b/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs @@ -32,14 +32,28 @@ private enum Id private static EventId MakeValidationId(Id id) => new EventId((int)id, _validationPrefix + id); /// - /// A schema was configured for an entity type, but SQLite does not support schemas. - /// This event is in the category. + /// + /// A schema was configured for an entity type, but SQLite does not support schemas. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SchemaConfiguredWarning = MakeValidationId(Id.SchemaConfiguredWarning); /// - /// A sequence was configured for an entity type, but SQLite does not support sequences. - /// This event is in the category. + /// + /// A sequence was configured for an entity type, but SQLite does not support sequences. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SequenceConfiguredWarning = MakeValidationId(Id.SequenceConfiguredWarning); } diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteLoggerExtensions.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteLoggerExtensions.cs index a3c686a8f39..1540216b096 100644 --- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteLoggerExtensions.cs +++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteLoggerExtensions.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -32,14 +31,23 @@ public static void SchemaConfiguredWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - EntityType = entityType, - Schema = schema - }); + new EntityTypeSchemaEventData( + definition, + SchemaConfiguredWarning, + entityType, + schema)); } } + private static string SchemaConfiguredWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (EntityTypeSchemaEventData)payload; + return d.GenerateMessage( + p.EntityType.DisplayName(), + p.Schema); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -56,11 +64,18 @@ public static void SequenceConfiguredWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Sequence = sequence - }); + new SequenceEventData( + definition, + SequenceConfiguredWarning, + sequence)); } } + + private static string SequenceConfiguredWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (SequenceEventData)payload; + return d.GenerateMessage(p.Sequence.Name); + } } } diff --git a/src/EFCore/DbContext.cs b/src/EFCore/DbContext.cs index df203d5148f..5eab0b01510 100644 --- a/src/EFCore/DbContext.cs +++ b/src/EFCore/DbContext.cs @@ -335,7 +335,7 @@ public virtual int SaveChanges(bool acceptAllChangesOnSuccess) } catch (Exception exception) { - _updateLogger.SaveChangesFailed(GetType(), exception); + _updateLogger.SaveChangesFailed(this, exception); throw; } @@ -407,7 +407,7 @@ public virtual async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, } catch (Exception exception) { - _updateLogger.SaveChangesFailed(GetType(), exception); + _updateLogger.SaveChangesFailed(this, exception); throw; } diff --git a/src/EFCore/Diagnostics/BinaryExpressionEventData.cs b/src/EFCore/Diagnostics/BinaryExpressionEventData.cs new file mode 100644 index 00000000000..90926c2f7b7 --- /dev/null +++ b/src/EFCore/Diagnostics/BinaryExpressionEventData.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Linq.Expressions; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// a query expression. + /// + public class BinaryExpressionEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The left . + /// The right . + public BinaryExpressionEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] Expression left, + [NotNull] Expression right) + : base(eventDefinition, messageGenerator) + { + Left = left; + Right = right; + } + + /// + /// The left . + /// + public virtual Expression Left { get; } + + /// + /// The right . + /// + public virtual Expression Right { get; } + } +} diff --git a/src/EFCore/Diagnostics/CoreEventId.cs b/src/EFCore/Diagnostics/CoreEventId.cs index e2b99eceaeb..97567680037 100644 --- a/src/EFCore/Diagnostics/CoreEventId.cs +++ b/src/EFCore/Diagnostics/CoreEventId.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.Logging; namespace Microsoft.EntityFrameworkCore.Diagnostics @@ -48,7 +47,7 @@ public static class CoreEventId /// The lower-bound for event IDs used only by database provider design-time and tooling. /// public const int ProviderDesignBaseId = 350000; - + // Warning: These values must not change between releases. // Only add new values to the end of sections, never in the middle. // Try to use naming and be consistent with existing names. @@ -69,9 +68,6 @@ private enum Id PossibleUnintendedCollectionNavigationNullComparisonWarning, PossibleUnintendedReferenceComparisonWarning, - // Model validation events - ModelValidationShadowKeyWarning = CoreBaseId + 300, - // Infrastucture events SensitiveDataLoggingEnabledWarning = CoreBaseId + 400, ServiceProviderCreated, @@ -82,8 +78,15 @@ private enum Id private static EventId MakeUpdateId(Id id) => new EventId((int)id, _updatePrefix + id); /// - /// An error occurred while attempting to save changes to the database. - /// This event is in the category. + /// + /// An error occurred while attempting to save changes to the database. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SaveChangesFailed = MakeUpdateId(Id.SaveChangesFailed); @@ -91,94 +94,176 @@ private enum Id private static EventId MakeQueryId(Id id) => new EventId((int)id, _queryPrefix + id); /// - /// An error occurred while processing the results of a query. - /// This event is in the category. + /// + /// An error occurred while processing the results of a query. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId QueryIterationFailed = MakeQueryId(Id.QueryIterationFailed); /// - /// A query model is being compiled. - /// This event is in the category. + /// + /// A query model is being compiled. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId QueryModelCompiling = MakeQueryId(Id.QueryModelCompiling); /// - /// A query uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results. - /// This event is in the category. + /// + /// A query uses a row limiting operation (Skip/Take) without OrderBy which may lead to unpredictable results. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId RowLimitingOperationWithoutOrderByWarning = MakeQueryId(Id.RowLimitingOperationWithoutOrderByWarning); /// - /// A query uses First/FirstOrDefault operation without OrderBy and filter which may lead to unpredictable results. - /// This event is in the category. + /// + /// A query uses First/FirstOrDefault operation without OrderBy and filter which may lead to unpredictable results. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId FirstWithoutOrderByAndFilterWarning = MakeQueryId(Id.FirstWithoutOrderByAndFilterWarning); /// - /// A query model was optimized. - /// This event is in the category. + /// + /// A query model was optimized. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId QueryModelOptimized = MakeQueryId(Id.QueryModelOptimized); /// - /// A navigation was included in the query. - /// This event is in the category. + /// + /// A navigation was included in the query. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId NavigationIncluded = MakeQueryId(Id.NavigationIncluded); /// - /// A navigation was ignored while compiling a query. - /// This event is in the category. + /// + /// A navigation was ignored while compiling a query. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId IncludeIgnoredWarning = MakeQueryId(Id.IncludeIgnoredWarning); /// - /// A query is planned for execution. - /// This event is in the category. + /// + /// A query is planned for execution. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId QueryExecutionPlanned = MakeQueryId(Id.QueryExecutionPlanned); /// - /// Possible uninteded comparison of collection navigation to null. - /// This event is in the category. + /// + /// Possible uninteded comparison of collection navigation to null. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId PossibleUnintendedCollectionNavigationNullComparisonWarning = MakeQueryId(Id.PossibleUnintendedCollectionNavigationNullComparisonWarning); /// - /// Possible uninteded reference comparison. - /// This event is in the category. + /// + /// Possible uninteded reference comparison. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId PossibleUnintendedReferenceComparisonWarning = MakeQueryId(Id.PossibleUnintendedReferenceComparisonWarning); - private static readonly string _validationPrefix = DbLoggerCategory.Model.Validation.Name + "."; - private static EventId MakeValidationId(Id id) => new EventId((int)id, _validationPrefix + id); - - /// - /// A warning during model validation indicating a key is configured on shadow properties. - /// This event is in the category. - /// - public static readonly EventId ModelValidationShadowKeyWarning = MakeValidationId(Id.ModelValidationShadowKeyWarning); - private static readonly string _infraPrefix = DbLoggerCategory.Infrastructure.Name + "."; private static EventId MakeInfraId(Id id) => new EventId((int)id, _infraPrefix + id); /// - /// A warning indicating that sensitive data logging is enabled and may be logged. - /// This event may be in different categories depending on where sensitive data is being logged. + /// + /// A warning indicating that sensitive data logging is enabled and may be logged. + /// + /// + /// This event may be in different categories depending on where sensitive data is being logged. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId SensitiveDataLoggingEnabledWarning = MakeInfraId(Id.SensitiveDataLoggingEnabledWarning); /// - /// A service provider was created for internal use by Entity Framework. - /// This event is in the category. + /// + /// A service provider was created for internal use by Entity Framework. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ServiceProviderCreated = MakeInfraId(Id.ServiceProviderCreated); /// - /// Many service proviers were created in a single app domain. - /// This event is in the category. + /// + /// Many service proviers were created in a single app domain. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// /// public static readonly EventId ManyServiceProvidersCreatedWarning = MakeInfraId(Id.ManyServiceProvidersCreatedWarning); } diff --git a/src/EFCore/Diagnostics/DbContextErrorEventData.cs b/src/EFCore/Diagnostics/DbContextErrorEventData.cs new file mode 100644 index 00000000000..98186e88084 --- /dev/null +++ b/src/EFCore/Diagnostics/DbContextErrorEventData.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for error events that reference + /// a . + /// + public class DbContextErrorEventData : DbContextEventData + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The current . + /// The exception that triggered this event. + public DbContextErrorEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] DbContext context, + [NotNull] Exception exception) + : base(eventDefinition, messageGenerator, context) + { + Exception = exception; + } + + /// + /// The exception that triggered this event. + /// + public virtual Exception Exception { get; } + } +} diff --git a/src/EFCore/Diagnostics/DbContextEventData.cs b/src/EFCore/Diagnostics/DbContextEventData.cs new file mode 100644 index 00000000000..2aab1bc61bf --- /dev/null +++ b/src/EFCore/Diagnostics/DbContextEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that reference + /// a . + /// + public class DbContextEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The current . + public DbContextEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] DbContext context) + : base(eventDefinition, messageGenerator) + { + Context = context; + } + + /// + /// The current . + /// + public virtual DbContext Context { get; } + } +} diff --git a/src/EFCore/Diagnostics/DbContextTypeErrorEventData.cs b/src/EFCore/Diagnostics/DbContextTypeErrorEventData.cs new file mode 100644 index 00000000000..d92d21c392b --- /dev/null +++ b/src/EFCore/Diagnostics/DbContextTypeErrorEventData.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for error events that reference + /// a type. + /// + public class DbContextTypeErrorEventData : DbContextTypeEventData + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The type of the current . + /// The exception that triggered this event. + public DbContextTypeErrorEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] Type contextType, + [NotNull] Exception exception) + : base(eventDefinition, messageGenerator, contextType) + { + Exception = exception; + } + + /// + /// The exception that triggered this event. + /// + public virtual Exception Exception { get; } + } +} diff --git a/src/EFCore/Diagnostics/DbContextTypeEventData.cs b/src/EFCore/Diagnostics/DbContextTypeEventData.cs new file mode 100644 index 00000000000..08af803228a --- /dev/null +++ b/src/EFCore/Diagnostics/DbContextTypeEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that reference + /// a type. + /// + public class DbContextTypeEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The current . + public DbContextTypeEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] Type contextType) + : base(eventDefinition, messageGenerator) + { + ContextType = contextType; + } + + /// + /// The current . + /// + public virtual Type ContextType { get; } + } +} diff --git a/src/EFCore/Diagnostics/EventDataBase.cs b/src/EFCore/Diagnostics/EventDataBase.cs new file mode 100644 index 00000000000..fd8cca45406 --- /dev/null +++ b/src/EFCore/Diagnostics/EventDataBase.cs @@ -0,0 +1,48 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.Extensions.Logging; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A base class for all Entity Framework event payloads. + /// + public class EventDataBase + { + private readonly EventDefinitionBase _eventDefinition; + private readonly Func _messageGenerator; + + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + public EventDataBase( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator) + { + _eventDefinition = eventDefinition; + _messageGenerator = messageGenerator; + } + + /// + /// The that defines the message ID and name. + /// + public virtual EventId EventId => _eventDefinition.EventId; + + /// + /// The that would be used to log message for this event. + /// + public virtual LogLevel LogLevel => _eventDefinition.Level; + + /// + /// A logger message describing this event. + /// + /// A logger message describing this event. + public override string ToString() => _messageGenerator(_eventDefinition, this); + } +} diff --git a/src/EFCore/Diagnostics/EventDefinition.cs b/src/EFCore/Diagnostics/EventDefinition.cs index 3e8b4ac7a76..3b9e4b8a7cb 100644 --- a/src/EFCore/Diagnostics/EventDefinition.cs +++ b/src/EFCore/Diagnostics/EventDefinition.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/EventDefinition`.cs b/src/EFCore/Diagnostics/EventDefinition`.cs index 1045e50c9d7..308d83b6128 100644 --- a/src/EFCore/Diagnostics/EventDefinition`.cs +++ b/src/EFCore/Diagnostics/EventDefinition`.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/EventDefinition``.cs b/src/EFCore/Diagnostics/EventDefinition``.cs index 5ca1f17cabb..06d3ed095a1 100644 --- a/src/EFCore/Diagnostics/EventDefinition``.cs +++ b/src/EFCore/Diagnostics/EventDefinition``.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/EventDefinition```.cs b/src/EFCore/Diagnostics/EventDefinition```.cs index 7bf246166d3..e11daa90112 100644 --- a/src/EFCore/Diagnostics/EventDefinition```.cs +++ b/src/EFCore/Diagnostics/EventDefinition```.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/EventDefinition````.cs b/src/EFCore/Diagnostics/EventDefinition````.cs index 078e69950a9..0f0753e352d 100644 --- a/src/EFCore/Diagnostics/EventDefinition````.cs +++ b/src/EFCore/Diagnostics/EventDefinition````.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/EventDefinition`````.cs b/src/EFCore/Diagnostics/EventDefinition`````.cs index e1e82b8a32f..14868c45d17 100644 --- a/src/EFCore/Diagnostics/EventDefinition`````.cs +++ b/src/EFCore/Diagnostics/EventDefinition`````.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/EventDefinition``````.cs b/src/EFCore/Diagnostics/EventDefinition``````.cs index 2bb51e86ff0..d1724acb81f 100644 --- a/src/EFCore/Diagnostics/EventDefinition``````.cs +++ b/src/EFCore/Diagnostics/EventDefinition``````.cs @@ -3,7 +3,6 @@ using System; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; diff --git a/src/EFCore/Diagnostics/IDiagnosticsLogger.cs b/src/EFCore/Diagnostics/IDiagnosticsLogger.cs index 94a7ce7192f..02d4d7ec99c 100644 --- a/src/EFCore/Diagnostics/IDiagnosticsLogger.cs +++ b/src/EFCore/Diagnostics/IDiagnosticsLogger.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.Logging; namespace Microsoft.EntityFrameworkCore.Diagnostics diff --git a/src/EFCore/Diagnostics/IncludeEventData.cs b/src/EFCore/Diagnostics/IncludeEventData.cs new file mode 100644 index 00000000000..967cf559406 --- /dev/null +++ b/src/EFCore/Diagnostics/IncludeEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// an specification. + /// + public class IncludeEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The Include specification. + public IncludeEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] string includeSpecification) + : base(eventDefinition, messageGenerator) + { + IncludeSpecification = includeSpecification; + } + + /// + /// The specification. + /// + public virtual string IncludeSpecification { get; } + } +} diff --git a/src/EFCore/Diagnostics/NavigationPathEventData.cs b/src/EFCore/Diagnostics/NavigationPathEventData.cs new file mode 100644 index 00000000000..1831cf80e4c --- /dev/null +++ b/src/EFCore/Diagnostics/NavigationPathEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// a navigation property. + /// + public class NavigationPathEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The navigation property. + public NavigationPathEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] string navigationPath) + : base(eventDefinition, messageGenerator) + { + NavigationPath = navigationPath; + } + + /// + /// The navigation property. + /// + public virtual string NavigationPath { get; } + } +} diff --git a/src/EFCore/Diagnostics/PropertyEventData.cs b/src/EFCore/Diagnostics/PropertyEventData.cs new file mode 100644 index 00000000000..5734aa60507 --- /dev/null +++ b/src/EFCore/Diagnostics/PropertyEventData.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// a property. + /// + public class PropertyEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The property. + public PropertyEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] IProperty property) + : base(eventDefinition, messageGenerator) + { + Property = property; + } + + /// + /// The property. + /// + public virtual IProperty Property { get; } + } +} diff --git a/src/EFCore/Diagnostics/QueryExpressionEventData.cs b/src/EFCore/Diagnostics/QueryExpressionEventData.cs new file mode 100644 index 00000000000..4fa9dea3db4 --- /dev/null +++ b/src/EFCore/Diagnostics/QueryExpressionEventData.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Query.Internal; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// a query expression. + /// + public class QueryExpressionEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + /// An that can be used to render the . + public QueryExpressionEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] Expression queryExpression, + [NotNull] IExpressionPrinter expressionPrinter) + : base(eventDefinition, messageGenerator) + { + Expression = queryExpression; + ExpressionPrinter = expressionPrinter; + } + + /// + /// The . + /// + public virtual Expression Expression { get; } + + /// + /// An that can be used to render the . + /// + public virtual IExpressionPrinter ExpressionPrinter { get; } + } +} diff --git a/src/EFCore/Diagnostics/QueryModelEventData.cs b/src/EFCore/Diagnostics/QueryModelEventData.cs new file mode 100644 index 00000000000..2523a4343a8 --- /dev/null +++ b/src/EFCore/Diagnostics/QueryModelEventData.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Remotion.Linq; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// a query model. + /// + public class QueryModelEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + public QueryModelEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] QueryModel queryModel) + : base(eventDefinition, messageGenerator) + { + QueryModel = queryModel; + } + + /// + /// The . + /// + public virtual QueryModel QueryModel { get; } + } +} diff --git a/src/EFCore/Diagnostics/QueryModelExpressionEventData.cs b/src/EFCore/Diagnostics/QueryModelExpressionEventData.cs new file mode 100644 index 00000000000..4be1b4d4ed4 --- /dev/null +++ b/src/EFCore/Diagnostics/QueryModelExpressionEventData.cs @@ -0,0 +1,39 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; +using Remotion.Linq; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have + /// a query model and an expression. + /// + public class QueryModelExpressionEventData : QueryModelEventData + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + /// The expression. + public QueryModelExpressionEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] QueryModel queryModel, + [NotNull] object expression) + : base(eventDefinition, messageGenerator, queryModel) + { + Expression = expression; + } + + /// + /// The expression. + /// + public virtual object Expression { get; } + } +} diff --git a/src/EFCore/Diagnostics/SaveChangesEventData.cs b/src/EFCore/Diagnostics/SaveChangesEventData.cs new file mode 100644 index 00000000000..77e2816e2c6 --- /dev/null +++ b/src/EFCore/Diagnostics/SaveChangesEventData.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Update; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that + /// specify the enties being saved and the rows affected. + /// + public class SaveChangesEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// Entries for the entities being saved. + /// The rows affected. + public SaveChangesEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] IEnumerable entries, + int rowsAffected) + : base(eventDefinition, messageGenerator) + { + Entries = entries; + RowsAffected = rowsAffected; + } + + /// + /// Entries for the entities being saved. + /// + public virtual IEnumerable Entries { get; } + + /// + /// The rows affected. + /// + public virtual int RowsAffected { get; } + } +} diff --git a/src/EFCore/Diagnostics/ServiceProviderEventData.cs b/src/EFCore/Diagnostics/ServiceProviderEventData.cs new file mode 100644 index 00000000000..12688b3faff --- /dev/null +++ b/src/EFCore/Diagnostics/ServiceProviderEventData.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that reference + /// a container. + /// + public class ServiceProviderEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The . + public ServiceProviderEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] IServiceProvider serviceProvider) + : base(eventDefinition, messageGenerator) + { + ServiceProvider = serviceProvider; + } + + /// + /// The . + /// + public virtual IServiceProvider ServiceProvider { get; } + } +} diff --git a/src/EFCore/Diagnostics/ServiceProvidersEventData.cs b/src/EFCore/Diagnostics/ServiceProvidersEventData.cs new file mode 100644 index 00000000000..4606dc37cc1 --- /dev/null +++ b/src/EFCore/Diagnostics/ServiceProvidersEventData.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that reference + /// multiple containers. + /// + public class ServiceProvidersEventData : EventDataBase + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The s. + public ServiceProvidersEventData( + [NotNull] EventDefinitionBase eventDefinition, + [NotNull] Func messageGenerator, + [NotNull] ICollection serviceProviders) + : base(eventDefinition, messageGenerator) + { + ServiceProviders = serviceProviders; + } + + /// + /// The s. + /// + public virtual ICollection ServiceProviders { get; } + } +} diff --git a/src/EFCore/Diagnostics/WarningsConfiguration.cs b/src/EFCore/Diagnostics/WarningsConfiguration.cs index f97ecd52b93..39f9de2bd13 100644 --- a/src/EFCore/Diagnostics/WarningsConfiguration.cs +++ b/src/EFCore/Diagnostics/WarningsConfiguration.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.Logging; namespace Microsoft.EntityFrameworkCore.Diagnostics diff --git a/src/EFCore/Extensions/Internal/CoreLoggerExtensions.cs b/src/EFCore/Extensions/Internal/CoreLoggerExtensions.cs index b52bc9d9260..cd2fd7a7470 100644 --- a/src/EFCore/Extensions/Internal/CoreLoggerExtensions.cs +++ b/src/EFCore/Extensions/Internal/CoreLoggerExtensions.cs @@ -6,9 +6,6 @@ using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; using Remotion.Linq; @@ -29,28 +26,35 @@ public static class CoreLoggerExtensions /// public static void SaveChangesFailed( [NotNull] this IDiagnosticsLogger diagnostics, - [NotNull] Type contextType, + [NotNull] DbContext context, [NotNull] Exception exception) { var definition = CoreStrings.LogExceptionDuringSaveChanges; definition.Log( diagnostics, - contextType, Environment.NewLine, exception, + context.GetType(), Environment.NewLine, exception, exception); if (diagnostics.DiagnosticSource.IsEnabled(definition.EventId.Name)) { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ContextType = contextType, - Exception = exception - }); + new DbContextErrorEventData( + definition, + SaveChangesFailed, + context, + exception)); } } + private static string SaveChangesFailed(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (DbContextErrorEventData)payload; + return d.GenerateMessage(p.Context.GetType(), Environment.NewLine, p.Exception); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -71,14 +75,21 @@ public static void QueryIterationFailed( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - ContextType = contextType, - Exception = exception - }); + new DbContextTypeErrorEventData( + definition, + QueryIterationFailed, + contextType, + exception)); } } + private static string QueryIterationFailed(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (DbContextTypeErrorEventData)payload; + return d.GenerateMessage(p.ContextType, Environment.NewLine, p.Exception); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -101,13 +112,20 @@ public static void QueryModelCompiling( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - QueryModel = queryModel - }); + new QueryModelEventData( + definition, + QueryModelCompiling, + queryModel)); } } + private static string QueryModelCompiling(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (QueryModelEventData)payload; + return d.GenerateMessage(Environment.NewLine, p.QueryModel.Print()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -130,13 +148,20 @@ public static void RowLimitingOperationWithoutOrderByWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - QueryModel = queryModel - }); + new QueryModelEventData( + definition, + RowLimitingOperationWithoutOrderByWarning, + queryModel)); } } + private static string RowLimitingOperationWithoutOrderByWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (QueryModelEventData)payload; + return d.GenerateMessage(p.QueryModel.Print(removeFormatting: true, characterLimit: QueryModelStringLengthLimit)); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -159,13 +184,20 @@ public static void FirstWithoutOrderByAndFilterWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - QueryModel = queryModel - }); + new QueryModelEventData( + definition, + FirstWithoutOrderByAndFilterWarning, + queryModel)); } } + private static string FirstWithoutOrderByAndFilterWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (QueryModelEventData)payload; + return d.GenerateMessage(p.QueryModel.Print(removeFormatting: true, characterLimit: QueryModelStringLengthLimit)); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -188,13 +220,20 @@ public static void QueryModelOptimized( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - QueryModel = queryModel - }); + new QueryModelEventData( + definition, + QueryModelOptimized, + queryModel)); } } + private static string QueryModelOptimized(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (QueryModelEventData)payload; + return d.GenerateMessage(Environment.NewLine, p.QueryModel.Print()); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -213,13 +252,20 @@ public static void NavigationIncluded( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - IncludeSpecification = includeSpecification - }); + new IncludeEventData( + definition, + NavigationIncluded, + includeSpecification)); } } + private static string NavigationIncluded(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (IncludeEventData)payload; + return d.GenerateMessage(p.IncludeSpecification); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -243,13 +289,21 @@ public static void QueryExecutionPlanned( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - QueryExecutorExpression = queryExecutorExpression - }); + new QueryExpressionEventData( + definition, + QueryExecutionPlanned, + queryExecutorExpression, + expressionPrinter)); } } + private static string QueryExecutionPlanned(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (QueryExpressionEventData)payload; + return d.GenerateMessage(p.ExpressionPrinter.Print(p.Expression)); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -266,7 +320,9 @@ public static void SensitiveDataLoggingEnabledWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - null); + new EventDataBase( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage())); } } @@ -288,13 +344,20 @@ public static void IncludeIgnoredWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - IncludeSpecification = includeSpecification - }); + new IncludeEventData( + definition, + IncludeIgnoredWarning, + includeSpecification)); } } + private static string IncludeIgnoredWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (IncludeEventData)payload; + return d.GenerateMessage(p.IncludeSpecification); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -313,13 +376,20 @@ public static void PossibleUnintendedCollectionNavigationNullComparisonWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - NavigationPath = navigationPath - }); + new NavigationPathEventData( + definition, + PossibleUnintendedCollectionNavigationNullComparisonWarning, + navigationPath)); } } + private static string PossibleUnintendedCollectionNavigationNullComparisonWarning(EventDefinitionBase definition, EventDataBase payload) + { + var d = (EventDefinition)definition; + var p = (NavigationPathEventData)payload; + return d.GenerateMessage(p.NavigationPath); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -340,45 +410,19 @@ public static void PossibleUnintendedReferenceComparisonWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - Left = left, - Right = right - }); + new BinaryExpressionEventData( + definition, + PossibleUnintendedReferenceComparisonWarning, + left, + right)); } } - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public static void ModelValidationShadowKeyWarning( - [NotNull] this IDiagnosticsLogger diagnostics, - [NotNull] IEntityType entityType, - [NotNull] IKey key) + private static string PossibleUnintendedReferenceComparisonWarning(EventDefinitionBase definition, EventDataBase payload) { - var definition = CoreStrings.LogShadowKey; - - // Checking for enabled here to avoid string formatting if not needed. - if (diagnostics.GetLogBehavior(definition.EventId, definition.Level) != WarningBehavior.Ignore) - { - definition.Log( - diagnostics, - Property.Format(key.Properties), - entityType.DisplayName(), - Property.Format(key.Properties)); - } - - if (diagnostics.DiagnosticSource.IsEnabled(definition.EventId.Name)) - { - diagnostics.DiagnosticSource.Write( - definition.EventId.Name, - new - { - EntityType = entityType, - Key = key - }); - } + var d = (EventDefinition)definition; + var p = (BinaryExpressionEventData)payload; + return d.GenerateMessage(p.Left, p.Right); } /// @@ -397,10 +441,10 @@ public static void ServiceProviderCreated( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - IServiceProvider = serviceProvider - }); + new ServiceProviderEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), + serviceProvider)); } } @@ -420,10 +464,10 @@ public static void ManyServiceProvidersCreatedWarning( { diagnostics.DiagnosticSource.Write( definition.EventId.Name, - new - { - IServiceProviders = serviceProviders - }); + new ServiceProvidersEventData( + definition, + (d, p) => ((EventDefinition)d).GenerateMessage(), + serviceProviders)); } } } diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index 151e3f7c063..0316ce1ef97 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -850,18 +850,6 @@ public static string ReferencedShadowKey([CanBeNull] object referencingEntityTyp GetString("ReferencedShadowKey", nameof(referencingEntityTypeOrNavigation), nameof(referencedEntityTypeOrNavigation), nameof(foreignKeyPropertiesWithTypes), nameof(primaryKeyPropertiesWithTypes)), referencingEntityTypeOrNavigation, referencedEntityTypeOrNavigation, foreignKeyPropertiesWithTypes, primaryKeyPropertiesWithTypes); - /// - /// The key {key} on entity type '{entityType}' contains properties in shadow state - {shadowProperties}. - /// - public static readonly EventDefinition LogShadowKey - = new EventDefinition( - CoreEventId.ModelValidationShadowKeyWarning, - LogLevel.Warning, - LoggerMessage.Define( - LogLevel.Warning, - CoreEventId.ModelValidationShadowKeyWarning, - _resourceManager.GetString("LogShadowKey"))); - /// /// An exception was thrown while attempting to evaluate a LINQ query parameter expression. To show additional information call EnableSensitiveDataLogging() when overriding DbContext.OnConfiguring. /// diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index ad63fce1d8b..1b8d79f1c14 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -431,10 +431,6 @@ The relationship from '{referencingEntityTypeOrNavigation}' to '{referencedEntityTypeOrNavigation}' with foreign key properties {foreignKeyPropertiesWithTypes} cannot target the primary key {primaryKeyPropertiesWithTypes} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship. - - The key {key} on entity type '{entityType}' contains properties in shadow state - {shadowProperties}. - Warning CoreEventId.ModelValidationShadowKeyWarning string string string - An exception was thrown while attempting to evaluate a LINQ query parameter expression. To show additional information call EnableSensitiveDataLogging() when overriding DbContext.OnConfiguring. diff --git a/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs b/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs index 3344e2aa676..3c434fe0e4f 100644 --- a/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs +++ b/test/EFCore.Tests/Infrastructure/CoreEventIdTest.cs @@ -28,6 +28,7 @@ public void Every_eventId_has_a_logger_method_and_logs_when_level_enabled() var fakeFactories = new Dictionary> { { typeof(Type), () => typeof(object) }, + { typeof(DbContext), () => new DbContext(new DbContextOptionsBuilder().UseInMemoryDatabase("D").Options) }, { typeof(QueryModel), () => queryModel }, { typeof(string), () => "Fake" }, { typeof(IExpressionPrinter), () => new ExpressionPrinter() },