Beispiel #1
0
        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());
        }
    }