Sunday, July 24, 2016

Make your NuGet Server use NLog

The latest version of NuGet.Server is fast, stable, and super simple to setup. As for most .NET tools, Scott Hanselman already create a great write up about how to use it.

However, I was very disappointed at how unintuitive it was to get wire up a custom logger!

You need to take several steps to make the official NuGet server write to something like NLog:

  1. Create a log wrapper.
  2. Implement NuGet.Server.Logging.ILogger.
  3. Implement NuGet.ILogger...
  4. ...which also makes you implement NuGet.IFileConflictResolver!
  5. Implement your own NuGet.Server.IServiceResolver
  6. When instantiating ServerPackageRepository...
  7. ...pass in the ILogger...
  8. ...AND set the Logger property!

Still confused? Pull the code here, or take a look below!

NLogLogger

public class NLogLogger : Logging.ILogger, ILogger
{
    private readonly global::NLog.ILogger _logger;
 
    public NLogLogger(global::NLog.ILogger logger)
    {
        _logger = logger;
    }
 
    public void Log(LogLevel level, string message, params object[] args)
    {
        switch (level)
        {
            case LogLevel.Verbose:
                _logger.Trace(message, args);
                break;
 
            case LogLevel.Info:
                _logger.Info(message, args);
                break;
 
            case LogLevel.Warning:
                _logger.Warn(message, args);
                break;
 
            case LogLevel.Error:
                _logger.Error(message, args);
                break;
 
            default:
                throw new ArgumentOutOfRangeException(nameof(level), level, null);
        }
    }
 
    public FileConflictResolution ResolveFileConflict(string message)
    {
        _logger.Warn(message);
 
        // This is what the default NullLogger returns.
        return FileConflictResolution.Ignore;
    }
 
    public void Log(MessageLevel level, string message, params object[] args)
    {
        switch (level)
        {
            case MessageLevel.Info:
                _logger.Info(message, args);
                break;
 
            case MessageLevel.Warning:
                _logger.Warn(message, args);
                break;
 
            case MessageLevel.Debug:
                _logger.Debug(message, args);
                break;
 
            case MessageLevel.Error:
                _logger.Error(message, args);
                break;
 
            default:
                throw new ArgumentOutOfRangeException(nameof(level), level, null);
        }
    }
}

NLogServiceResolver

public class NLogServiceResolver : IServiceResolver
{
    private readonly IHashProvider _hashProvider;
    private readonly IServerPackageRepository _packageRepository;
    private readonly IPackageAuthenticationService _packageAuthenticationService;
    private readonly IPackageService _packageService;
    private readonly ILogger _logger;
    private readonly Logging.ILogger _loggingLogger;
 
    public NLogServiceResolver()
    {
        var logger = LogManager.GetCurrentClassLogger();
        logger.Info("Initializing NLogServiceResolver");
 
        var nlogLogger = new NLogLogger(logger);
        _logger = nlogLogger;
        _loggingLogger = nlogLogger;
 
        _hashProvider = new CryptoHashProvider("SHA512");
        _packageRepository = new ServerPackageRepository(
            PackageUtility.PackagePhysicalPath,
            _hashProvider,
            _loggingLogger)
        {
            // The base class has a separate logger that you have to set.
            Logger = _logger
        };
            
        _packageAuthenticationService = new PackageAuthenticationService();
        _packageService = new PackageService(_packageRepository, _packageAuthenticationService);
    }
 
    public object Resolve(Type type)
    {
        if (type == typeof(IHashProvider))
            return _hashProvider;
 
        if (type == typeof(IServerPackageRepository))
            return _packageRepository;
 
        if (type == typeof(IPackageAuthenticationService))
            return _packageAuthenticationService;
 
        if (type == typeof(IPackageService))
            return _packageService;
 
        if (type == typeof(ILogger))
            return _logger;
 
        if (type == typeof(Logging.ILogger))
            return _loggingLogger;
 
        return null;
    }
}

Enjoy,
Tom

No comments:

Post a Comment

Real Time Web Analytics