【问题标题】:How to store Elmah exception information to a web service?如何将 Elmah 异常信息存储到 Web 服务?
【发布时间】:2015-12-27 03:26:05
【问题描述】:

我们使用 elmah 已经有一段时间了,我们有一个新的要求,即用户界面不要直接将信息保存到他的数据库中,团队经理询问我们是否可以告诉 elmah 将异常信息发送到 Web 服务。有没有人做过这个或者有任何信息可以分享,谢谢。

【问题讨论】:

  • 胡安的回答可能效果很好。另一种方法是使用 elmah.io(我创建的)、Raygun、Loggly、Airbrake 或类似工具将整个 ELMAH 日志移动到云中。
  • 我完全同意,我用 elmah.io 和 raygun 甚至 Microsoft Insights 进行了一些测试,它们提供了开箱即用的优秀替代方案....但有时管理层不希望这样更好他们有什么理由的选择.....我还没有测试过airbrake和loggly我会看看,谢谢
  • 而且这个选项不适用于新的 asp.net 5

标签: elmah.mvc


【解决方案1】:

我实现了这个希望它可以帮助某人:

网络服务:

   using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Mail;
using System.Web.Http;
using System.Xml;
using System.Xml.Linq;
using Elmah;
using Newtonsoft.Json;

namespace ElmahExt.Service.Controllers
{
    public class ElmahCommandsController : ApiController
    {
       private readonly string _connection = ConfigurationManager.ConnectionStrings["conSQL"].ConnectionString ;

        [HttpPost]
        public HttpResponseMessage LogError(Error elmahErrorInformation)
        {
            try
            {

                var id = Guid.NewGuid();

                using (SqlConnection cnn = new SqlConnection(_connection))
                using (SqlCommand cmd = SqlCommands.LogError(elmahErrorInformation,id.ToString()))
                {
                    cmd.Connection = cnn;
                    cnn.Open();
                    cmd.ExecuteNonQuery();
                    return Request.CreateResponse(HttpStatusCode.OK, id.ToString());
                }

        }
        catch
        {
            return Request.CreateResponse(HttpStatusCode.ExpectationFailed,string.Empty);
        }

    }

    [HttpGet]
    public HttpResponseMessage GetErrors(string appName, int pageIndex, int pageSize)
    {
        using (SqlConnection cnn = new SqlConnection(_connection))
        using (SqlCommand cmd = SqlCommands.GetErrorsXml(appName, pageIndex, pageSize))
        {
            cmd.Connection = cnn;
            cnn.Open();



            XmlReader reader = cmd.ExecuteXmlReader();

            try
            {
                int? total =(int?)cmd.Parameters["@TotalCount"].Value ?? 0;

                List<string> errors = new List<string>();

                while (reader.IsStartElement("error"))
                    errors.Add(reader.ReadOuterXml());

                XDocument doc = new XDocument(
                    new XElement("GetErrorsResult",
                        new XAttribute("total", total),
                        from string error in errors
                        select new XElement("Error", error)
                        )
                    );

                return Request.CreateResponse(HttpStatusCode.OK, doc.ToString());

            }
            finally
            {
                reader.Close();
            }
        }
    }

    [HttpGet]
    public HttpResponseMessage GetError(string appName, string id)
    {
        Guid errorGuid = new Guid(id);

        string errorXml;

        using (SqlConnection cnn = new SqlConnection(_connection))
        using (SqlCommand cmd = SqlCommands.GetErrorXml(appName, errorGuid))
        {
            cmd.Connection = cnn;
            cnn.Open();
            errorXml = (string)cmd.ExecuteScalar();
        }

        XElement errorEl = (errorXml == null) ? null : new XElement("Error", errorXml);

        XDocument doc = new XDocument(
            new XElement("GetErrorResult", errorEl)
            );
        return Request.CreateResponse(HttpStatusCode.OK, doc.ToString());

    }

}

}

Elmah 扩展

   using System;
using System.Collections;
using System.Linq;
using System.Net.Http;
using System.Net.Mail;
using System.Threading.Tasks;
using System.Xml.Linq;
using Elmah;


namespace ElmahExt
{


    public class ServiceErrorLog : ErrorLog
    {



           private string _url;
            public ServiceErrorLog(IDictionary config)
            {
    \\Here config have the information from the configuration in the web config
                ApplicationName = config["applicationName"] as string ?? "";
                _url = config["WebServiceUrl"] as string ?? "";

            }

      static ServiceErrorLog()
        {
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        }
    private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
       e.SetObserved();
    }

    public override string Name => "Custom Elmah provider using web services.";


    /// <summary>
    /// This method log the error information coming from an Elmah call. The result of the web service is received with the guid id of the error but is not waited or returned. 
    /// This implementation was on purpose to continue the processing.
    /// </summary>
    /// <param name="error">Elmah object containing all the information of the exception</param>
    /// <returns></returns>
    public override string Log(Error error)
    {

        Task T = Task.Factory.StartNew(() =>
        {
            using (var client = new HttpClient())
            {
              var result = client.PostAsJsonAsync(_url, error).Result;
            }
        });

        return string.Empty;

    }



    /// <summary>
    /// Return a list of errors to display in the Elmah viewer.
    /// </summary>
    /// <param name="pageIndex">The index of the page to display</param>
    /// <param name="pageSize">The amount of records to display per page</param>
    /// <param name="errorEntryList">The list of errors</param>
    /// <returns>A list of errors in XML format.</returns>
    public override int GetErrors(int pageIndex, int pageSize, IList errorEntryList)
    {
        int total = 0;

        using (var client = new HttpClient())
        {
            _url += $"?pageIndex={pageIndex}&pageSize={pageSize}&appName={ApplicationName}";

            var response = client.GetAsync(_url).Result;

            if (response.IsSuccessStatusCode)
            {

                var result = response.Content.ReadAsAsync<string>().Result;

                XDocument doc = XDocument.Parse(result);
                XElement root = doc.Element("GetErrorsResult");


                if (root != null)
                {
                    var errors = from XElement el in root.Elements("Error")
                        select new
                        {
                            value = el.Value,
                            element = XElement.Parse(el.Value)
                        };

                    foreach (var err in errors)
                    {
                        string errorId = err.element.Attribute("errorId").Value;
                        Error error = ErrorXml.DecodeString(err.value);
                        errorEntryList.Add(new ErrorLogEntry(this, errorId, error));
                    }

                    total = int.Parse(root.Attribute("total").Value);


                }



            }
        }

        return total;
    }


    /// <summary>
    /// Returns an specific error
    /// </summary>
    /// <param name="id">The id of the error.(Guid)</param>
    /// <returns>Returns an XML with the error information.</returns>
    public override ErrorLogEntry GetError(string id)
    {
        ErrorLogEntry errorLogEntry = null;

        using (var client = new HttpClient())
        {
            _url += $"?id={id}&appName={ApplicationName}";

            var response = client.GetAsync(_url).Result;

            if (response.IsSuccessStatusCode)
            {

                var result = response.Content.ReadAsAsync<string>().Result;

                XDocument doc = XDocument.Parse(result);
                XElement root = doc.Element("GetErrorResult");


                XElement errorEl = root?.Element("Error");

                if (errorEl != null)
                {
                    Error error = ErrorXml.DecodeString(errorEl.Value);
                    errorLogEntry = new ErrorLogEntry(this, id, error);
                }
            }


        }

        return errorLogEntry;
    }
}

}

在您的网络配置中必须添加自定义提供程序:

  <errorLog type="ElmahExt.ServiceErrorLog, ElmahExt" applicationName="Elmah Evaluation App" 
                  WebServiceUrl="http://localhost:28382/api/ElmahCommands/LogError" />

在此配置部分中注意 Web 服务 url 的变量和自定义提供程序的构造函数中使用的应用程序的名称。

【讨论】:

  • 如果你实现了这段代码,你必须在异常处理区域进行一些重构。并尝试添加一种替代方法来捕获错误,以识别 Web 服务器是否已关闭或数据库。此代码在新版本的asp.net 5中不起作用
猜你喜欢
  • 2011-01-11
  • 2012-11-12
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-15
  • 1970-01-01
相关资源
最近更新 更多