Voyager.DBConnection.Logging
4.6.0
dotnet add package Voyager.DBConnection.Logging --version 4.6.0
NuGet\Install-Package Voyager.DBConnection.Logging -Version 4.6.0
<PackageReference Include="Voyager.DBConnection.Logging" Version="4.6.0" />
<PackageVersion Include="Voyager.DBConnection.Logging" Version="4.6.0" />
<PackageReference Include="Voyager.DBConnection.Logging" />
paket add Voyager.DBConnection.Logging --version 4.6.0
#r "nuget: Voyager.DBConnection.Logging, 4.6.0"
#:package Voyager.DBConnection.Logging@4.6.0
#addin nuget:?package=Voyager.DBConnection.Logging&version=4.6.0
#tool nuget:?package=Voyager.DBConnection.Logging&version=4.6.0
Voyager.DBConnection.Logging
Logging extension for Voyager.DBConnection that provides automatic logging of all database operations.
Features
- ✅ Automatic logging of all SQL operations (stored procedures, queries)
- ✅ Execution time tracking
- ✅ Parameter logging
- ✅ Error and exception logging
- ✅ Support for both
DbCommandExecutor(modern) andConnection(legacy) - ✅ Multi-framework support: .NET Framework 4.8, .NET 6.0, .NET 8.0
- ✅ Uses
Microsoft.Extensions.Logging.Abstractionsfor flexible logging backends
Installation
dotnet add package Voyager.DBConnection.Logging
Quick Start
Using with DbCommandExecutor (Recommended)
using Microsoft.Extensions.Logging;
using Voyager.DBConnection;
// Create your logger (e.g., using Microsoft.Extensions.Logging)
ILogger logger = loggerFactory.CreateLogger("DatabaseOperations");
// Create database and executor
var database = new Database(factory, connectionString);
var executor = new DbCommandExecutor(database, errorPolicy);
// Add logging - logs all database operations automatically
executor.AddLogger(logger);
// All operations are now logged
var result = executor.ExecuteNonQuery(
"InsertUser",
cmd => cmd
.WithInputParameter("Username", DbType.String, 50, "john_doe")
.WithInputParameter("Email", DbType.String, 100, "john@example.com")
)
.Tap(rows => Console.WriteLine($"Inserted {rows} row(s)"))
.TapError(error => Console.WriteLine($"Error: {error.Message}"));
Using with Connection (Legacy)
using Microsoft.Extensions.Logging;
using Voyager.DBConnection;
var connection = new Connection(database, exceptionPolicy);
connection.AddLogger(logger);
// Operations are logged automatically
connection.ExecuteNonQuery(commandFactory);
What Gets Logged
The logging extension captures:
- Command Type: SQL query, stored procedure name
- Execution Time: Duration of the operation in milliseconds
- Parameters: Input, output, and input/output parameters with values
- Results: Number of rows affected, scalar values returned
- Errors: Exception details, error messages, stack traces
- Success/Failure: Operation outcome
Example Log Output
Successful Operation:
[Information] Executing stored procedure 'InsertUser' with parameters: Username='john_doe', Email='john@example.com'
[Information] Completed 'InsertUser' in 45ms - 1 row(s) affected
Error:
[Error] Executing stored procedure 'InsertUser' with parameters: Username='john_doe', Email='john@example.com'
[Error] Failed 'InsertUser' after 12ms - SqlException: Violation of UNIQUE KEY constraint 'UQ_Users_Username'
Logging Backends
This package uses Microsoft.Extensions.Logging.Abstractions, which means you can use any logging provider:
Console Logging
using Microsoft.Extensions.Logging;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger("Database");
executor.AddLogger(logger);
Serilog
using Serilog;
using Microsoft.Extensions.Logging;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/database.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddSerilog();
});
var logger = loggerFactory.CreateLogger("Database");
executor.AddLogger(logger);
NLog
using NLog.Extensions.Logging;
using Microsoft.Extensions.Logging;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddNLog();
});
var logger = loggerFactory.CreateLogger("Database");
executor.AddLogger(logger);
Advanced Usage
Filtering Logs
Use your logging framework's filtering capabilities:
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Database", LogLevel.Information) // Only log Info and above
.AddConsole();
});
Multiple Loggers
You can add the same logger to multiple executors:
var sharedLogger = loggerFactory.CreateLogger("Database");
var executor1 = new DbCommandExecutor(database1, errorPolicy);
executor1.AddLogger(sharedLogger);
var executor2 = new DbCommandExecutor(database2, errorPolicy);
executor2.AddLogger(sharedLogger);
Removing Logging
Logging is implemented as a feature that can be disposed:
// The logger is automatically cleaned up when the executor is disposed
executor.Dispose();
Performance Considerations
- Logging adds minimal overhead to database operations
- Parameter values are only serialized when logging is enabled
- Use appropriate log levels (
Informationfor normal operations,Errorfor failures) - Consider using structured logging for better performance in production
Integration with ASP.NET Core
// In Startup.cs or Program.cs
services.AddSingleton<IDbCommandExecutor>(provider =>
{
var logger = provider.GetRequiredService<ILogger<DbCommandExecutor>>();
var connectionString = configuration.GetConnectionString("DefaultConnection");
var factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
var database = new Database(factory, connectionString);
var executor = new DbCommandExecutor(database, new SqlServerErrorPolicy());
executor.AddLogger(logger);
return executor;
});
Integration with Application Insights
Azure Application Insights can track database operations as dependencies, providing rich telemetry including execution time, success/failure rates, and correlation with requests.
Using Application Insights with Logging Extension
The simplest approach is to use the built-in logging extension with Application Insights logger:
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.Logging;
// Configure Application Insights
var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.InstrumentationKey = "your-instrumentation-key";
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddApplicationInsights(telemetryConfiguration, options => { });
});
var logger = loggerFactory.CreateLogger("Database");
// Add logging to executor
var executor = new DbCommandExecutor(database, errorPolicy);
executor.AddLogger(logger);
// All database operations are now logged to Application Insights
executor.ExecuteNonQuery("InsertUser", cmd => cmd
.WithInputParameter("Username", DbType.String, 50, "john_doe")
);
Custom Telemetry with SqlCallEvent
For more granular control and richer telemetry, you can subscribe to database events directly and send custom telemetry:
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Voyager.DBConnection.Events;
using Voyager.DBConnection.Interfaces;
public class ApplicationInsightsDatabaseFeature : IFeature
{
private readonly TelemetryClient telemetryClient;
private readonly IRegisterEvents registerEvents;
public ApplicationInsightsDatabaseFeature(TelemetryClient telemetryClient, IRegisterEvents registerEvents)
{
this.telemetryClient = telemetryClient;
this.registerEvents = registerEvents;
this.registerEvents.AddEvent(TrackDatabaseOperation);
}
public void Dispose()
{
this.registerEvents.RemoveEvent(TrackDatabaseOperation);
}
private void TrackDatabaseOperation(SqlCallEvent sqlEvent)
{
var dependency = new DependencyTelemetry
{
Type = "SQL",
Target = sqlEvent.DatabaseName ?? "Database",
Name = sqlEvent.CommandText ?? "SQL Query",
Data = sqlEvent.CommandText,
Duration = sqlEvent.ExecutionTime,
Success = !sqlEvent.IsError,
Timestamp = DateTimeOffset.Now
};
// Add custom properties
dependency.Properties["CommandType"] = sqlEvent.CommandType.ToString();
dependency.Properties["ParameterCount"] = sqlEvent.Parameters?.Count.ToString() ?? "0";
if (sqlEvent.IsError && !string.IsNullOrEmpty(sqlEvent.ErrorMessage))
{
dependency.Properties["ErrorMessage"] = sqlEvent.ErrorMessage;
}
// Add parameters (be careful with sensitive data!)
if (sqlEvent.Parameters != null)
{
foreach (var param in sqlEvent.Parameters)
{
dependency.Properties[$"Param_{param.Key}"] = param.Value?.ToString() ?? "null";
}
}
telemetryClient.TrackDependency(dependency);
}
}
// Extension method for easy integration
public static class ApplicationInsightsExtensions
{
public static void AddApplicationInsights(this DbCommandExecutor executor, TelemetryClient telemetryClient)
{
executor.AddFeature(new ApplicationInsightsDatabaseFeature(telemetryClient, executor));
}
public static void AddApplicationInsights(this Connection connection, TelemetryClient telemetryClient)
{
connection.AddFeature(new ApplicationInsightsDatabaseFeature(telemetryClient, connection));
}
}
// Usage
var telemetryClient = new TelemetryClient(telemetryConfiguration);
var executor = new DbCommandExecutor(database, errorPolicy);
executor.AddApplicationInsights(telemetryClient);
Application Insights in ASP.NET Core
For ASP.NET Core applications, use dependency injection:
// In Program.cs or Startup.cs
builder.Services.AddApplicationInsightsTelemetry(options =>
{
options.InstrumentationKey = configuration["ApplicationInsights:InstrumentationKey"];
});
builder.Services.AddSingleton<IDbCommandExecutor>(provider =>
{
var telemetryClient = provider.GetRequiredService<TelemetryClient>();
var logger = provider.GetRequiredService<ILogger<DbCommandExecutor>>();
var connectionString = configuration.GetConnectionString("DefaultConnection");
var factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
var database = new Database(factory, connectionString);
var executor = new DbCommandExecutor(database, new SqlServerErrorPolicy());
// Option 1: Use logging extension (simpler)
executor.AddLogger(logger);
// Option 2: Use custom Application Insights feature (more control)
executor.AddApplicationInsights(telemetryClient);
return executor;
});
Benefits of Application Insights Integration
When using Application Insights with Voyager.DBConnection.Logging, you get:
- Dependency Tracking: Database calls appear as dependencies in Application Insights
- Performance Monitoring: Track slow queries and execution times
- Failure Analysis: Identify and diagnose database errors
- Query Analytics: Analyze which queries are most frequently executed
- Correlation: Link database operations to specific user requests
- Alerting: Set up alerts for slow queries or high error rates
- Custom Dashboards: Create dashboards showing database performance metrics
Example Query in Application Insights
// Find slow database operations
dependencies
| where type == "SQL"
| where duration > 1000 // More than 1 second
| project timestamp, name, target, duration, success
| order by duration desc
// Database error rate
dependencies
| where type == "SQL"
| summarize Total = count(), Failures = countif(success == false) by name
| extend ErrorRate = (Failures * 100.0) / Total
| where ErrorRate > 5 // More than 5% error rate
| order by ErrorRate desc
Security Considerations
When logging to Application Insights:
- Never log sensitive data (passwords, credit card numbers, PII)
- Use parameter names instead of values for sensitive parameters
- Consider implementing a filtering mechanism to exclude sensitive parameters
- Be mindful of logging volume and costs in high-traffic applications
// Example: Filter sensitive parameters
private void TrackDatabaseOperation(SqlCallEvent sqlEvent)
{
var dependency = new DependencyTelemetry { /* ... */ };
// Only log non-sensitive parameters
var sensitiveParams = new[] { "Password", "CreditCard", "SSN" };
if (sqlEvent.Parameters != null)
{
foreach (var param in sqlEvent.Parameters.Where(p => !sensitiveParams.Contains(p.Key)))
{
dependency.Properties[$"Param_{param.Key}"] = param.Value?.ToString() ?? "null";
}
}
telemetryClient.TrackDependency(dependency);
}
Related Packages
- Voyager.DBConnection - Core library
- Voyager.DBConnection.MsSql - SQL Server support
- Voyager.DBConnection.Oracle - Oracle support
- Voyager.DBConnection.PostgreSql - PostgreSQL support
- Voyager.DBConnection.MySql - MySQL support
License
MIT License - see LICENSE for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions:
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.1)
- Voyager.DBConnection (>= 4.6.0)
-
net6.0
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.1)
- Voyager.DBConnection (>= 4.6.0)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.1)
- Voyager.DBConnection (>= 4.6.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.6.0 | 87 | 2/19/2026 |
| 4.5.1-preview.2 | 42 | 2/19/2026 |
| 4.5.1-preview.1 | 39 | 2/19/2026 |
| 4.5.0 | 90 | 1/27/2026 |
| 4.5.0-preview.3.2 | 50 | 1/27/2026 |
| 4.5.0-preview.3 | 43 | 1/27/2026 |
| 4.5.0-preview.2 | 48 | 1/13/2026 |
| 4.5.0-preview.1 | 47 | 1/13/2026 |
| 4.4.6-preview.1 | 47 | 1/12/2026 |
| 4.4.5-preview.3 | 45 | 1/12/2026 |
| 4.4.5-preview.2 | 56 | 1/8/2026 |
| 4.4.5-preview.1 | 57 | 1/8/2026 |
| 4.4.4-preview.12 | 63 | 1/2/2026 |
| 4.4.4-preview.11 | 54 | 1/2/2026 |
| 4.4.4-preview.10 | 51 | 1/2/2026 |
| 4.4.4-preview.9 | 137 | 12/24/2025 |
| 4.4.4-preview.8 | 128 | 12/24/2025 |
| 4.1.2 | 442 | 12/5/2023 |
| 4.1.1 | 208 | 12/5/2023 |
| 4.1.0 | 223 | 11/22/2023 |