0

我正在使用 slf4net.log4net nuget 包来处理项目的日志记录。因为在运行时日志级别必须可以更改,所以我在代码中进行了配置。问题是此代码在 slf4net.log4net 版本 0.1.32.1 中运行良好,但是当我将其升级到版本 1.0.0 时,会创建日志文件,但日志文件中不存在日志。我创建了一个虚拟项目来显示这个问题。我看不到如何在此处添加 zip 文件,因此我将在此处发布代码。它是 net framework 4.7.2 中的控制台应用程序;

class Program
{
    private static string GetLoggingPath()
    {
        var path = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData,
                Environment.SpecialFolderOption.DoNotVerify), "LoggingTesting");
        Directory.CreateDirectory(path);
        return path;
    }
    static void Main(string[] args)
    {
        var layout = new PatternLayout
        {
            ConversionPattern = "%d{ABSOLUTE}: %message %newline"
        };
        layout.ActivateOptions();

        var fileAppender = new RollingFileAppender();
        fileAppender.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Date;
        fileAppender.Layout = layout;
        var path = GetLoggingPath();
        fileAppender.File = path + System.IO.Path.DirectorySeparatorChar + "LISlogging_.txt";
        fileAppender.AppendToFile = true;
        fileAppender.PreserveLogFileNameExtension = true;
        fileAppender.StaticLogFileName = false;
        fileAppender.DatePattern = "yyyy-MM-dd";
        fileAppender.MaxSizeRollBackups = 10;
        fileAppender.ActivateOptions();
        ILoggerRepository repository = log4net.LogManager.GetRepository(Assembly.GetCallingAssembly());
        BasicConfigurator.Configure(repository, fileAppender);
        var root = (repository as Hierarchy)?.Root;
        if (root == null) return;
        root.Level = log4net.Core.Level.All;
        //  Create log4net ILoggerFactory and set the resolver
        var factory = new slf4net.log4net.Log4netLoggerFactory();
        var resolver = new SimpleFactoryResolver(factory);
        slf4net.LoggerFactory.SetFactoryResolver(resolver);
        // trigger logging
        var log = slf4net.LoggerFactory.GetLogger(typeof(Program));
        log.Info("log this line");
    }
}

public class SimpleFactoryResolver : IFactoryResolver
{
    private readonly slf4net.ILoggerFactory _factory;

    public SimpleFactoryResolver(slf4net.ILoggerFactory factory)
    {
        _factory = factory;
    }
    public slf4net.ILoggerFactory GetFactory()
    {
        return _factory;
    }
}

这个虚拟项目是在 .net 框架中创建的,但我需要在 .net 核心项目中使用它。这就是为什么我需要版本 1.0.0 。我还在 slf4net 的 github 页面上发布了这个问题(因为它看起来像一个错误):https ://github.com/ef-labs/slf4net/issues/6

关于堆栈溢出,我的主要问题是是否有解决方法,所以这可以与 slf4net.log4net 版本 1.0.0 一起使用

4

1 回答 1

0

我找到了解决方法。也许不是最干净的解决方案,但它有效。如果有人知道更清洁的解决方案,请在此处添加。

查看 slf4net.log4net 代码时,我发现当它尝试配置 log4net 时,它使用 xml 文件或配置文件,如果你想在运行时设置日志级别,这是一场噩梦。您可以将 customconfigurator 作为 Log4netLoggerFactory 的参数传递。此 customconfigurator 需要实现 IXmlConfigurator。我制作的 CustomConfigurator 接受 IAppender 和 loglevel (log4net.Core.Level)。在 Configure(ICollection(ILoggerRepository repository) 方法的实现中。我设置了根日志级别并使用 BasicConfigurator 进行了配置。CustomConfigurator 如下所示:

public class CustomConfigurator: IXmlConfigurator
{
    private readonly IAppender _appender;
    private readonly log4net.Core.Level _logLevel;

    public CustomConfigurator(IAppender appender, log4net.Core.Level logLevel)
    {
        _appender = appender;
        _logLevel = logLevel;
    }

    public ICollection Configure(ILoggerRepository repository)
    {
        var root = (repository as Hierarchy)?.Root;
        if (root != null)
        {
            root.Level = _logLevel;
        }
        return BasicConfigurator.Configure(repository, _appender);
    }

    public ICollection Configure(ILoggerRepository repository, XmlElement element)
    {
        return XmlConfigurator.Configure(repository, element);
    }

    public ICollection Configure(ILoggerRepository repository, FileInfo configFile)
    {
        return XmlConfigurator.Configure(repository, configFile);
    }

    public ICollection ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile)
    {
        return XmlConfigurator.ConfigureAndWatch(repository, configFile);
    }
}

现在您可以在问题中显示的代码中创建一个附加程序(直到 fileappender.ActivateOptions)然后在构造 log4netLoggerFactory 时传递一个 CustomConfigurator 实例,该实例将 fileAppender 和 loglevel 作为参数。

var factory = new slf4net.log4net.Log4netLoggerFactory(new CustomConfigurator(fileAppender, Level.All));
var resolver = new SimpleFactoryResolver(factory);
slf4net.LoggerFactory.SetFactoryResolver(resolver);

这应该有效。

于 2020-09-04T11:58:00.320 回答