public static DatabaseConnection GetNewConnection(NamedConnectionString connectionString, IProcess process, int maxRetryCount = 5, int retryDelayMilliseconds = 2000) { if (string.IsNullOrEmpty(connectionString.ProviderName)) { var ex = new EtlException(process, "missing provider name for connection string"); ex.Data["ConnectionStringName"] = connectionString.Name; ex.AddOpsMessage("missing provider name for connection string key: " + connectionString.Name); throw ex; } var iocUid = 0; var connection = _connectionManager.GetNewConnection(connectionString, maxRetryCount, retryDelayMilliseconds, onOpening: (connectionString, connection) => { iocUid = process.Context.RegisterIoCommandStart(process, IoCommandKind.dbConnection, connectionString.Name, connection.ConnectionTimeout, "open connection", Transaction.Current.ToIdentifierString(), null, "opening database connection to {ConnectionStringName} ({Provider})", connectionString.Name, connectionString.GetFriendlyProviderName()); }, onOpened: (connectionString, connection, retryCount) => { process.Context.RegisterIoCommandSuccess(process, IoCommandKind.dbConnection, iocUid, null); }, onError: (connectionString, connection, retryCount, ex) => { process.Context.RegisterIoCommandFailed(process, IoCommandKind.dbConnection, iocUid, null, ex); if (retryCount < maxRetryCount) { process.Context.Log(LogSeverity.Error, process, "can't connect to database, connection string key: {ConnectionStringName} ({Provider}), retrying in {DelayMsec} msec (#{AttemptIndex}): {ExceptionMessage}", connectionString.Name, connectionString.GetFriendlyProviderName(), retryDelayMilliseconds * (retryCount + 1), retryCount, ex.Message); process.Context.LogOps(LogSeverity.Error, process, "can't connect to database, connection string key: {ConnectionStringName} ({Provider}), retrying in {DelayMsec} msec (#{AttemptIndex}): {ExceptionMessage}", connectionString.Name, connectionString.GetFriendlyProviderName(), retryDelayMilliseconds * (retryCount + 1), retryCount, ex.Message); } else { var exception = new EtlException(process, "can't connect to database", ex); exception.AddOpsMessage(string.Format(CultureInfo.InvariantCulture, "can't connect to database, connection string key: {0}, message: {1}", connectionString.Name, ex.Message)); exception.Data.Add("ConnectionStringName", connectionString.Name); exception.Data.Add("ProviderName", connectionString.ProviderName); exception.Data.Add("NumberOfAttempts", maxRetryCount + 1); throw exception; } }); return(connection); }
public static string FormatExceptionWithDetails(this Exception exception, bool includeTrace = true) { try { var lvl = 0; var msg = "EXCEPTION: "; var cex = exception; while (cex != null) { if (lvl > 0) { msg += "\nINNER EXCEPTION: "; } msg += cex.GetType().GetFriendlyTypeName() + ": " + cex.Message; if (cex.Data?["ProcessType"] is string processType) { msg += "\n\tPROCESS: "; if (cex.Data?["ProcessTypeAssembly"] is string processTypeAssembly) { msg += "(" + processTypeAssembly + ") "; } msg += processType; if (cex.Data?["ProcessName"] is string processName && processName != processType) { msg += " (\"" + processName + "\")"; } if (cex.Data?["ProcessTopic"] is string processTopic) { msg += ", topic: " + processTopic; } if (cex.Data?["ProcessKind"] is string processKind) { msg += ", kind: " + processKind; } } if (cex.Data?.Count > 0) { var first = true; foreach (var key in cex.Data.Keys) { var k = key.ToString(); if (k is "ProcessName" or "ProcessKind" or "ProcessTopic" or "ProcessType" or "ProcessTypeAssembly") { continue; } if (k == "CallChain") { continue; } if (k == "OpsMessage") { continue; } if (k == "Trace") { continue; } if (k == "Row") { continue; } if (k.Contains("Row", StringComparison.InvariantCultureIgnoreCase) && cex.Data[key] is string rowStr && rowStr.StartsWith("uid", StringComparison.InvariantCultureIgnoreCase)) { continue; } if (first) { msg += "\n\tDATA:"; first = false; } else { msg += ", "; } var value = cex.Data[key]; msg += "\n\t\t[" + k + "] = " + (value != null ? value.ToString().Trim() : "NULL"); } } if (cex.Data?["Row"] is string storedRow) { msg += "\n\tROW: " + storedRow.Replace("\n", "\n\t\t", StringComparison.InvariantCultureIgnoreCase); } if (cex.Data?.Count > 0) { foreach (var key in cex.Data.Keys) { var k = key.ToString(); if (k == "Row") { continue; } if (k.Contains("Row", StringComparison.InvariantCultureIgnoreCase) && cex.Data[key] is string rowStr && rowStr.StartsWith("uid", StringComparison.InvariantCultureIgnoreCase)) { msg += "\n\t" + k.ToUpperInvariant() + ": " + rowStr; } } } if (cex.Data?["CallChain"] is string callChain) { msg += "\n\tCALL CHAIN:\n\t\t" + callChain.Replace("\n", "\n\t\t", StringComparison.Ordinal); } if (includeTrace) { if (cex.Data?["Trace"] is not string trace) { trace = EtlException.GetTraceFromStackFrames(new StackTrace(cex, true).GetFrames()); } if (trace != null) { msg += "\n\tTRACE:\n\t\t" + trace.Replace("\n", "\n\t\t", StringComparison.Ordinal); } } cex = cex.InnerException; lvl++; } return(msg); } catch (Exception) { return(exception.ToString()); } }