From 3f7e593bc2ee7c3b48af9506c3e95b129dedb0db Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 20 Dec 2016 14:10:06 +1100 Subject: [PATCH] U4-9302 Add logging of non security related connection string details when the connection fails --- src/Umbraco.Core/DatabaseContext.cs | 29 +++++++++++++-- .../Persistence/DbConnectionExtensions.cs | 37 ++++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs index 585f1d51cf..a6d6ca9e6e 100644 --- a/src/Umbraco.Core/DatabaseContext.cs +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -34,6 +34,12 @@ namespace Umbraco.Core private string _connectionString; private string _providerName; private DatabaseSchemaResult _result; + private DateTime? _connectionLastChecked = null; + + /// + /// The number of minutes to throttle the checks to CanConnect + /// + private const int ConnectionCheckMinutes = 1; [Obsolete("Use the constructor specifying all dependencies instead")] public DatabaseContext(IDatabaseFactory factory) @@ -110,13 +116,28 @@ namespace Umbraco.Core { get { - if (IsDatabaseConfigured == false) return false; - var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider); - LogHelper.Info("CanConnect = " + canConnect); - return canConnect; + if (IsDatabaseConfigured == false) + return false; + + //Don't check again if the timeout period hasn't elapsed + //this ensures we don't keep checking the connection too many times in a row like during startup. + //Do check if the _connectionLastChecked is null which means we're just initializing or it could + //not connect last time it was checked. + if ((_connectionLastChecked.HasValue && (DateTime.Now - _connectionLastChecked.Value).TotalMinutes > ConnectionCheckMinutes) + || _connectionLastChecked.HasValue == false) + { + var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider); + LogHelper.Info("CanConnect = " + canConnect); + + _connectionLastChecked = canConnect == false ? null : (DateTime?) DateTime.Now; + return canConnect; + } + + return _connectionLastChecked.HasValue; } } + /// /// Gets the configured umbraco db connection string. /// diff --git a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs index c0c7b2a777..86072c45d5 100644 --- a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs +++ b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs @@ -4,9 +4,11 @@ using System.Configuration; using System.Data; using System.Data.Common; using System.Data.SqlClient; +using System.Data.SqlServerCe; using System.Linq; using System.Text; using System.Threading.Tasks; +using MySql.Data.MySqlClient; using Umbraco.Core.Logging; namespace Umbraco.Core.Persistence @@ -69,6 +71,38 @@ namespace Umbraco.Core.Persistence } } + public static string GetConnStringExSecurityInfo(this IDbConnection connection) + { + try + { + if (connection is SqlConnection) + { + var builder = new SqlConnectionStringBuilder(connection.ConnectionString); + return string.Format("DataSource: {0}, InitialCatalog: {1}", builder.DataSource, builder.InitialCatalog); + } + + if (connection is SqlCeConnection) + { + var builder = new SqlCeConnectionStringBuilder(connection.ConnectionString); + return string.Format("DataSource: {0}", builder.DataSource); + } + + if (connection is MySqlConnection) + { + var builder = new MySqlConnectionStringBuilder(connection.ConnectionString); + return string.Format("Server: {0}, Database: {1}", builder.Server, builder.Database); + } + } + catch (Exception ex) + { + LogHelper.WarnWithException(typeof(DbConnectionExtensions), + "Could not resolve connection string parameters", ex); + return "(Could not resolve)"; + } + + throw new ArgumentException(string.Format("The connection type {0} is not supported", connection.GetType())); + } + public static bool IsAvailable(this IDbConnection connection) { try @@ -79,7 +113,8 @@ namespace Umbraco.Core.Persistence catch (DbException exc) { // Don't swallow this error, the exception is super handy for knowing "why" its not available - LogHelper.WarnWithException("Configured database is reporting as not being available!", exc); + LogHelper.WarnWithException(typeof(DbConnectionExtensions), + "Configured database is reporting as not being available! {0}", exc, connection.GetConnStringExSecurityInfo); return false; }