Simple logger class in C# I've been using logging libraries recently and somebody told me to try and write my own. I've kept it minimal but the only drawback is I can't log in static classes, due to TClass.



Follow-up



I'm looking for constructive criticism on how to improve it.

How do I declare a logger variable?

private static readonly Logger&lt;CatalogController&gt; Logger = new Logger&lt;CatalogController&gt;();


I guess another drawback is that its pretty long, including the class name (twice) and then all the access modifiers and class names of the logger, it an get pretty ugly.

public class Logger &lt;TClass&gt;
{
    private readonly Type _className;

    public Logger()
    {
        _className = typeof(TClass);
    }

    public void Trace(string message, bool log = false)
    {
        Log(message, ConsoleColor.White, log);
    }

    public void Warn(string message, bool log = false)
    {
        Log(message, ConsoleColor.Yellow, log);
    }

    public void Debug(string message, bool log = false)
    {
        Log(message, ConsoleColor.Cyan, log);
    }

    public void Success(string message, bool log = false)
    {
        Log(message, ConsoleColor.Green, log);
    }

    public void Error(string message, bool log = false)
    {
        Log(message, ConsoleColor.Red, log);
    }

    public void Error(Exception e)
    {
        Log("An error occurred: " + Environment.NewLine + e, ConsoleColor.Red);
    }

    private void Log(string message, ConsoleColor color, bool log = false)
    {
        var oldColor = Console.ForegroundColor;
        Console.ForegroundColor = color;
        Console.WriteLine($"[{DateTime.Now:MM/dd HH:mm:ss}] " + message);
        Console.ForegroundColor = oldColor;

        string logFile;

        switch (color)
        {
            case ConsoleColor.Yellow:
                logFile = "error.log";
                break;
            case ConsoleColor.Cyan:
                logFile = "debug.log";
                break;
            case ConsoleColor.Red:
                logFile = "error.log";
                break;
            default:
                logFile = "trace.log";
                break;
        }

        LogToFile(logFile, $"Occurred at [{DateTime.Now:MM/dd HH:mm:ss}] in [{_className.FullName}]: " + message);
    }

    private static void LogToFile(string file, string content)
    {
        var executionPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        var fileWriter = new StreamWriter(executionPath + "/resources/logging/" + file, true);

        fileWriter.WriteLine(content);
        fileWriter.Close();
    }
}
I have two notes to make here,


Extract a public interface from this code, like ILogger&lt;T&gt;, and store (or inject) an ILogger&lt;T&gt; instead of a Logger&lt;T&gt;


This will allow you to create different implementations of your logger type and pass it to the consumers of your logger without them knowing/caring whether it's logging to a console, to a file, or to a typewriter. 

An important use case for that is creating an ILogger implementation for unit tests. You probably don't want your unit tests to have any side effects, so you could create a TestLogger class that implements ILogger and records all the logs to a list instead of a to a file or console.


Handle write access in a safer way


Currently you are not disposing of your StreamWriter instance. Even though you are calling Close you really should be either using a using statement or having a single instance of the stream writer that is accessed through an actor or other thread safe method and is disposed when your logger is disposed.

(Less important, but I would also store the execution path in a static readonly

private static readonly string executionPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location + "/resources/logging/" + file;

private static void LogToFile(string file, string content)
{
    using (var fileWriter = new StreamWriter(executionPath, true))
    {
        fileWriter.WriteLine(content);
        fileWriter.Close();
    }
}