问题描述:记得以前使用Log4net时,可以在config文件中配置多个Appender,
每一个类对应一个Appender,即每个类产生的日志会写入到不同的日志文件中,
可避免日志堆累在一起。
目前环境有所变化,使用的是ABP框架,日志使用的类为Microsoft.Extensions.Logging.ILogger
首先我定义了两个Appender, 其目的就是不同的类日志写入到不同的Appender所定义的日志文件中去
<?xml version="1.0" encoding="utf-8"?>
<log4net>
<appender name="DataSyncServices" type="log4net.Appender.RollingFileAppender">
<file value="../../../App_Data/Logs/日志文件1.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<appender name="DataSyncTwoServices" type="log4net.Appender.RollingFileAppender">
<file value="../../../App_Data/Logs/日志文件2.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>-->
<root>
<appender-ref ref="DataSyncServices" />
<appender-ref ref="DataSyncTwoServices" />
<level value="DEBUG" />
</root>
<logger name="NHibernate">
<level value="WARN" />
</logger>
</log4net>
代码内容如下
private readonly ILogger<DataSyncServices> _logger;
public class DataSyncServices : AMSApiServiceBase, IDataSyncServices
{
public DataSyncServices(ILogger<DataSyncServices> logger,。。。。)
{
_logger = logger; //这里是大家都知道的,应用了依赖注入去实例化日志类
}
private void Method()
{
....
/*
这里输出至日志文件
奇怪的是,日志内容会同时写入到日志文件1.txt 和 日志文件2.txt两个文件中,与目的可谓是南辕北辙
*/
_logger.LogInformation("写入DataSyncServices类产生的日志");
}
}
private readonly ILogger<DataSyncTwoServices> _logger;
public class DataSyncTwoServices : AMSApiServiceBase, IDataSyncTwoServices
{
public DataSyncTwoServices(ILogger<DataSyncTwoServices> logger,。。。。)
{
_logger = logger; //这里是大家都知道的,应用了依赖注入去实例化日志类
}
private void Method()
{
....
/*
这里输出至日志文件
奇怪的是,日志内容会同时写入到日志文件1.txt 和 日志文件2.txt两个文件中,与目的可谓是南辕北辙
*/
_logger.LogInformation("写入DataSyncTwoServices类产生的日志");
}
}
提出问题:我的目的是将不同的类产生的日志输入到不同的文件中去,但是按照上面的做法,
结果相反,一个类的日志内容似乎会往两个日志文件中写入。
对于.net core6的Microsoft.Extensions.Logging.ILogger使用,怎样才能实现不同的类产生的日志
输入到不同的文件中去? 有什么好的建议或代码片断可供参考吗?
期待得到各位的指点,感谢!
当使用 Microsoft.Extensions.Logging 日志框架时,可以使用 Microsoft.Extensions.Logging.File 提供程序来将不同类产生的日志输入到不同的文件中。下面是一个完整的示例代码,展示了如何配置和使用该提供程序:
首先,确保在项目中引用以下 NuGet 包:
接下来,创建一个名为 "LoggingConfig.cs" 的配置类,用于配置日志提供程序和日志过滤器:
using Microsoft.Extensions.Logging;
public static class LoggingConfig
{
public static void ConfigureLoggerFactory(LoggerFactory loggerFactory)
{
// 添加文件日志提供程序
loggerFactory.AddFile("MyClass.log");
loggerFactory.AddFile("AnotherClass.log");
// 添加过滤器,将不同类的日志写入不同文件
loggerFactory.AddFilter("MyNamespace.MyClass", LogLevel.Information);
loggerFactory.AddFilter("MyNamespace.AnotherClass", LogLevel.Information);
}
}
然后,在程序的入口点(例如 Program.cs 文件中的 Main 方法)中进行日志配置:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
public static class Program
{
public static void Main()
{
// 创建服务集合
var services = new ServiceCollection();
// 添加日志
services.AddLogging(builder =>
{
builder.ClearProviders(); // 清除默认的日志提供程序
// 配置日志提供程序
builder.Services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
// 配置 LoggerFactory
builder.Services.AddSingleton<ILoggerFactory>(loggerFactory =>
{
var factory = new LoggerFactory();
// 调用自定义的配置方法
LoggingConfig.ConfigureLoggerFactory(factory);
return factory;
});
});
// 构建服务提供程序
var serviceProvider = services.BuildServiceProvider();
// 获取 ILoggerFactory 实例
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
// 创建 MyClass 实例并使用日志记录
var myClass = new MyClass(loggerFactory.CreateLogger<MyClass>());
myClass.DoSomething();
// 创建 AnotherClass 实例并使用日志记录
var anotherClass = new AnotherClass(loggerFactory.CreateLogger<AnotherClass>());
anotherClass.DoSomethingElse();
}
}
在上述示例中,我们创建了一个静态类 LoggingConfig
用于配置日志提供程序和过滤器。在 ConfigureLoggerFactory
方法中,我们添加了 FileLoggerProvider
提供程序并配置了两个日志文件("MyClass.log" 和 "AnotherClass.log")。然后,我们通过添加过滤器,将 MyClass
类的日志写入 "MyClass.log" 文件中,将 AnotherClass
类的日志写入 "AnotherClass.log" 文件中。
在程序的入口点,我们使用 ServiceCollection
和 ServiceProvider
配置和构建服务提供程序。然后,我们获取 ILoggerFactory
实例并创建 MyClass
和 AnotherClass
的实例,为它们创建对应的日志记录器。
请注意,根据实际的命名空间和类名,你需要相应地修改代码中的命名空间和类名,以及文件名和路径。
首先你需要在log4net.config中定义多个appender,并给每个appender指定一个name和一个file。然后,在log4net.config中定义多个logger,并给每个logger指定一个name和一个appender-ref。name属性应该与你的类名或命名空间相对应,appender-ref属性应该与你想要输出到的文件的appender相对应就可以了
看下边我举的例子:
还可以参考这个: https://stackoverflow.com/questions/56674910/log-to-multiple-logfiles-with-microsoft-extensions-logging-abstractions
比如你有两个类DataSyncServices和DataSyncTwoServices,分别输出到日志文件1.txt和日志文件2.txt,这样配置log4net.config看是否可行:
<log4net>
<appender name="DataSyncServices" type="log4net.Appender.RollingFileAppender">
<file value="../../../App_Data/Logs/日志文件1.txt" />
<!-- 省略其他配置 -->
</appender>
<appender name="DataSyncTwoServices" type="log4net.Appender.RollingFileAppender">
<file value="../../../App_Data/Logs/日志文件2.txt" />
<!-- 省略其他配置 -->
</appender>
<root>
<level value="DEBUG" />
</root>
<logger name="DataSyncServices">
<level value="DEBUG" />
<appender-ref ref="DataSyncServices" />
</logger>
<logger name="DataSyncTwoServices">
<level value="DEBUG" />
<appender-ref ref="DataSyncTwoServices" />
</logger>
</log4net>
采用chatgpt:
在Microsoft.Extensions.Logging中,每个ILogger实例是对应一个类的,而不是对应一个日志文件。因此,直接使用ILogger接口无法实现将不同的类产生的日志输入到不同的文件中。
要实现类似的功能,你可以通过扩展ILoggerProvider接口来自定义一个ILoggerProvider,并在其中创建不同的ILogger实例,每个实例关联一个特定的日志文件。
以下是一个示例代码片段,展示如何创建一个自定义的ILoggerProvider,实现按类名写入不同的日志文件:
using Microsoft.Extensions.Logging;
using System.IO;
public class ClassLoggerProvider<T> : ILoggerProvider
{
private readonly string _logFilePath;
public ClassLoggerProvider(string logFilePath)
{
_logFilePath = logFilePath;
}
public ILogger CreateLogger(string categoryName)
{
if (categoryName == typeof(T).FullName)
{
var logPath = Path.Combine(_logFilePath, $"{typeof(T).Name}.txt");
// Create a logger that writes to the specified log file
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddFile(logPath);
});
return loggerFactory.CreateLogger(categoryName);
}
// Return a null logger for other categories
return NullLogger.Instance;
}
public void Dispose()
{
// Clean up resources if needed
}
}
上述代码中,我们创建了一个ClassLoggerProvider类,其中T是具体的类。它实现了ILoggerProvider接口,用于创建ILogger实例。
在CreateLogger方法中,我们检查传入的categoryName是否与typeof(T).FullName相等,即是否为目标类的全名。如果是,我们创建一个基于文件的ILogger实例,将日志写入指定的日志文件。
对于其他类,我们返回一个NullLogger实例,该实例不执行任何日志操作,以避免不必要的日志记录。
要使用这个自定义的ILoggerProvider,你可以在程序启动时进行注册:
using Microsoft.Extensions.DependencyInjection;
// 注册自定义ILoggerProvider
services.AddSingleton(typeof(ILoggerProvider), new ClassLoggerProvider<DataSyncServices>(logFilePath1));
services.AddSingleton(typeof(ILoggerProvider), new ClassLoggerProvider<DataSyncTwoServices>(logFilePath2));
在上述代码中,logFilePath1和logFilePath2分别是目标类DataSyncServices和DataSyncTwoServices对应的日志文件路径。
通过这种方式,你可以实现将不同的类产生的日志输入到不同的文件中。每个类都有自己的ILogger实例,与相应的日志文件关联起来。
引用chatgpr回答: 在使用.NET Core 6
的Microsoft.Extensions.Logging.ILogger
时,您可以实现将不同的类产生的日志输入到不同的文件中。以下是一种可能的解决方法:
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"NHibernate": "Warning",
"DataSyncServices": "Information",
"DataSyncTwoServices": "Information"
},
"Appenders": [
{
"Name": "DataSyncServices",
"Type": "log4net.Appender.RollingFileAppender",
"FileName": "Logs/DataSyncServices.log",
"...
},
{
"Name": "DataSyncTwoServices",
"Type": "log4net.Appender.RollingFileAppender",
"FileName": "Logs/DataSyncTwoServices.log",
"...
}
]
}
}
在这个示例中,我们为DataSyncServices
和DataSyncTwoServices
这两个类设置了Information
级别的日志,并为它们定义了自己的日志文件。
public void ConfigureServices(IServiceCollection services)
{
// 注册日志
services.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders(); // 清除所有默认的日志提供程序(例如Console和Debug)
loggingBuilder.SetMinimumLevel(LogLevel.Trace); // 设置最低日志级别
// 添加自定义的log4net提供程序
loggingBuilder.AddLog4Net();
});
}
在AddLogging
方法中,我们清除了默认的日志提供程序并配置了最低的日志级别。然后,我们添加了自定义的log4net日志提供程序。
public class DataSyncServices
{
private readonly ILogger<DataSyncServices> _logger;
public DataSyncServices(ILogger<DataSyncServices> logger)
{
_logger = logger;
}
// ...
}
public class DataSyncTwoServices
{
private readonly ILogger<DataSyncTwoServices> _logger;
public DataSyncTwoServices(ILogger<DataSyncTwoServices> logger)
{
_logger = logger;
}
// ...
}
_logger.LogInformation
来记录Information
级别的日志。确保每个类使用了适当的日志级别。看下这几篇文章:
https://learn.microsoft.com/zh-cn/dotnet/core/extensions/custom-logging-provider
https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.extensions.logging.ilogger?view=dotnet-plat-ext-7.0
https://blog.csdn.net/lindexi_gd/article/details/107204416
在使用Microsoft.Extensions.Logging框架时,可以通过配置不同的Logger Provider来实现不同类的日志输出到不同的文件中。下面是一种可能的解决方案:
ILoggerProvider
接口并重写CreateLogger
方法,根据不同的类名创建不同的Logger实例。public class CustomLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
// 根据类名创建不同的Logger实例
if (categoryName == typeof(DataSyncServices).FullName)
{
return new Logger<DataSyncServices>();
}
else if (categoryName == typeof(DataSyncTwoServices).FullName)
{
return new Logger<DataSyncTwoServices>();
}
// 如果没有匹配的类名,返回默认的Logger实例
return new Logger(categoryName);
}
public void Dispose()
{
// 清理资源
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, loggingBuilder) =>
{
loggingBuilder.ClearProviders(); // 清除默认的Logger Provider
loggingBuilder.AddProvider(new CustomLoggerProvider()); // 添加自定义的Logger Provider
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
ILogger
接口,并重写相关的日志输出方法。public class Logger<T> : ILogger<T>
{
private readonly string _categoryName;
public Logger()
{
_categoryName = typeof(T).FullName;
}
public IDisposable BeginScope<TState>(TState state)
{
return NullScope.Instance; // 可以根据需要返回不同的Scope
}
public bool IsEnabled(LogLevel logLevel)
{
return true; // 可以根据需要进行日志级别的判断
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
// 在这里实现日志的输出到对应的文件,可以使用log4net等日志框架
// 可以根据_logCategory判断是哪个类的日志,然后输出到对应的文件
}
}
通过上述步骤,你可以实现不同类的日志输出到不同的文件中。在CustomLoggerProvider
中根据类名创建对应的Logger实例,在Logger
类中根据类名来决定将日志输出到哪个文件。你可以根据需要使用合适的日志框架(如log4net)来实现日志的输出到文件中。
希望这个解决方案对你有帮助!
将不同级别的logging 日志信息写入不同文件
编写python测试脚本
#!/usr/bin/env python
import logging
import logging.config
logging.config.fileConfig("logger.conf")
def logerror():
logger = logging.getLogger("errorLogger")
logger.error("There is a error in this file",exc_info=1)
def logdebug():
logger = logging.getLogger("debugLogger")
logger.debug("There is a debug in this file")
logdebug()
def testfun():
print "test"
try:
testfun(1)
except TypeError,e:
logerror()
编写logging配置文档,将一般调试日志文件写入myapp.debug文件,将脚本运行过程中出错信息写入myapp.err文件。
[loggers]
keys=root,errorLogger,debugLogger
[logger_root]
level=DEBUG
handlers=errorHand,debugHand
[logger_errorLogger]
handlers=errorHand
qualname=errorLogger
propagate=0
[logger_debugLogger]
handlers=debugHand
qualname=debugLogger
propagate=0
###############################################
[handlers]
keys=errorHand,debugHand
[handler_errorHand]
class=handlers.RotatingFileHandler
level=ERROR
formatter=form01
args=('myapp.err', 'a', 10*1024*1024, 1)
[handler_debugHand]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=form01
args=('myapp.debug', 'a', 10*1024*1024, 1)
###############################################
[formatters]
keys=form01
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%Y-%e-%d %H:%M:%S
执行python测试脚本,查看日志文件信息
[root@localhost tmp]# python mytest.py
[root@localhost tmp]# cat myapp.debug
2016-21-21 07:31:29 mytest.py[line:13] DEBUG There is a debug in this file
[root@localhost tmp]# cat myapp.err
2016-21-21 07:31:29 mytest.py[line:9] ERROR There is a error in this file
Traceback (most recent call last):
File "mytest.py", line 21, in <module>
testfun(1)
TypeError: testfun() takes no arguments (1 given)
在每个需要记录日志的类中创建一个私有字段,该字段是 Microsoft.Extensions.Logging.ILogger 的实例。例如:
private ILogger<MyClass> logger;
在类的构造函数中获取 ILogger 实例,并将其分配给 logger 字段。例如:
public MyClass()
{
logger = LogManager.GetLogger<MyClass>();
}
在类的方法中使用 logger 字段记录日志。例如:
public void MyMethod()
{
logger.LogInformation("This is an information message.");
}
在配置文件中配置不同级别的日志方案
要实现不同类产生的日志输入到不同的文件,可以使用Microsoft.Extensions.Logging
的日志配置功能,在appsettings.json文件中配置不同的日志输出目标和规则,定义每个文件的日志级别和文件路径,在Startup.cs文件的ConfigureServices方法中,添加日志服务并配置使用文件日志,在每个需要记录日志的类中,通过构造函数注入ILogger实例,在每个类的方法中,使用ILogger实例调用合适的日志记录方法,日志会根据配置输出到不同的文件中
在构造函数中注入ILogger