问题描述:
项目中使用log4net进行日志记录,使用配置文件对log4net进行配置,都进行得很顺利。但出于security方面的考虑,要求某些敏感字段(如password)不能出现在配置文件中。因此需要在程序中设置这些字段,先从保存敏感信息的地方(比如AKV)读取敏感字段,再写到log4net配置中。
在程序中改写log4net配置:
比如改写配置文件中SmtpAppender中的Password属性:
Hierarchy hier = log4net.LogManager.GetRepository() as Hierarchy;
var smtpAppender =
(SmtpAppender)(hier.Root.Appenders.OfType<SmtpAppender>().FirstOrDefault());
if (smtpAppender != null)
{
smtpAppender.Password = parameters.SecureCodeEmailPassword;
smtpAppender.ActivateOptions();
}
在改写配置后调用logger.Error(message)可以如期工作,似乎一切都很顺利(^_^)然而这时诡异的事情发生了–在改写配置后的某个遥远的地方(在程序入口改写配置,后经过一段业务逻辑处理),日志功能不work了,一脸懵逼o(╯□╰)o
定位问题 – 启用log4net内部调试
这时候自然需要更多的详细信息帮助定位问题和解决问题,在设置log4net debug属性后(具体可参考开启log4net内部调试),可以定位到问题是程序中改写的配置没有生效!!!
可开始的调用明明显示改写的配置已经生效了,又一脸懵o(╯□╰)o
只好仔细的看日志信息了ε=(´ο`*)))sign
log4net: Creating repository for assembly [AzureKeyVaultAdapter, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]
log4net: Assembly [AzureKeyVaultAdapter, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35] Loaded From [D:\\Bothell\\target\\dev\\metrics\\CheckinMonitoringJob\\debug\\amd64\\AzureKeyVaultAdapter.dll]
log4net: Assembly [AzureKeyVaultAdapter, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35] does not have a RepositoryAttribute specified.
log4net: Assembly [AzureKeyVaultAdapter, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35] using repository [log4net-default-repository] and repository type [log4net.Repository.Hierarchy.Hierarchy]
log4net: Creating repository [log4net-default-repository] using type [log4net.Repository.Hierarchy.Hierarchy]
log4net: Creating repository for assembly [Internal.OSS.GenericLogger, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]
log4net: Assembly [Internal.OSS.GenericLogger, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35] Loaded From [D:\\Bothell\\target\\dev\\metrics\\CheckinMonitoringJob\\debug\\amd64\\Internal.OSS.GenericLogger.dll]
log4net: Assembly [Internal.OSS.GenericLogger, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35] does not have a RepositoryAttribute specified.
log4net: Assembly [Internal.OSS.GenericLogger, Version=16.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35] using repository [log4net-default-repository] and repository type [log4net.Repository.Hierarchy.Hierarchy]
log4net: repository [log4net-default-repository] already exists, using repository type [log4net.Repository.Hierarchy.Hierarchy]
log4net: configuring repository [log4net-default-repository] using file [Xxx.exe.Config] watching for file updates
log4net: configuring repository [log4net-default-repository] using file [Xxx.exe.Config]
log4net: configuring repository [log4net-default-repository] using stream
log4net: loading configuration
log4net: Configuring Repository [log4net-default-repository]
log4net: Configuration update mode [Merge].
log4net: Logger [root] Level string is [ALL].
log4net: Logger [root] level set to [name=\"ALL\",value=-2147483648].
log4net: Loading Appender [LogFileAppender] type: [log4net.Appender.FileAppender]
log4net: Setting Property [File] to String value [CheckinMonitoring.log]
从日志中不难发现,每次加载一个Assembly后,都会重新配置log4net默认的repository [log4net-default-repository] 。这是因为每个Assembly都没有指定RepositoryAttribute,log4net会为其选用默认的repository。正是因为如此,所以我们一般都不需要特别关注log4net repository相关的配置,默认的可以适用绝大部分场景。
问题也就找到了:在改写配置之后,因为又新加载了新的Assembly,也是采用log4net默认的repository,并且重新load配置文件配置log4net默认的repository。重新配置覆盖了之前改写的配置。
解决问题 – 为Assembly指定Repository
问题找到了,解决问题大概有下面几种方法:
- 在加载完所有Assembly后再重新改写log4net的配置;
- 为我们的Assembly指定repository,而不是采用默认的repository。这样即使有新的Assembly加载进来,也只是重新配置默认的repository,不会覆盖改写的配置。
- …
我们采用指定repository的办法,具体操作:
- 在AssemblyInfo.cs文件中添加:
[assembly: log4net.Config.Repository(name: \"myRepository\")]
[assembly: log4net.Config. Configurator()]
- 改写myRepository的配置:
Hierarchy hier = log4net.LogManager.GetRepository(\"myRepository\") as Hierarchy;
var smtpAppender =
(SmtpAppender)(hier.Root.Appenders.OfType<SmtpAppender>().FirstOrDefault());
if (smtpAppender != null)
{
smtpAppender.Password = parameters.SecureCodeEmailPassword;
smtpAppender.ActivateOptions();
}
LogManager.GetRepository(repositoryName)会返回指定的repository,当没有指定repositoryName时,会返回默认的repository,即log4net-default-repository。
完美؏؏☝ᖗ乛◡乛ᖘ☝؏؏
继续阅读与本文标签相同的文章
泰瑞&神钢战略合作持续升级
-
加速5G商业成功,华为5G设备全球发货超40万
2026-05-18栏目: 教程
-
如何看清新媒体行业过去和未来的红利?
2026-05-18栏目: 教程
-
阿里云独门绝技之无代理混合云数据库实时增量备份
2026-05-18栏目: 教程
-
外国网友惊叹中国5G公交:中国早已比我们想象的更好
2026-05-18栏目: 教程
-
Aliyun Serverless VSCode Extension v1.8.0 发布
2026-05-18栏目: 教程
