【问题标题】:Exception block for multi-tiered internal system多层内部系统的异常块
【发布时间】:2012-03-30 21:13:01
【问题描述】:

我的项目非常大,它包括 IIS 服务器和 Windows 服务,甚至还有一些 UNIX/cgi 服务,它们将使用 WCF 框架读取

它将包括 3 层、一个 Ms MVC 网站、多个服务网关等。

我想知道您会为我推荐哪种异常处理机制。

我正在寻找多功能的东西,但我们不想过火。我检查了ELMAH

据我了解,ELMAH 使用 HttpModules,因此如果不对其进行一些调整,它将无法与我的 Windows 服务一起使用。

你还有什么推荐的吗?

附言
我没有层之间的安全问题。它们都在我的域中

【问题讨论】:

  • 你能定义“异常处理机制”吗?下面提到的ELMAH和log4net都是日志解决方案,不是异常处理;您仍然需要编写代码来捕获异常并记录它们。你希望这个机制为你做什么?
  • 我们正在研究异常块,例如(企业库块)EL 5。我们将在 MVC 和其他数据区域中使用 EntityFramework。我只是觉得 EL 对我们来说可能太复杂了,也许 tweeking ELMAH 接受 Windows 服务异常会是更好的方法。我们将有自定义例外,但所有重新包装和安全删除都超出了我们项目的要求。不要误会我的意思是非常大的。将包括 10 个服务模块,每个模块都有自己的数据中心和服务定位器。
  • 让我重新表述一下:您希望这个异常处理机制真正做什么?您要满足什么用例?是只是“记录我的异常”,还是需要集中的异常屏蔽、包装、转换等?
  • 我对 amdocs 企业解决方案的不同异常块在理论上和使用方面了解很多。我在一个新项目中希望实现一些异常块。我正在考虑基于规则,因为下线,我很确定我们会提出我们不熟悉的要求。但是,截至目前,我们没有特殊情况(尽管这是第一个 sprint,我们都知道这是怎么回事)。我正在考虑 EL 与 ELMAH。我倾向于 ELMAH,所以我想我们需要创建一些插入 Windows 服务的 ELMAH 风格。或者使用 MAMOTH EL。 wwjd ? :P

标签: .net logging enterprise-library elmah error-logging


【解决方案1】:

使用 log4net。为了使其更加健壮,您需要创建另一个 WCF 服务,将您的异常、错误或消息记录到您的数据库中。

为此的步骤。

1 - 修改客户端应用程序的 web.config / app.config

<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
</configuration>

2 - 添加 log4net 部分如下。

  <log4net>
    <appender name="WcfAppender" type="Problem.Common.Logging.WcfAppender, Problem.Common">
      <endpointAddress value="http://localhost.poc.trunk.site-dev.local/Services/Log.svc"/>
    </appender>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="log.log" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{dd-MM-yyyy HH:mm:ss} %message%newline" />
      </layout>
    </appender>
    <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <target value="Console.Error" />
      <mapping>
        <level value="FATAL" />
        <foreColor value="Red" />
        <backColor value="White" />
      </mapping>
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="WARN" />
        <foreColor value="Yellow" />
      </mapping>
      <mapping>
        <level value="INFO" />
        <foreColor value="Cyan" />
      </mapping>
      <mapping>
        <level value="DEBUG" />
        <foreColor value="Green" />
      </mapping>
      <layout type="log4net.Layout.SimpleLayout" />
    </appender>
    <logger name="WcfLogger">
      <level value="ALL" />
      <appender-ref ref="WcfAppender" />
      <appender-ref ref="ColoredConsoleAppender" />
    </logger>
    <logger name="FileLogger">
      <level value="ALL" />
      <appender-ref ref="FileAppender" />
      <appender-ref ref="ColoredConsoleAppender" />
    </logger>
  </log4net>

3 - 如下所述创建 log.svc。

namespace Problem.CustomerCore.Services
{
using System;
using System.ServiceModel;
using Common.ExceptionHandling;
using log4net;
using log4net.Core;

/// <summary>
/// Service contract for instrumentation operations - such as logging and performance tracking
/// </summary>
[ServiceContract]
public interface ILogPOC
{
    /// <summary>
    /// Writes an entry to the logging framework
    /// </summary>
    /// <param name="logDateTime">The timestamp that the event occurred</param>
    /// <param name="logLevel">The level of the event</param>
    /// <param name="host">The host on which the event occurred</param>
    /// <param name="loggerName">The name of the type that originally raised the exception</param>
    /// <param name="message">The message describing the event context</param>
    /// <param name="exception">Excpetion object in case of the log entry being an error</param>
    /// <param name="version">The version number of the component reporting the log entry</param>
    /// <param name="tenancyExternalReference">The external reference identifying the current tenancy.</param>
    [OperationContract]
    [FaultContract(typeof(ProcessingResultsList))]
    void WriteLogEntry(DateTime logDateTime, Level logLevel, string host, string loggerName, string message, string exception, string version, Guid tenancyExternalReference);
}

/// <summary>
/// Methods for instrumenting the application
/// </summary>
public class Log : ILogPOC
{
    /// <summary>
    /// The logger to use for writing out exceptions nad info logs
    /// </summary>
    private static ILog logger = LogManager.GetLogger(typeof(Instrumentation));

    /// <summary>
    /// Writes an entry to the logging framework
    /// </summary>
    /// <param name="logDateTime">The timestamp that the event occurred</param>
    /// <param name="logLevel">The level of the event</param>
    /// <param name="host">The host on which the event occurred</param>
    /// <param name="loggerName">The name of the type that originally raised the exception</param>
    /// <param name="message">The message describing the event context</param>
    /// <param name="exception">Excpetion object in case of the log entry being an error</param>
    /// <param name="version">The version number of the component reporting the log entry</param>
    /// <param name="tenancyExternalReference">The external reference identifying the current tenancy.</param>
    public void WriteLogEntry(DateTime logDateTime, Level logLevel, string host, string loggerName, string message, string exception, string version, Guid tenancyExternalReference)
    {
        log4net.Config.XmlConfigurator.Configure();
        ThreadContext.Properties["Host"] = host;
        ThreadContext.Properties["Version"] = version;
        ThreadContext.Properties["Tenancy"] = tenancyExternalReference;
        ThreadContext.Properties["User"] = System.Threading.Thread.CurrentPrincipal.Identity.Name;

        var eventData = new LoggingEventData
                            {
                                Identity = System.Threading.Thread.CurrentPrincipal.Identity.Name,
                                UserName = System.Threading.Thread.CurrentPrincipal.Identity.Name,
                                Level = logLevel,
                                LoggerName = loggerName,
                                TimeStamp = logDateTime,
                                Message = message,
                                ExceptionString = exception
                            };
        var logEvent = new LoggingEvent(eventData);

        // log the exception
        logger.Logger.Log(logEvent);
    }
}
}

4 - 在数据库中创建一个日志表。

5 - WCF 的 Web.config 应该如下所示。特别是 log4net 部分。

<log4net>
    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.30319.1, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
      <bufferSize value="100" />
      <lossy value="true" />
      <evaluator type="log4net.Core.LevelEvaluator">
        <threshold value="INFO"/>
      </evaluator>
      <connectionString value="Database=XYZ-trunk;Server=localhost;User ID=a;Password=b;Trusted_Connection=False;" />
      <connectionStringName value="connectionException" /> 
      <commandText value="[dbo].[spLog_WriteEntry]" />
      <commandType value="StoredProcedure" />
      <parameter>
        <parameterName value="@LogDateTime" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" /> 
      </parameter>
      <parameter>
        <parameterName value="@Component" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout" value="%logger" />
      </parameter>
      <parameter>
        <parameterName value="@LogLevel" /> 
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout" value="%level" />
      </parameter>
      <parameter>
        <parameterName value="@Host" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{Host}"/>
        </layout> 
      </parameter>
      <parameter>
        <parameterName value="@Message" /> 
        <dbType value="String" /> 
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout" value="%message" />
      </parameter>
      <parameter>
        <parameterName value="@Exception" />
        <dbType value="String" />
        <size value="2000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
      <parameter>
        <parameterName value="@Coulmn1" />
        <dbType value="String" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{Tenancy}"/>
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@Username" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{User}"/>
        </layout>
      </parameter>
    </appender>
    <appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
       <threshold value="WARN"/>
       <to value="error@a.com" />
       <from value="build@abc.com" />
       <subject value="SmtpAppender" />
       <smtpHost value="xyz.com" />
       <bufferSize value="512" />
       <lossy value="false" />
       <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />
       </layout>
    </appender>
    <root> 
      <level value="DEBUG" />
      <appender-ref ref="AdoNetAppender" />
    </root>
  </log4net>

现在您设置 WCF 服务。

希望对你有所帮助。

【讨论】:

  • 兔佐,谢谢你的建议。我不是 NIH 的人,但这是我们正在考虑的事情。我肯定会认真考虑这一点,并至少创建一个测试项目来检查这一点。尽管这是一个记录器,而不是异常处理程序或事件侦听器。但感谢您的详细解释。 :)
猜你喜欢
  • 2016-06-12
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多