Skip to content

Commit

Permalink
Updated with review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Nov 9, 2020
1 parent 0b83a6e commit b8a8af3
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ This observer must then be registered globally, for example in the application's
-->
[!code-csharp[RegisterDiagnosticListener](../../../samples/core/Miscellaneous/DiagnosticListeners/Program.cs?name=RegisterDiagnosticListener)]

Second, once the EF Core DiagnosticListener is found, a new key-value observer it is created to subscribe to the actual EF Core events. For example:
Second, once the EF Core DiagnosticListener is found, a new key-value observer is created to subscribe to the actual EF Core events. For example:

<!--
public class KeyValueObserver : IObserver<KeyValuePair<string, object>>
Expand Down
2 changes: 1 addition & 1 deletion entity-framework/core/logging-events-diagnostics/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ms.date: 10/15/2020
uid: core/logging-events-diagnostics/events
---

# .NET events in EF Core
# .NET Events in EF Core

> [!TIP]
> You can [download the events sample](https://github.com/dotnet/EntityFramework.Docs/tree/master/samples/core/Miscellaneous/Events) from GitHub.
Expand Down
14 changes: 6 additions & 8 deletions entity-framework/core/logging-events-diagnostics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ ms.date: 10/01/2020
uid: core/logging-events-diagnostics/index
---

# Overview of logging and interception
# Overview of Logging and Interception

Entity Framework Core (EF Core) contains several mechanisms for generating logs, responding to events, and obtaining diagnostics. Each of these are tailored to different situations, and it is important to select the best mechanism for the task in hand, even when multiple mechanisms could work. For example, a database interceptor could be used to log SQL, but this is better handled by one of the mechanisms tailored to logging. This page presents an overview of each of these mechanisms and describes when each should be used.
Entity Framework Core (EF Core) contains several mechanisms for generating logs, responding to events, and obtaining diagnostics. Each of these is tailored to different situations, and it is important to select the best mechanism for the task in hand, even when multiple mechanisms could work. For example, a database interceptor could be used to log SQL, but this is better handled by one of the mechanisms tailored to logging. This page presents an overview of each of these mechanisms and describes when each should be used.

## Quick reference

Expand All @@ -22,14 +22,14 @@ The table below provides a quick reference for the differences between the mecha
| Interceptors | Yes | Per context | Context configuration | Manipulating EF operations
| Diagnostics listeners | No | Process | Globally | Application diagnostics

*Typically `Microsoft.Extensions.Logging` is configured per-application in D.I. However, at the EF level, each context _can_ be configured with a different logger if needed.
*Typically `Microsoft.Extensions.Logging` is configured per-application via dependency injection However, at the EF level, each context _can_ be configured with a different logger if needed.

## Simple logging

> [!NOTE]
> This feature was added in EF Core 5.0.
EF Core logs can be accessed from any type of application through use of [LogTo](https://github.com/dotnet/efcore/blob/ec3df8fd7e4ea4ebeebfa747619cef37b23ab2c6/src/EFCore/DbContextOptionsBuilder.cs#L135) <!-- Issue #2748 <xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.LogTo%2A> --> when [configuring a DbContext instance](xref:core/dbcontext-configuration/index). This configuration is commonly done in an override of <xref:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring%2A?displayProperty=nameWithType>. For example:
EF Core logs can be accessed from any type of application through the use of [LogTo](https://github.com/dotnet/efcore/blob/ec3df8fd7e4ea4ebeebfa747619cef37b23ab2c6/src/EFCore/DbContextOptionsBuilder.cs#L135) <!-- Issue #2748 <xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.LogTo%2A> --> when [configuring a DbContext instance](xref:core/dbcontext-configuration/index). This configuration is commonly done in an override of <xref:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring%2A?displayProperty=nameWithType>. For example:

<!--
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
Expand All @@ -43,9 +43,7 @@ See [Simple Logging](xref:core/logging-events-diagnostics/simple-logging) for mo

## Microsoft.Extensions.Logging

[Microsoft.Extensions.Logging](/dotnet/core/extensions/logging) is an extensible logging mechanism with plug-in providers for many common logging systems.

EF Core fully integrates with `Microsoft.Extensions.Logging` and this form of logging is used by default for ASP.NET Core applications.
[Microsoft.Extensions.Logging](/dotnet/core/extensions/logging) is an extensible logging mechanism with plug-in providers for many common logging systems. EF Core fully integrates with `Microsoft.Extensions.Logging` and this form of logging is used by default for ASP.NET Core applications.

See [Using Microsoft.Extensions.Logging in EF Core](xref:core/logging-events-diagnostics/extensions-logging) for more information.

Expand All @@ -65,7 +63,7 @@ See [.NET Events in EF Core](xref:core/logging-events-diagnostics/events) for mo
> [!NOTE]
> This feature was added in EF Core 3.0. Additional interceptors were added in EF Core 5.0.
EF Core interceptors enable interception, modification, and/or suppression of EF Core events. This includes low-level database operations such as executing a command, as well as higher-level events, such as calls to SaveChanges.
EF Core interceptors enable interception, modification, and/or suppression of EF Core operations. This includes low-level database operations such as executing a command, as well as higher-level operations, such as calls to SaveChanges.

Interceptors are different from logging and diagnostics in that they allow modification or suppression of the operation being intercepted. [Simple logging](xref:core/logging-events-diagnostics/simple-logging) or [Microsoft.Extensions.Logging](xref:core/logging-events-diagnostics/extensions-logging) are better choices for logging.

Expand Down
13 changes: 9 additions & 4 deletions entity-framework/core/logging-events-diagnostics/interceptors.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ uid: core/logging-events-diagnostics/interceptors

# Interceptors

Entity Framework Core (EF Core) interceptors enable interception, modification, and/or suppression of EF Core events. This includes low-level database operations such as executing a command, as well as higher-level events, such as calls to SaveChanges.
Entity Framework Core (EF Core) interceptors enable interception, modification, and/or suppression of EF Core operations. This includes low-level database operations such as executing a command, as well as higher-level operations, such as calls to SaveChanges.

Interceptors are different from logging and diagnostics in that they allow modification or suppression of the operation being intercepted. [Simple logging](xref:core/logging-events-diagnostics/simple-logging) or [Microsoft.Extensions.Logging](xref:core/logging-events-diagnostics/extensions-logging) are better choices for logging.

Interceptors are registered per DbContext instance when the context is configured. Use a [diagnostic listener](xref:core/logging-events-diagnostics/diagnostic-listeners) to get the same information but for all DbContext instances in the process.

## Registering interceptors

Interceptors are registered using <xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.AddInterceptors%2A> when [configuring a DbContext instance](xref:core/miscellaneous/configuring-dbcontext). This is commonly done in an override of <xref:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring%2A?displayProperty=nameWithType>. For example:
Interceptors are registered using <xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.AddInterceptors%2A> when [configuring a DbContext instance](xref:core/dbcontext-configuration). This is commonly done in an override of <xref:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring%2A?displayProperty=nameWithType>. For example:

<!--
public class ExampleContext : BlogsContext
Expand Down Expand Up @@ -58,13 +58,13 @@ Low-level database interception is split into the three interfaces shown in the

| Interceptor | Database operations intercepted
|:-----------------------------------------------------------------------|-------------------------------------------------
| <xref:Microsoft.EntityFrameworkCore.Diagnostics.IDbCommandInterceptor> | Creating commands</br>Executing commands</br>Command failures</br>Disposing the command DataReader
| <xref:Microsoft.EntityFrameworkCore.Diagnostics.IDbCommandInterceptor> | Creating commands</br>Executing commands</br>Command failures</br>Disposing the command's DbDataReader
| <xref:Microsoft.EntityFrameworkCore.Diagnostics.IDbConnectionInterceptor> | Opening and closing connections</br>Connection failures
| <xref:Microsoft.EntityFrameworkCore.Diagnostics.IDbTransactionInterceptor> | Creating transactions</br>Using existing transactions</br>Committing transactions</br>Rolling back transactions</br>Creating and using savepoints</br>Transaction failures

The base classes <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbCommandInterceptor>, <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbConnectionInterceptor>, and <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbTransactionInterceptor> contain no-op implementations for each method in the corresponding interface. Use the base classes to avoid the need to implement unused interception methods.

The methods on each interceptor type come in pairs; one called before the database operation is started; the other called after the operation has completed. For example, <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbCommandInterceptor.ReaderExecuting%2A?displayProperty=nameWithType> is called before a query is executed, and <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbCommandInterceptor.ReaderExecuted%2A?displayProperty=nameWithType> is called after query has been sent to the database.
The methods on each interceptor type come in pairs, with the first being called before the database operation is started, and the second after the operation has completed. For example. For example, <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbCommandInterceptor.ReaderExecuting%2A?displayProperty=nameWithType> is called before a query is executed, and <xref:Microsoft.EntityFrameworkCore.Diagnostics.DbCommandInterceptor.ReaderExecuted%2A?displayProperty=nameWithType> is called after query has been sent to the database.

Each pair of methods have both sync and async variations. This allows for asynchronous I/O, such as requesting an access token, to happen as part of intercepting an async database operation.

Expand Down Expand Up @@ -166,6 +166,8 @@ public class AadAuthenticationInterceptor : DbConnectionInterceptor
var sqlConnection = (SqlConnection)connection;
var provider = new AzureServiceTokenProvider();
// Note: in some situations the access token may not be cached automatically the Azure Token Provider.
// Depending on the kind of token requested, you may need to implement your own caching here.
sqlConnection.AccessToken = await provider.GetAccessTokenAsync("https://database.windows.net/", null, cancellationToken);
return result;
Expand All @@ -180,6 +182,9 @@ public class AadAuthenticationInterceptor : DbConnectionInterceptor
> [!WARNING]
> Notice that the interceptor throws if a sync call is made to open the connection. This is because there is no non-async method to obtain the access token and there is [no universal and simple way to call an async method from non-async context without risking deadlock](https://devblogs.microsoft.com/dotnet/configureawait-faq/).
> [!WARNING]
> in some situations the access token may not be cached automatically the Azure Token Provider. Depending on the kind of token requested, you may need to implement your own caching here.
### Example: Advanced command interception for caching

> [!TIP]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ms.date: 10/03/2020
uid: core/logging-events-diagnostics/simple-logging
---

# Simple logging
# Simple Logging

> [!NOTE]
> This feature was added in EF Core 5.0.
Expand All @@ -21,7 +21,7 @@ Entity Framework Core (EF Core) simple logging can be used to easily obtain logs
## Configuration

EF Core logs can be accessed from any type of application through use of [LogTo](https://github.com/dotnet/efcore/blob/ec3df8fd7e4ea4ebeebfa747619cef37b23ab2c6/src/EFCore/DbContextOptionsBuilder.cs#L135) <!-- Issue #2748 <xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.LogTo%2A> --> when [configuring a DbContext instance](xref:core/dbcontext-configuration/index). This configuration is commonly done in an override of <xref:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring%2A?displayProperty=nameWithType>. For example:
EF Core logs can be accessed from any type of application through the use of [LogTo](https://github.com/dotnet/efcore/blob/ec3df8fd7e4ea4ebeebfa747619cef37b23ab2c6/src/EFCore/DbContextOptionsBuilder.cs#L135) <!-- Issue #2748 <xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.LogTo%2A> --> when [configuring a DbContext instance](xref:core/dbcontext-configuration/index). This configuration is commonly done in an override of <xref:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring%2A?displayProperty=nameWithType>. For example:

<!--
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public override async ValueTask<InterceptionResult> ConnectionOpeningAsync(
var sqlConnection = (SqlConnection)connection;

var provider = new AzureServiceTokenProvider();
// Note: in some situations the access token may not be cached automatically the Azure Token Provider.
// Depending on the kind of token requested, you may need to implement your own caching here.
sqlConnection.AccessToken = await provider.GetAccessTokenAsync("https://database.windows.net/", null, cancellationToken);

return result;
Expand Down

0 comments on commit b8a8af3

Please sign in to comment.