zoukankan      html  css  js  c++  java
  • 自定义错误信息并写入到Elmah

    在ap.net Web项目中一直使用Elmah进行日志记录,

    但一直有一个问题困扰我很久,那就是我如何自己生成一个错误并记录到Elmah里去。

    你知道有时你需要在项目中生成一个错误用于一些特殊的需求

    最开始之前我是这样处理的。

    使用Sql语句自定义错误信息添加到Elmah的Sqlite数据库中,但这样做有一个问题,

    如果Elmah更改存储方式非Sqlite(如Xml,txt,Mysql等)那么下面的方式就无效啦(错误信息无法在Elmah中显示)

         
    public class CustomErrorSqlite{
    static   string  UrlDecodeUtf( string  _val)
            {
                 return   HttpUtility .UrlDecode(_val, System.Text. Encoding .UTF8);
            }
       static string StrDecode(string str)
            {
                return UrlDecodeUtf(str).Replace("&", "").Replace("<br />", "  ").Replace("<br>", "  ").Replace("<", "<").Replace(">", ">").Replace(""", """).Replace("'", "'").Replace(")", ")").Replace("(", "(").Replace("{", "{").Replace("}", "}").Replace("/", "/");
            }   
      static string GetServerVariables
            {
                get
                {
                    StringBuilder sb = new StringBuilder("<serverVariables>");
                    foreach (string str in HttpContext.Current.Request.ServerVariables)
                    {
                        sb.Append(string.Format("<item name='{0}'><value string='{1}'/></item>", str, StrDecode(HttpContext.Current.Request.ServerVariables[str])));
                    }
                    sb.Append("</serverVariables>");
                    return sb.ToString();
                }
            }
    /// <summary>
            /// 错误信息,错误地址,错误详细信息
            /// AllXml列需要将@#等特殊字符进行处理,否则在查看Elmah详情时会出现
            /// </summary>
            /// <param name="message">错误信息</param>
            /// <param name="source">错误来源</param>
            /// <param name="detailmessage">详细的错误信息</param>
            public static void AddLog(string message, string source, string detailmessage)
            {
                detailmessage = StrDecode(UrlDecodeUtf(detailmessage));
                message = StrDecode(UrlDecodeUtf(message));
                source = StrDecode(UrlDecodeUtf(source));
     
                //使用Elmah的Sqlite数据库
                //如果在配置文件中更改sqlite数据库位置或更改为其他存储方式
                //下面的处理方式无效(数据无法在Elmah中显示和查看)
                string ConnectionString = string.Empty;
                foreach (ConnectionStringSettings str in ConfigurationManager.ConnectionStrings)
                {
                    if (!str.Name.Contains("Elmah_SQLiteErrorLog"))
                        continue;
                    ConnectionString = str.ConnectionString;
                    break;
                }
                using (SQLiteConnection sQLiteConnection = new SQLiteConnection(ConnectionString))
                {
                    using (SQLiteCommand sQLiteCommand = new SQLiteCommand("INSERT INTO Error (Application, Host, Type, Source, Message, User, StatusCode, TimeUtc, AllXml)VALUES (@Application, @Host, @Type, @Source, @Message, @User, @StatusCode, @TimeUtc, @AllXml);SELECT last_insert_rowid();", sQLiteConnection))
                    {
                        SQLiteParameterCollection parameters = sQLiteCommand.Parameters;
                        parameters.Add("@Application", DbType.String, 60).Value = "/";
                        parameters.Add("@Host", DbType.String, 30).Value = Environment.UserName;
                        parameters.Add("@Type", DbType.String, 100).Value = "UserType";
                        parameters.Add("@Source", DbType.String, 60).Value = "UserType";
                        parameters.Add("@Message", DbType.String, 500).Value = message;
                        parameters.Add("@User", DbType.String, 50).Value = Environment.UserName;
                        parameters.Add("@StatusCode", DbType.Int64).Value = 300;
                        parameters.Add("@TimeUtc", DbType.DateTime).Value = DateTime.Now;
                        parameters.Add("@AllXml", DbType.String).Value = string.Format("<error   type="UserType"  message="{0}"  source="{1}"  detail="
    {2}
    Source:{3}  ">{4}</error>", message, source, detailmessage + "
    datetime:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ms"), source, GetServerVariables);
     
                        try
                        {
                            sQLiteConnection.Open();
                            sQLiteCommand.ExecuteScalar();
                        }
                        catch (Exception)
                        {
     
                        }
                        finally
                        {
                            sQLiteCommand.Clone();
                        }
                    }
                }
            }
        }
    View Code

      

    经过搜索 发现一个更好的解决方案使用Elmah内部对象来添加错误信息,但可能性能上会有损耗,每次都会创建Error或Exception对象
     
    using System;
    using System.Web;
    using Elmah;
    namespace CustomErrorElmah
    {
        public partial class Default : System.Web.UI.Page
        {
     
            protected void Page_Load(object sender, EventArgs e)
            {
     
                string querystr = "
    ";
                if (!string.IsNullOrEmpty(Request.QueryString.ToString()))
                    querystr += Request.QueryString;
     
                //自定义错误
                CustomErrorSqlite.AddLog("THIS IS TEST  ,自定义Sql添加到Elmah的Sqlit数据库中", "Page_Load()", "自定义错误  自定义Sql添加到Elmah的Sqlit数据库中" + querystr);
     
                #region
                //创建一个Elmah的Error对象并写错误日志
     
                Error error = new Error();
                error.Message = "THIS IS TEST  使用Elmah的Error对象";
                error.HostName = Request.Url.Host;
                error.StatusCode = 100;
                error.Time = DateTime.Now;
                error.User = Environment.UserName;
                error.Type = "Elmah 自定义类型";
                error.Detail = "THIS IS TEST  ,创建一个Elmah的Error对象并写错误日志 但没有Server Variables,cookie等信息" + querystr;
                error.Source = "Page_Load";
     
     
                Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(error);
                #endregion
     
                //创建一个异常并写入错误日志,无法自定义错误的类型
                Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("创建一个异常并写入错误日志" + querystr));
            }
        }
    }
    View Code

    Web.config配置Elmah 

    <?xml version="1.0" encoding="utf-8"?>
     
    <configuration>
        <configSections>
            <!--监控应用程序-->
            <sectionGroup name="elmah">
                <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
                <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah"/>
                <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/>
            </sectionGroup>
        </configSections>
     
        <!--Elmah连接数据库-->
        <elmah>
            <security allowRemoteAccess="yes"/>
            <errorLog type="Elmah.SQLiteErrorLog, Elmah" connectionStringName="Elmah_SQLiteErrorLog"/>
     
        </elmah>
        <connectionStrings>
            <!--监控应用程序 数据存储位置-->
            <add name="Elmah_SQLiteErrorLog" connectionString="Data Source=|DataDirectory|Error.db3"/>
        </connectionStrings>
        <system.web>
     
            <!--出现错误时的处理模块-->
            <httpHandlers>
                <add verb="POST,GET,HEAD" path="Elmah/Error.aspx" type="Elmah.ErrorLogPageFactory, Elmah"/>
            </httpHandlers>
            <httpModules>
                <!--出错时的处理模块-->
                <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
                <!--发送Email-->
                <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
            </httpModules>
            <customErrors defaultRedirect="/404.html" mode="Off"/>
        </system.web>
    </configuration>
    View Code

    有图有真相:

     

    1.

    2.

    .

    3.

    之前一直想解决完全自定义错误信息的问题,但上面三个方法总不能让我完全满意(我需要Request的完整信息)

    但第二个最接近我想要的效果,只是生成的错误信息没有Request信息见图2

    在Bing.com和stackoverflow.com上搜索了半天也没有解决,无奈只好下载源码自己来处理

    通过源码发现实现方法完全可以实现我要的效果(自动添加Request信息)

    只需要将当前的HttpContext指向“Error ”对象既可


            
      //创建一个Elmah的Error对象并写错误日志
                //没有Request信息
                Error error =   new  Elmah. Error ( ); 
                //当前的HttpContext指向“Error ”,在生成的错误信息时会自动添加Request信息
                Error error =   new  Elmah. Error ( new   Exception (),  HttpContext .Current); 
                error.Message = "THIS IS TEST  使用Elmah的Error对象" ;
                error.HostName = Request.Url.Host;
                error.StatusCode = 100 ;
                error.Time = DateTime.Now;
                error.User = Environment.UserName;
                error.Type = "Elmah 自定义类型" ;
                error.Detail = "THIS IS TEST  ,创建一个Elmah的Error对象并写错误日志 但没有Server Variables,cookie等信息" + querystr;
                error.Source = "Page_Load" ;
    View Code

    Elmah:http://code.google.com/p/elmah/

    http://asp.net.bigresource.com/Logging-username-with-Elmah-for-WCF-Webservices--Wp1ghgwYB.html#TwdsRSkL9

    http://stackoverflow.com/questions/2108404/elmah-exceptions-without-httpcontext

    http://stackoverflow.com/questions/3812538/elmah-add-message-to-error-logged-through-call-to-raisee

    http://stackoverflow.com/questions/7441062/how-to-use-elmah-to-manually-log-errors

  • 相关阅读:
    OutputStream 和 Writer
    elasticsearch技术解析与实战(一) 入门和索引
    Kafka Consumer API样例
    关于kafka的新的group无法订阅到topic中历史消息的问题
    apache kafka系列之在zookeeper中存储结构
    KafkaConsumer 长时间地在poll(long )方法中阻塞
    问题记录
    java随笔
    Ubuntu18.10下运行blender2.80bate闪退(问题?)
    linux下简单制作iso,img镜像文件
  • 原文地址:https://www.cnblogs.com/huangtailang/p/3795225.html
Copyright © 2011-2022 走看看