2015-09-29 1 views
1

Мы используем elmah в течение некоторого времени, и у нас есть новое требование для сохранения информации непосредственно в базу данных, и менеджер команды спросил, можем ли мы сообщить elmah о отправке информации об исключениях в веб-службу. Кто-нибудь сделал это и/или имел любую информацию, чтобы поделиться, спасибо.Как хранить информацию об исключениях Elmah в веб-службе?

+0

Ответы Хуана, вероятно, прекрасно работают. Альтернативой было бы переместить весь журнал ELMAH в облако, используя elmah.io (я основал это), Raygun, Loggly, Airbrake или аналогичный. – ThomasArdal

+0

Я полностью согласен, и я сделал несколько тестов с elmah.io и raygun даже с Microsoft Insights, и они предлагают отличные альтернативы из коробки. Но иногда люди в управлении не хотят этого лучшего варианта того, что когда-либо было у них ..... Я не тестировал airbrake и loggly, я посмотрю, спасибо – Juan

+0

И эти параметры не работают с новым asp.net 5 – Juan

ответ

0

Я реализовал эту надежду, что это помогает кто-то:

Веб-сервис:

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" /> 

Примечание В этом разделе конфигурации переменные URL-адрес веб-службы и имя приложения, используемого в конструкторе пользовательского поставщика.

+0

Если вы реализуете этот код, вам нужно сделать некоторый рефакторинг в область обработки исключений. И попробуйте добавить альтернативный способ захвата ошибок, чтобы определить, отключен ли веб-сервер или база данных. Этот код не работает в новой версии asp.net 5 – Juan