2013-12-11 5 views
33

Я создал небольшое приложение winforms C#, в качестве дополнительной функции, которую я рассматривал, добавляя в нее некоторую форму регистрации ошибок. У кого-нибудь есть какие-то предложения по хорошим путям? Это особенность, с которой я никогда не смотрел добавление к предыдущим проектам, поэтому я открыт для предложений от разработчиков, у которых больше опыта.Простой способ выполнения регистрации ошибок?

Я рассматривал что-то вроде строк для записи исключений в указанный текстовый файл или, возможно, таблицу базы данных. Это приложение, которое будет использоваться в течение нескольких месяцев, а затем отбрасывается при завершении работы большего продукта.

+2

Если вы думаете о регистрации БД, почему бы не сделать свою собственную функцию вставки SQL для ошибок? – Saren

+0

Проверьте это: http://logging.apache.org/log4net/, BTW, вы не хотите использовать системный журнал? Это самое простое решение. – Harry

+8

«Это приложение, которое будет использоваться в течение нескольких месяцев, а затем отбрасывается, когда заканчивается более крупный продукт»? Хотите сделать ставку на это? –

ответ

3

Well log4net работает как кирпич. Это может быть немного сложно настроить, но это того стоит. Она также позволяет настроить блокирование файлов этих файлов журналов и т.д.

http://www.codeproject.com/Articles/140911/log4net-Tutorial

+0

Кажется, что это может быть что-то стоящее, и я определенно буду заинтересован в том, чтобы узнать больше в любом случае. Можете ли вы помочь мне разобраться с app.config, dll и настройкой кода? Кажется немного запутанным в вашей ссылке. –

+0

Если вы хотите, я могу написать краткое описание того, как использовать log4net в качестве ответа. – Mino

+1

Я думаю, это было бы большой помощью, если бы вы не возражали! :) –

1

Вы просто выписывать свои ошибки исключения в текстовый файл. Write to Text File. Одно из предложений состоит в том, чтобы поместить файл, который вы создаете, в каталог userdata или appdata, хотя вам не нужно бороться с разрешениями.

Поскольку это требуется всего несколько месяцев и будет отброшено, нет причин переходить за борт с БД. Достаточно простого текстового файла.

+0

Вот что я думал, но хотел внешнего мнения. В настоящее время я перехватываю исключения и показываю их следующим образом: 'catch (Exception ex) {MessageBox.Show (" Источник: \ t "+ ex.Source +" \ nMessage: \ t "+ ex.Message +" \ nДата: \ t "+ ex.Data); } '. Любые идеи о том, как я мог бы сделать это более полезным при записи в журнал ошибок? (Помимо добавления даты/времени). –

+0

Исключение будет указывать вам на место в кодовой базе, чтобы исследовать, так что помимо даты/времени вам действительно не нужно ничего другого. Возможно, 'StackTrace' – KSdev

8

Оптимальное решение, на мой взгляд, было бы использовать NLog: http://nlog-project.org/

Просто установите пакет конфигурации из NuGet: http://www.nuget.org/packages/NLog.Config/ и вы будете в конечном итоге с библиотекой и предварительно сконфигурированной регистратор файла ...

Тогда в коде вам просто необходимо:

// A logger member field: 

private readonly Logger logger = LogManager.GetCurrentClassLogger(); // creates a logger using the class name 

// use it: 
logger.Info(...); 
logger.Error(...); 

// and also: 
logger.ErrorException("text", ex); // which will log the stack trace. 

в конфигурационном файле вы получаете, вы должны раскомментировать разделы, которые вам нужны:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    <!-- 
     See http://nlog-project.org/wiki/Configuration_file 
     for information on customizing logging rules and outputs. 
    --> 
    <targets> 
     <!-- add your targets here --> 

     <!-- UNCOMMENT THIS! 
     <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log" 
       layout="${longdate} ${uppercase:${level}} ${message}" /> 
     --> 
    </targets> 

    <rules> 
     <!-- add your logging rules here --> 

     <!-- UNCOMMENT THIS! 
     <logger name="*" minlevel="Trace" writeTo="f" /> 
     --> 
    </rules> 
</nlog> 
+0

Еще одно примечание, если используется' error.XXXException (строка, исключение) '... вам нужно изменить целевой макет с помощью' $ {exception} ', чтобы получить сообщение об исключении или' $ {exception : format = tostring} ', чтобы получить полное значение tostring. –

+1

kudos на сжатом показе того, что нужно делать в конфигурации и кодекса ... спасибо! – Chrysalis

+0

Утверждение, что эта сторонняя библиотека является «лучшим решением», возможно, является слишком агрессивной претензией. Я думаю, что более объективная формулировка будет оценена по достоинству. – Zero3

72

Я бы не стал слишком много разбираться в внешних библиотеках, так как ваши потребности в регистрации очень просты.

.NET Framework уже поставляется с этой функцией в пространстве имен System.Diagnostics, вы можете написать все, что нужно протоколирование там методами просто заходящих под Trace класса:

Trace.TraceInformation("Your Information"); 
Trace.TraceError("Your Error"); 
Trace.TraceWarning("Your Warning"); 

, а затем настроить все следы слушатели, которые соответствуют вашим потребностям в файле app.config:

<configuration> 
    // other config 
    <system.diagnostics> 
    <trace autoflush="true" indentsize="4"> 
     <listeners> 
     <add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener"/> 
     <add name="textWriterListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="YourLogFile.txt"/> 
     <add name="eventLogListener" type="System.Diagnostics.EventLogTraceListener" initializeData="YourEventLogSource" /> 
     <remove name="Default"/> 
     </listeners> 
    </trace> 
    </system.diagnostics> 
    // other config 
</configuration> 

или, если вы предпочитаете, вы можете также настроить слушателей в приложении, не в зависимости от файла конфигурации:

Trace.Listeners.Add(new TextWriterTraceListener("MyTextFile.log")); 

Не забудьте установить для свойства Trace.AutoFlush значение true, чтобы текстовый журнал работал правильно.

+0

Где он регистрируется? Текстовый файл? – Zapnologica

+2

Результат этого подхода зависит от настроек, которые вы настраиваете. То есть, для входа в текстовый файл, просто настройте System.Diagnostics.TextWriterTraceListener. – Mauro2

+0

Привет, Это работает, но он генерирует исключение: исключение типа «System.Security.SecurityException» произошло в System.dll, но не было обработано в коде пользователя. Таким образом, он записывает журналы, но не имеет на это разрешения. http://stackoverflow.com/questions/20389248/the-source-was-not-found-but-some-or-all-event-logs-could-not-be-searched-inac –

2

пример Heres для log4net:

  1. Создать новый консольный проект под названием Log4NetTest
  2. Добавить log4net [1.2.13] NuGet пакет в проекте
  3. Написать следующая программа:

    using System.Threading.Tasks; 
    using log4net; 
    using System.Text; 
    using System.CollectionsGeneric; 
    using System; 
    namespace Log4NetTest 
    { 
        class Program 
        { 
    
         private static readonly ILog _logger = LogManager.GetLogger("testApp.LoggingExample"); 
    
         static void Main(string[] args) 
         { 
          // Configure from App.config. This is marked as obsolete so you can also add config into separate config file 
          // and use log4net.Config.XmlConfigurator method to configure from xml file.    
          log4net.Config.DOMConfigurator.Configure(); 
    
          _logger.Debug("Shows only at debug"); 
          _logger.Warn("Shows only at warn"); 
          _logger.Error("Shows only at error"); 
    
          Console.ReadKey(); 
         } 
        } 
    } 
    
  4. Изменить app.config к следующему:

    <!-- language: xml --> 
    <?xml version="1.0" encoding="utf-8" ?> 
    <configuration> 
        <configSections> 
         <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> 
        </configSections> 
         <startup> 
           <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
         </startup> 
        <log4net debug="false"> 
         <appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" > 
          <param name="File" value="myLog.log" /> 
          <param name="AppendToFile" value="true" /> 
          <layout type="log4net.Layout.PatternLayout,log4net"> 
           <param name="ConversionPattern" value="%date [%thread] %-5level %logger %ndc - %message%newline" /> 
          </layout>  
         </appender> 
         <root> 
          <priority value="ALL" /> 
          <appender-ref ref="LogFileAppender" /> 
         </root> 
         <category name="testApp.LoggingExample"> 
          <priority value="ALL" /> 
         </category> 
        </log4net> 
    </configuration> 
    

5.Run приложение, и вы должны найдите следующий файл из папки bin \ Debug:

2013-12-13 13:27:27,252 [8] DEBUG testApp.LoggingExample (null) - Shows only at debug 
2013-12-13 13:27:27,280 [8] WARN testApp.LoggingExample (null) - Shows only at warn 
2013-12-13 13:27:27,282 [8] ERROR testApp.LoggingExample (null) - Shows only at error 
+0

Было очень сложно вставить этот XML-конфигуратор, не могли бы лучше стилизовать :( – Mino

8

Вы можете использовать SimpleLog.

Это простое, но надежное и мощное одноклассное решение для регистрации, которое легко понять, легко интегрируется и прост в использовании. Не нужно тратить дни на настройку и настройку log4Net, с этим классом вы делаете это за считанные минуты.

Хотя он в настоящее время регистрируется в файле, его следует легко настраивать для входа в базу данных.

http://www.codeproject.com/Tips/585796/Simple-Log

+0

Пожалуйста, не публикуйте ссылки только ответы –

+1

Было бы неплохо, если бы это было nuget pacakge – Zapnologica

+0

Ну, потребовалось две секунды, чтобы скачать ZIP и добавьте исходный файл в мое приложение. Спасибо. –

1

Создайте класс Log.cs Я использую Linq To Sql для сохранения в базе данных

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Reflection; 
using System.Runtime.CompilerServices; 
using System.Text; 
public static partial class Log 
{ 
    /// <summary> 
    /// Saves the exception details to ErrorLogging db with Low Priority 
    /// </summary> 
    /// <param name="ex">The exception.</param> 
    public static void Save(this Exception ex) 
    { 
     Save(ex, ImpactLevel.Low, ""); 
    } 

    /// <summary> 
    /// Saves the exception details to ErrorLogging db with specified ImpactLevel 
    /// </summary> 
    /// <param name="ex">The exception.</param> 
    /// <param name="impactLevel">The Impact level.</param> 
    public static void Save(this Exception ex, ImpactLevel impactLevel) 
    { 
     Save(ex, impactLevel,""); 
    } 
    /// <summary> 
    /// Saves the exception details to ErrorLogging db with specified ImpactLevel and user message 
    /// </summary> 
    /// <param name="ex">The exception</param> 
    /// <param name="impactLevel">The impact level.</param> 
    /// <param name="errorDescription">The error Description.</param> 
    public static void Save(this Exception ex, ImpactLevel impactLevel, string errorDescription) 
    { 
     using (var db = new ErrorLoggingDataContext()) 
     { 
      Log log = new Log(); 

      if (errorDescription != null && errorDescription != "") 
      { 
       log.ErrorShortDescription = errorDescription; 
      } 
      log.ExceptionType = ex.GetType().FullName; 
      var stackTrace = new StackTrace(ex, true); 
      var allFrames = stackTrace.GetFrames().ToList(); 
      foreach (var frame in allFrames) 
      { 
       log.FileName = frame.GetFileName(); 
       log.LineNumber = frame.GetFileLineNumber(); 
       var method = frame.GetMethod(); 
       log.MethodName = method.Name; 
       log.ClassName = frame.GetMethod().DeclaringType.ToString(); 
      } 

      log.ImpactLevel = impactLevel.ToString(); 
      try 
      { 
       log.ApplicationName = Assembly.GetCallingAssembly().GetName().Name; 
      } 
      catch 
      { 
       log.ApplicationName = ""; 
      } 

      log.ErrorMessage = ex.Message; 
      log.StackTrace = ex.StackTrace; 
      if (ex.InnerException != null) 
      { 
       log.InnerException = ex.InnerException.ToString(); 
       log.InnerExceptionMessage = ex.InnerException.Message; 
      } 
      log.IpAddress = ""; //get the ip address 

      if (System.Diagnostics.Debugger.IsAttached) 
      { 
       log.IsProduction = false; 
      } 

      try 
      { 
       db.Logs.InsertOnSubmit(log); 
       db.SubmitChanges(); 
      } 
      catch (Exception eex) 
      { 

      } 
     } 
    } 
} 

Создайте следующую таблицу

USE [database Name] 
GO 

/****** Object: Table [dbo].[Log] Script Date: 9/27/2016 11:52:32 AM ******/ 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

SET ANSI_PADDING ON 
GO 

CREATE TABLE [dbo].[Log](
    [LogId] [INT] IDENTITY(1,1) NOT NULL, 
    [ErrorDate] [DATETIME] NOT NULL CONSTRAINT [DF_Log_Date] DEFAULT (GETDATE()), 
    [ErrorShortDescription] [VARCHAR](1000) NULL, 
    [ExceptionType] [VARCHAR](255) NULL, 
    [FileName] [VARCHAR](1000) NULL, 
    [LineNumber] [INT] NULL, 
    [MethodName] [VARCHAR](255) NULL, 
    [ClassName] [VARCHAR](150) NULL, 
    [ImpactLevel] [VARCHAR](50) NOT NULL, 
    [ApplicationName] [VARCHAR](255) NULL, 
    [ErrorMessage] [VARCHAR](4000) NULL, 
    [StackTrace] [VARCHAR](MAX) NULL, 
    [InnerException] [VARCHAR](2000) NULL, 
    [InnerExceptionMessage] [VARCHAR](2000) NULL, 
    [IpAddress] [VARCHAR](150) NULL, 
    [IsProduction] [BIT] NOT NULL CONSTRAINT [DF_Log_IsProduction] DEFAULT ((1)), 
    [LastModified] [DATETIME] NOT NULL CONSTRAINT [DF_Log_LastModified] DEFAULT (GETDATE()), 
CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED 
(
    [LogId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

GO 

SET ANSI_PADDING OFF 
GO 

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'This table holds all the exceptions. 
ErrorData = when error happened 
,[ErrorShortDescription] == short desc about the error entered by the developers 
     ,[FileName] = file where error happened full path 
     ,[LineNumber] = line number where code failed 
     ,[MethodName] = method name where exception happened 
     ,[ClassName] = class where exception happened 
     ,[ImpactLevel] = high, medium, low 
     ,[ApplicationName] = name of the application where error came from 
     ,[ErrorMessage] = exception error messge 
     ,[StackTrace] = C# stack trace 
     ,[InnerException] = inner exception of strack trace 
     ,[InnerExceptionMessage] = inner message 
     ,[IpAddress] 
     ,[IsProduction]' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Log' 
GO 

Уровень воздействия в основном Enum

public enum ImpactLevel 
    { 
     High = 0, 
     Medium = 1, 
     Low = 2, 
    } 

Вы можете использовать его следующим образом

try 
{ 


} 
catch(Exception ex) 
{ 
    //this will save the exception details and mark exception as low priority 
    ex.Save(); 
} 


try 
{ 


} 
catch(Exception ex) 
{ 
    //this will save the exception details with priority you define: High, Medium,Low 
    ex.Save(ImpactLevel.Medium); 
} 

try 
{ 


} 
catch(Exception ex) 
{ 
    //this will save the exception details with priority you define: High, Medium,Low 
    ex.Save(ImpactLevel.Medium, "You can enter an details you want here "); 
} 
+0

Хороший вклад. Только то, что я почти делал. Благодаря! –

1

После прочтения предложения здесь, я в конечном итоге, используя следующие:

private void LogSystemError(string message) 
{ 
    EventLog.WriteEntry("YourAppName", message, EventLogEntryType.Error); 
} 

Класс EventLog доступен с помощью System.Diagnostics.

Я избегал возможности входа в файлы (например, «yourLogFile.txt»), чтобы избежать проблем с параллелизмом ошибок при записи нескольких потоков, местоположения файла и безопасности доступа и возможных проблем с тем, что файл тоже растет большой.

Смежные вопросы