Minimalist logging for Habbo emulators

c4353b8e

New Member
May 26, 2018
20
8
I know a lot of emulators use the package log4net & a few others but I've always seen it as overload, especially how emulators never really get into using even half of the functionality of that package. I put together a simple clone of what NLog does in a single class.

If anybody likes writing their own code, or just need something minimal, here you go. It could be written a lot better but what couldn't, it serves its purpose & I'm happy with the code quality it's at. You probably don't need the File.Exists part inside the final method, but I just put it there for safety. Id recommend throwing an interface on this too so you can have multiple types of ILogger

Code:
public class ConsoleLogger <TClass> : ILogger, IDisposable
{
    private readonly string _filePath;
    private readonly Type _className;
    private readonly Dictionary<string, StreamWriter> _streams;

    public ConsoleLogger()
    {
        _filePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location + "/resources/logging/");
        _className = typeof(TClass);
        _streams = new Dictionary<string, StreamWriter>();
    }

    private readonly Dictionary<LogType, string> _fileForLogType = new Dictionary<LogType, string> {
        {LogType.Success , "trace.log"},
        {LogType.Warn ,    "error.log"},
        {LogType.Error ,   "error.log"},
        {LogType.Debug ,   "debug.log"},
    };

    private readonly Dictionary<LogType, ConsoleColor> _colorForLogType = new Dictionary<LogType, ConsoleColor> {
        {LogType.Success , ConsoleColor.Green},
        {LogType.Warn ,    ConsoleColor.Yellow},
        {LogType.Error ,   ConsoleColor.Red},
        {LogType.Debug ,   ConsoleColor.Cyan},
    };

    public void Trace(string message, bool logToFile = false)
    {
        Log(message, LogType.Trace, logToFile);
    }

    public void Warn(string message, bool logToFile = false)
    {
        Log(message, LogType.Warn, logToFile);
    }

    public void Debug(string message, bool logToFile = false)
    {
        Log(message, LogType.Debug, logToFile);
    }

    public void Success(string message, bool logToFile = false)
    {
        Log(message, LogType.Success, logToFile);
    }

    public void Error(string message, bool logToFile = false)
    {
        Log(message, LogType.Error, logToFile);
    }

    public void Error(Exception e, bool logToFile = true)
    {
        Log("An error occurred: " + Environment.NewLine + e, LogType.Error, logToFile);
    }

    private void Log(string message, LogType logType, bool logToFile = false)
    {
        var oldColor = Console.ForegroundColor;

        Console.ForegroundColor = _colorForLogType[logType];
        Console.WriteLine($"[{DateTime.Now:MM/dd HH:mm:ss}] " + message);
        Console.ForegroundColor = oldColor;
    
        if (logToFile)
        {
            LogToFile(_fileForLogType[logType], $"Occurred at [{DateTime.Now:MM/dd HH:mm:ss}] in [{_className.FullName}]: {message}");
        }
    }
 
    private void LogToFile(string file, string content)
    {
        var fullPath = Path.Combine(_filePath, file);

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

        if (!File.Exists(fullPath))
        {
            File.Create(fullPath);
        }

        if (!_streams.ContainsKey(file))
        {
            _streams.Add(file, new StreamWriter(_filePath + file, true));
        }

        _streams[file].WriteLine(content);
    }

    public void Dispose()
    {
        foreach (var stream in _streams.Values)
        {
            stream.Dispose();
        }
    }
}

Update: Improved code quality, cached streams, & better logic for getting the files & colors via log type.

Here are the other files.
Code:
public enum LogType
{
    Trace,
    Warn,
    Debug,
    Success,
    Error
}

& the interface
Code:
public interface ILogger
{
    void Trace(string message, bool logToFile = false);
    void Warn(string message, bool logToFile = false);
    void Debug(string message, bool logToFile = false);
    void Success(string message, bool logToFile = false);
    void Error(string message, bool logToFile = false);
    void Error(Exception e, bool logToFile = true);
}

Here's some usage, using statement for instant disposal.
Code:
using (var logger = new ConsoleLogger(typeof(Program)))
{
    logger.Debug("test");
    logger.Warn("test");
    logger.Trace("test");
    logger.Success("test");
    logger.Error("test", true);
}

Don't do the using approach in production, it'll close the streams instantly and the caching is useless. Create a property for each class that requires to log and you can use it throughout its lifetime.
 
Last edited:

Users who are viewing this thread

Top