92

I would like to implement logging in my application, but would rather not use any outside frameworks like log4net.

So I would like to do something like DOS's echo to a file. What is the most effective way to do it?

Is there a way to log unhandled exceptions logged without using an outside framework?

Tatranskymedved
  • 4,194
  • 3
  • 21
  • 47
IAdapter
  • 62,595
  • 73
  • 179
  • 242
  • 2
    I feel enterprise library better option than log4net. – hungryMind Feb 20 '11 at 14:39
  • 1
    You can use the built-in [System.Diagnostics.TraceSource](http://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx).
    Here is a list of [the built in trace listeners](http://msdn.microsoft.com/en-us/library/4y5y10s7.aspx) + [FileLogTraceListener](http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.logging.filelogtracelistener.aspx). There are many manuals over the web [like this](http://www.thejoyofcode.com/from_zero_to_logging_with_system_diagnostics_in_15_minutes.aspx), [or this one by Jeff Atwood](http://www.codinghorror.com/blog/2005/03/logging-tracelistener
    – HuBeZa Feb 20 '11 at 14:38
  • If you're only looking for simple console logging, System.Diagnostics.Tracing is probably for you. Trace can be used like Console (Trace.WriteLine). – Paul Apr 04 '19 at 12:13

7 Answers7

66
public void Logger(string lines)
{
  //Write the string to a file.append mode is enabled so that the log
  //lines get appended to  test.txt than wiping content and writing the log

  using(System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test.txt", true))
  {
    file.WriteLine(lines);
  }
}

For more information MSDN

live2
  • 3,771
  • 2
  • 37
  • 46
Brandon
  • 1,412
  • 11
  • 15
  • 22
    you should use a `using` on file, though since it is local to a method will get diposed soon anyway. – markmnl May 21 '14 at 04:58
  • 19
    Also keep in mind that when `file.WriteLine(lines);` throws an exception, the code will never hit `file.Close();`. Making use of `using` is an equivalent for `try { // using block } finally { // Dispose }`. This means that the object will be disposed even if the code inside the `using` block throws an exception, – Memet Olsen Mar 04 '15 at 14:59
  • 7
    What if this method is called again before the logging is complete? You will raise an error - The process cannot access the file 'C:\test.txt' because it is being used by another process. Does anyone know away around this problem? – Mike Sportsman May 11 '16 at 14:38
23

I would rather not use any outside frameworks like log4j.net.

Why? Log4net would probably address most of your requirements. For example check this class: RollingFileAppender.

Log4net is well documented and there are thousand of resources and use cases on the web.

empi
  • 15,755
  • 8
  • 62
  • 78
  • 3
    the reason is that I have never used any outside libs in .net, so I first need to learn how to do it ;) – IAdapter Feb 20 '11 at 14:32
  • 4
    Just add reference to your project and place some xml configuration - it's really easy. Google for log4net tutorial and choose the one that is best for you. – empi Feb 20 '11 at 14:35
  • 23
    Use Nuget. Using outside libraries will become a breeze – heneryville Mar 16 '13 at 04:12
  • 3
    Using external framework is nice for home projects, but for a big corporate an open source project is a potential threat where people outside the company can inject code in the projects. So it's usually strictly regulated. – Kobor42 Sep 25 '13 at 10:33
  • 37
    Why so many upvotes? The question states twice OP doesn't want to use an external framework and explicitly mentions not wanting Log4net. Surely this should be a comment, not an answer? – RyanfaeScotland Mar 31 '15 at 10:32
  • 1
    Aye; and you don't understand something until you can create it. – Tim Barrass Sep 11 '15 at 18:11
  • log4net is starting to be a bit old. There are other options like Logary: https://github.com/logary/logary – Tuomas Hietanen Aug 19 '16 at 13:54
  • @TuomasHietanen It's still being maintained. What does age have to do with it? .Net itself is like 15 years old. – Andy Aug 20 '16 at 00:37
  • 9
    @RyanfaeScotland You're right, maybe it won't suit OP but please don't forget that this is a public site. Since the Question's title only states "How to do logging in c#", also people like me who're fine with using any library will land here and find this answer useful. In fact, this thread was the first result when I googled for "c# logging". – swenzel Nov 05 '16 at 15:04
  • @swenzel Answers shouldn't be based on the title alone. Just cause it is useful doesn't make it suitable as an answer. Also my comment was a year and a half ago, I'm no longer debating this. – RyanfaeScotland Nov 05 '16 at 15:13
  • Is the Link to RollingFileAppeder dead? It gives me Not Found error. – Mohit Mar 29 '18 at 13:52
  • This answer is useful for me. – Paul Apr 04 '19 at 11:22
  • sometimes when your logging needs are simple you dont want to install these library and write additional code. – Lightsout Aug 05 '21 at 21:19
18

You can write directly to an event log. Check the following links:
http://support.microsoft.com/kb/307024
http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx

And here's the sample from MSDN:

using System;
using System.Diagnostics;
using System.Threading;

class MySample{

    public static void Main(){

        // Create the source, if it does not already exist.
        if(!EventLog.SourceExists("MySource"))
        {
             //An event log source should not be created and immediately used.
             //There is a latency time to enable the source, it should be created
             //prior to executing the application that uses the source.
             //Execute this sample a second time to use the new source.
            EventLog.CreateEventSource("MySource", "MyNewLog");
            Console.WriteLine("CreatedEventSource");
            Console.WriteLine("Exiting, execute the application a second time to use the source.");
            // The source is created.  Exit the application to allow it to be registered.
            return;
        }

        // Create an EventLog instance and assign its source.
        EventLog myLog = new EventLog();
        myLog.Source = "MySource";

        // Write an informational entry to the event log.    
        myLog.WriteEntry("Writing to event log.");

    }
}
šljaker
  • 7,294
  • 14
  • 46
  • 80
  • 1
    What's the best practise to use the same EventLog in different classes? Pass it as parameter in Constructor? Access it statically from some singleton class? Or anything better? – dpelisek Jul 23 '15 at 11:59
15

If you are looking for a real simple way to log, you can use this one liner. If the file doesn't exist, it's created.

System.IO.File.AppendAllText(@"c:\log.txt", "mymsg\n");
dan-gph
  • 16,301
  • 12
  • 61
  • 79
live-love
  • 48,840
  • 22
  • 240
  • 204
  • The problem with this solution is that it adds IO operation. So using it is not recommended for logging batch algorithm operations – Rami Yampolsky Aug 13 '15 at 09:51
  • @RamiYampolsky, I don't understand what you mean. – dan-gph Jul 06 '16 at 07:54
  • @dan-gph If you implement some code which is doing a lot of CPU operations, in case of logging during this code, you "waste" some time that is for logging instead of the actual algorithm that you try to implement. So you prefer to "waste" as short time as possible. Doing IO operation like in the example above is really long, so if you have a lot of logging commands in your code, it can make your whole execution about 1000 times slower! – Rami Yampolsky Jul 07 '16 at 09:07
  • @RamiYampolsky, I just made that code loop 100,000 times, and it took 10s. So that's 10,000 log entries per second, which is 0.01 microseconds per entry. If you logged 10 things in 1 second, that would take 0.1 microseconds. So no, that is not much overhead at all. – dan-gph Jul 07 '16 at 09:39
  • @dan-gph My answer related for different use case. Try to do loop 100,000 times that makes some calculation for simplicity, just do sum += i and then do the log. Try it with and without the log – Rami Yampolsky Jul 07 '16 at 10:36
  • @dan-gph by the way, as your results looked me very impressive for IO operation I made same experiment (with 1000 iterations) and it took ~3 seconds, making it 3 ms per iteration. Can you check that the log file actually created? – Rami Yampolsky Jul 07 '16 at 10:46
  • @RamiYampolsky, I tested it again. It took 10s. I'll post the code in the next comment. This is what I did: (1) Delete the log file manually, (2) run the code in LINQPad 4 in "C# Statements" mode, (3) note the time (10.101s), (4) look at the log file: the last line was "mymsg,99999,704982704" and it was on line 100,000 in my text editor, (5) run the code again, appending to the same file, (6) it took 10.845s (6) verify the file. – dan-gph Jul 08 '16 at 01:26
  • int sum = 0; for (int i = 0; i < 100000; ++i) { sum += i; System.IO.File.AppendAllText(@"e:\scratch\log.txt", string.Format("mymsg,{0},{1}\n", i, sum)); } – dan-gph Jul 08 '16 at 01:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/116749/discussion-between-dan-gph-and-rami-yampolsky). – dan-gph Jul 08 '16 at 01:28
7

I used to write my own error logging until I discovered ELMAH. I've never been able to get the emailing part down quite as perfectly as ELMAH does.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jonezy
  • 1,903
  • 13
  • 21
  • I will look at it, for my reasoning please checkout mine empi's comment. – IAdapter Feb 20 '11 at 14:38
  • ELMAH is so straight forward it's not even funny, you literally can drop it in an add a few lines to your web config and it's working. – jonezy Feb 20 '11 at 14:41
  • Also in terms of your requirement for knowing when your app is about to/starting to blow up I find elmah is better than most others because of it's ability to send emails, so as long as the server is up you'll get error emails from elmah. – jonezy Feb 20 '11 at 14:42
6

If you want to stay close to .NET check out Enterprise Library Logging Application Block. Look here. Or for a quickstart tutorial check this. I have used the Validation application Block from the Enterprise Library and it really suits my needs and is very easy to "inherit" (install it and refrence it!) in your project.

Youp Bernoulli
  • 5,303
  • 5
  • 39
  • 59
4

If you want your own custom Error Logging you can easily write your own code. I'll give you a snippet from one of my projects.

public void SaveLogFile(object method, Exception exception)
{
    string location = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\FolderName\";
    try
    {
        //Opens a new file stream which allows asynchronous reading and writing
        using (StreamWriter sw = new StreamWriter(new FileStream(location + @"log.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
        {
            //Writes the method name with the exception and writes the exception underneath
            sw.WriteLine(String.Format("{0} ({1}) - Method: {2}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), method.ToString()));
            sw.WriteLine(exception.ToString()); sw.WriteLine("");
        }
    }
    catch (IOException)
    {
        if (!File.Exists(location + @"log.txt"))
        {
            File.Create(location + @"log.txt");
        }
    }
}

Then to actually write to the error log just write (q being the caught exception)

SaveLogFile(MethodBase.GetCurrentMethod(), `q`);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MisdartedPenguin
  • 258
  • 1
  • 2
  • 12