How to dynamically set log file using App.config and System.Diagnostics?

点点圈 提交于 2019-12-07 08:28:38

问题


I was looking for a solution to provide logging to my latest project when I came across an article ( http://www.daveoncsharp.com/2009/09/create-a-logger-using-the-trace-listener-in-csharp/ ) that talked about using System.Diagnostics and App.config to log via the Trace method. I was able to successfully implement both the class and the App.config but I'd really like to be able to dynamically assign the value/location (inside initializeData) of the log file and I don't have a clue how to do it. If you have any suggestions, please feel free to post!

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="myListener" 
             type="System.Diagnostics.TextWriterTraceListener" 
             initializeData="fileSizeThreshold=512, fileSizeUnit=kilobytes, 
             fileAgeThreshold=1, fileAgeUnit=months, fileNameTemplate='{0}\MyApp-{1:MMM-yy}.log'"/>
        <remove name="Default" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Logger Class:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;


namespace MyCurrentProject
{
    class Logger
    {
        public void Error(string module, string message)
        {
            WriteEntry(message, "ERROR:", module);
        }

        public void Error(Exception ex, string module)
        {
            WriteEntry(ex.Message, "ERROR:", module);
        }

        public void Warning(string module, string message)
        {
            WriteEntry(message, "WARNING:", module);
        }

        public void Info(string module, string message)
        {
            WriteEntry(message, "INFO:", module);
        }

        private void WriteEntry(string message, string type, string module)
        {
            Trace.WriteLine(
                    string.Format("{0} {1} [{2}] {3}",
                                  DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                  type,
                                  module,
                                  message));
        }
    }
}

RE: Sorry for not being clear... just to be clear, I need the file path that the log file output is save to to be dynamically set. I'd like the path to save to a location in %AppData%. The problem I had with the config was that once I set the value for 'initializeData' I couldn't find a way to change or dynamically set/reset that value. Truthfully... at this point I just want a solution that works and allows me to manage the location of the log file.


回答1:


Here is a worked example using Systems.Diagnostics, which has two advantages over non-base class libraries. It is always allowed (in large organizations), always available, and to the extent that developers are familiar with the base class library, the next batch of maintenance developers will have heard of it.

using System.Diagnostics;

namespace DynamicTraceLog
{
    class Program
    {
        static void Main(string[] args)
        {
            //Use TraceSource, not Trace, they are easier to turn off
            TraceSource trace = new TraceSource("app");
            //SourceSwitches allow you to turn the tracing on and off.
            SourceSwitch level =new SourceSwitch("app");
            //I assume you want to be dynamic, so probalby some user input would be here:
            if(args.Length>0 && args[0]=="Off")
                level.Level= SourceLevels.Off;
            else
                level.Level = SourceLevels.Verbose;
            trace.Switch = level;
            //remove default listner to improve performance
            trace.Listeners.Clear();
            //Listeners implement IDisposable
            using (TextWriterTraceListener file = new TextWriterTraceListener("log.txt"))
            using (ConsoleTraceListener console = new ConsoleTraceListener())
            {
                //The file will likely be in /bin/Debug/log.txt
                trace.Listeners.Add(file);
                //So you can see the results in screen
                trace.Listeners.Add(console);
                //Now trace, the console trace appears immediately.
                trace.TraceInformation("Hello world");
                //File buffers, it flushes on Dispose or when you say so.
                file.Flush();
            }
            System.Console.ReadKey();
        }
    }
}

Re: how to format the output Try either of these two for trace listeners that implement templated trace formating/output using Systems.Diagnostics classes: http://essentialdiagnostics.codeplex.com or http://ukadcdiagnostics.codeplex.com/ Systems.Diagnostics doesn't provide for any particular formating or outputing of standard tokens.




回答2:


I know I may get down voted for this, but I'm going to go off the ranch for a minute and I'm going to suggest you use a different tool from the toolbox. Log4Net is a very powerful and succinct logging framework. For example, below is a console application that uses it and it's fully functional as you see it.

using Com.Foo;

// Import log4net classes.
using log4net;
using log4net.Config;

public class MyApp 
{
    // Define a static logger variable so that it references the
    // Logger instance named "MyApp".
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args) 
    {
        // Set up a simple configuration that logs on the console.
        BasicConfigurator.Configure();

        log.Info("Entering application.");
        Bar bar = new Bar();
        bar.DoIt();
        log.Info("Exiting application.");
    }
}

But let's say we wanted to do that with a configuration file just like you're implying you would like to use. Well, that's pretty straight forward! Below is the configuration we'd place in the App.config to accomplish the same thing:

<log4net>
    <!-- A1 is set to be a ConsoleAppender -->
    <appender name="A1" type="log4net.Appender.ConsoleAppender">

        <!-- A1 uses PatternLayout -->
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
        </layout>
    </appender>

    <!-- Set root logger level to DEBUG and its only appender to A1 -->
    <root>
        <level value="DEBUG" />
        <appender-ref ref="A1" />
    </root>
</log4net>

Then that configuration can be used like this:

using Com.Foo;

// Import log4net classes.
using log4net;
using log4net.Config;

public class MyApp 
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args) 
    {
        // BasicConfigurator replaced with XmlConfigurator.
        XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));

        log.Info("Entering application.");
        Bar bar = new Bar();
        bar.DoIt();
        log.Info("Exiting application.");
    }
}

And don't let the pattern stuff catch you off guard, it's just configuring what you're coding above so that you can have some consistency in the messages. It really keeps it easy though because all you ever have to log is the information that needs to be plugged into the pattern and the pattern is then encapsulated away.


This is a crash course in Log4Net, but the reason I'm really recommending it is because in the two examples above you see that they logged to the console, but you have a myriad of possible loggers, just look at this list:

log4net.Appender.AdoNetAppender: Writes logging events to a database using either prepared statements or stored procedures.

log4net.Appender.AnsiColorTerminalAppender: Writes color highlighted logging events to a an ANSI terminal window.

log4net.Appender.AspNetTraceAppender: Writes logging events to the ASP trace context. These can then be rendered at the end of the ASP page or on the ASP trace page.

log4net.Appender.ColoredConsoleAppender: Writes color highlighted logging events to the application's Windows Console.

log4net.Appender.ConsoleAppender: Writes logging events to the application's Console. The events may go to either the standard our stream or the standard error stream.

log4net.Appender.DebugAppender: Writes logging events to the .NET system.

log4net.Appender.EventLogAppender: Writes logging events to the Windows Event Log.

log4net.Appender.FileAppender: Writes logging events to a file in the file system.

log4net.Appender.LocalSyslogAppender: Writes logging events to the local syslog service (UNIX only).

log4net.Appender.MemoryAppender: Stores logging events in an in memory buffer.

log4net.Appender.NetSendAppender: Writes logging events to the Windows Messenger service. These messages are displayed in a dialog on a users terminal.

log4net.Appender.OutputDebugStringAppender: Writes logging events to the debugger. If the application has no debugger, the system debugger displays the string. If the application has no debugger and the system debugger is not active, the message is ignored.

log4net.Appender.RemoteSyslogAppender: Writes logging events to a remote syslog service using UDP networking.

log4net.Appender.RemotingAppender: Writes logging events to a remoting sink using .NET remoting.

log4net.Appender.RollingFileAppender: Writes logging events to a file in the file system. The RollingFileAppender can be configured to log to multiple files based upon date or file size constraints.

log4net.Appender.SmtpAppender: Sends logging events to an email address.

log4net.Appender.SmtpPickupDirAppender: Sends logging events to an email address but writes the emails to a configurable directory rather than sending them directly via SMTP.

log4net.Appender.TelnetAppender: Clients connect via Telnet to receive logging events.

log4net.Appender.TraceAppender: Writes logging events to the .NET trace system.

log4net.Appender.UdpAppender: Sends logging events as connectionless UDP datagrams to a remote host or a multicast group using a UdpClient.


So, as you can see, it's extremely capable OOB. I hope this post has been helpful.



来源:https://stackoverflow.com/questions/12810475/how-to-dynamically-set-log-file-using-app-config-and-system-diagnostics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!