Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing Logs to an XML File with .NET

Tags:

c#

xml

I am storing logs in an xml file...

In a traditional straight text format approach, you would typically just have a openFile... then writeLine method...

How is it possible to add a new entry into the xml document structure, like you would just with the text file approach?

like image 887
JL. Avatar asked Jul 13 '09 23:07

JL.


People also ask

What is log XML file?

The Logger. xml file is located at the root level of the /conf directory and is the configuration file for the logging file system. Logger. xml contains the elements and information used to configure log files. You can edit this file to add or change configuration information, including the location of the log files.

Can XML used with C#?

C# XmlDocument tutorial shows how to work with XML in C# with XmlDocument. Extensible Markup Language (XML) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable. XML is often used for application configuration, data storage and exchange.


5 Answers

One of the problems with writing a log file in XML format is that you can't just append lines to the end of the file, because the last line has to have a closing root element (for the XML to be valid)

This blog post by Filip De Vos demonstrates quite a good solution to this:
High Performance writing to XML Log files (edit: link now dead so removed)

Basically, you have two XML files linked together using an XML-include thing:

Header file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log [
<!ENTITY loglines SYSTEM "loglines.xml">
]>
<log>
&loglines;
</log>

Lines file (in this example, named loglines.xml):

<logline date="2007-07-01 13:56:04.313" text="start process" />
<logline date="2007-07-01 13:56:25.837" text="do something" />
<logline date="2007-07-01 13:56:25.853" text="the end" />

You can then append new lines to the 'lines file', but (most) XML parsers will be able to open the header file and read the lines correctly.

Filip notes that: This XML will not be parsed correctly by every XML parser on the planet. But all the parsers I have used do it correctly.

like image 20
codeulike Avatar answered Oct 26 '22 21:10

codeulike


use an XmlWriter.

example code:

    public class Quote
    {
        public string symbol;
        public double price;
        public double change;
        public int volume;
    }


    public void Run()
    {
        Quote q = new Quote
            {
                symbol = "fff",
                price = 19.86,
                change = 1.23,
                volume = 190393,
                };
        WriteDocument(q);
    }



    public void WriteDocument(Quote q) 
    {
        var settings = new System.Xml.XmlWriterSettings
            {
                OmitXmlDeclaration = true,
                Indent= true
            };

        using (XmlWriter writer = XmlWriter.Create(Console.Out, settings))
        {
            writer.WriteStartElement("Stock");
            writer.WriteAttributeString("Symbol", q.symbol);
            writer.WriteElementString("Price", XmlConvert.ToString(q.price));
            writer.WriteElementString("Change", XmlConvert.ToString(q.change));
            writer.WriteElementString("Volume", XmlConvert.ToString(q.volume));
            writer.WriteEndElement();
        }
    }

example output:

<Stock Symbol="fff">
  <Price>19.86</Price>
  <Change>1.23</Change>
  <Volume>190393</Volume>
</Stock>

see Writing with an XmlWriter for more info.

like image 169
Cheeso Avatar answered Oct 26 '22 21:10

Cheeso


The big difference is the way you are thinking about your log data. In plain text files you are indeed just adding new lines. XML is a tree structure however, and you need to think about like such. What you are adding is probably another NODE, i.e.:

<log>
   <time>12:30:03 PST</time>
   <user>joe</user>
   <action>login</action>
<log>

Because it is a tree what you need to ask is what parent are you adding this new node to. This is usually all defined in your DTD (Aka, how you are defining the structure of your data). Hopefully this is more helpful then just what library to use as once you understand this principle the interface of the library should make more sense.

like image 41
Scanningcrew Avatar answered Oct 26 '22 20:10

Scanningcrew


Why reinvent the wheel? Use TraceSource Class (System.Diagnostics) with the XmlWriterTraceListener.

like image 27
John Saunders Avatar answered Oct 26 '22 22:10

John Saunders


Sorry to post a answer for old thread. i developed the same long time ago. here i like to share my full code for logger saved log data in xml file date wise.

logger class code

using System.IO;
using System.Xml;
using System.Threading;

public class BBALogger
    {
        public enum MsgType
        {
            Error ,
            Info 
        }

        public static BBALogger Instance
        {
            get
            {
                if (_Instance == null)
                {
                    lock (_SyncRoot)
                    {
                        if (_Instance == null)
                            _Instance = new BBALogger();
                    }
                }
                return _Instance;
            }
        }

        private static BBALogger _Instance;
        private static object _SyncRoot = new Object();
        private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();

        private BBALogger()
        {
            LogFileName = DateTime.Now.ToString("dd-MM-yyyy");
            LogFileExtension = ".xml";
            LogPath= Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Log";
        }

        public StreamWriter Writer { get; set; }

        public string LogPath { get; set; }

        public string LogFileName { get; set; }

        public string LogFileExtension { get; set; }

        public string LogFile { get { return LogFileName + LogFileExtension; } }

        public string LogFullPath { get { return Path.Combine(LogPath, LogFile); } }

        public bool LogExists { get { return File.Exists(LogFullPath); } }

        public void WriteToLog(String inLogMessage, MsgType msgtype)
        {
            _readWriteLock.EnterWriteLock();
            try
            {
                LogFileName = DateTime.Now.ToString("dd-MM-yyyy");

                if (!Directory.Exists(LogPath))
                {
                    Directory.CreateDirectory(LogPath);
                }

                var settings = new System.Xml.XmlWriterSettings
                {
                    OmitXmlDeclaration = true,
                    Indent = true
                };

                StringBuilder sbuilder = new StringBuilder();
                using (StringWriter sw = new StringWriter(sbuilder))
                {
                    using (XmlWriter w = XmlWriter.Create(sw, settings))
                    {
                        w.WriteStartElement("LogInfo");
                        w.WriteElementString("Time", DateTime.Now.ToString());
                        if (msgtype == MsgType.Error)
                            w.WriteElementString("Error", inLogMessage);
                        else if (msgtype == MsgType.Info)
                            w.WriteElementString("Info", inLogMessage);

                        w.WriteEndElement();
                    }
                }
                using (StreamWriter Writer = new StreamWriter(LogFullPath, true, Encoding.UTF8))
                {
                    Writer.WriteLine(sbuilder.ToString());
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                _readWriteLock.ExitWriteLock();
            }
        }

        public static void Write(String inLogMessage, MsgType msgtype)
        {
            Instance.WriteToLog(inLogMessage, msgtype);
        }
    }

Calling or using this way

    BBALogger.Write("pp1", BBALogger.MsgType.Error);
    BBALogger.Write("pp2", BBALogger.MsgType.Error);
    BBALogger.Write("pp3", BBALogger.MsgType.Info);
    MessageBox.Show("done");

may my code help you and other :)

like image 42
Mou Avatar answered Oct 26 '22 20:10

Mou