Simple way to perform error logging?

2019-03-08 03:50发布

I've created a small C# winforms application, as an added feature I was considering adding some form of error logging into it. Anyone have any suggestions for good ways to go about this? This is a feature I've never looked into adding to previous projects, so I'm open to suggestions from Developers who have more experience.

I was considering something along the lines of writing exceptions to a specified text file, or possibly a database table. This is an application that will be in use for a few months and then discarded when a larger product is finished.

8条回答
女痞
2楼-- · 2019-03-08 03:55

I wouldn't dig too much on external libraries since your logging needs are simple.

.NET Framework already ships with this feature in the namespace System.Diagnostics, you could write all the logging you need there by simply calling methods under the Trace class:

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

And then configure all the trace listeners that fit your needs on your app.config file:

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

or if you prefer, you can also configure your listeners in your application, without depending on a config file:

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

Remember to set the Trace.AutoFlush property to true, for the Text log to work properly.

查看更多
冷血范
3楼-- · 2019-03-08 03:56

You could use SimpleLog.

It's a simple, but robust and powerful one-class logging solution, easy to understand, easy to integrate and easy to use. No need to spend days for setting up and customize log4Net, with that class, you're done in minutes.

Though it currently logs to a file, it should be easily customizable to log to a database.

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

查看更多
看我几分像从前
4楼-- · 2019-03-08 03:56

Create a class called Log.cs I am using Linq To SQl to save to the database

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)
            {

            }
        }
    }
}

Create the following table

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

Impact Level is basically Enum

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

You can use it as following

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 ");
}
查看更多
smile是对你的礼貌
5楼-- · 2019-03-08 04:00

After reading the suggestions here, I ended up using the following:

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

The EventLog class is available using System.Diagnostics.

I avoided the options of logging into files (e.g. "yourLogFile.txt") to avoid issues of concurrency of multiple threads logging errors, location of the file and access security, and the possible issues of having a file that grows too large.

查看更多
看我几分像从前
6楼-- · 2019-03-08 04:02

Well log4net works like a brick. It may be a bit hard to configure, but its worth it. It also allows you to configure file locking of those log files etc.

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

查看更多
男人必须洒脱
7楼-- · 2019-03-08 04:03

An optimal solution, in my opinion, would be to use NLog: http://nlog-project.org/

Just install the config package from NuGet: http://www.nuget.org/packages/NLog.Config/ and you will end up with the library and a pre-configured file logger...

Then in your code you just need:

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

In the config file you get, you need to uncomment the sections that you need:

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

Edit the properties of the nlog.config file to

Copy to Output Directory: Copy always
查看更多
登录 后发表回答