.net 如何从头开始以编程方式配置log4net(无配置)
这是个坏主意,我知道,但是。。。 我想从头开始以编程方式配置log4net,而不需要配置文件。我正在为我和我的团队开发一个简单的日志应用程序,用于我们负责的一些相对较小的部门应用程序。我希望他们都登录到同一个数据库。日志应用程序只是log4net的一个包装器,它预先配置了AdoNetAppender 所有应用程序都是ClickOnce部署的,这给部署配置文件带来了一个小问题。如果配置文件是核心项目的一部分,我可以将其属性设置为与程序集一起部署。但它是链接应用程序的一部分,因此我没有选择将其与主应用程序一起部署。(如果不是这样,请有人告诉我) 可能是因为这是一个坏主意,似乎没有太多的示例代码可用于从头编程配置log4net。这是我到目前为止所拥有的.net 如何从头开始以编程方式配置log4net(无配置),.net,logging,log4net,.net,Logging,Log4net,这是个坏主意,我知道,但是。。。 我想从头开始以编程方式配置log4net,而不需要配置文件。我正在为我和我的团队开发一个简单的日志应用程序,用于我们负责的一些相对较小的部门应用程序。我希望他们都登录到同一个数据库。日志应用程序只是log4net的一个包装器,它预先配置了AdoNetAppender 所有应用程序都是ClickOnce部署的,这给部署配置文件带来了一个小问题。如果配置文件是核心项目的一部分,我可以将其属性设置为与程序集一起部署。但它是链接应用程序的一部分,因此我没有选择将其与主应
Dim apndr As New AdoNetAppender()
apndr.CommandText = "INSERT INTO LOG_ENTRY (LOG_DTM, LOG_LEVEL, LOGGER, MESSAGE, PROGRAM, USER_ID, MACHINE, EXCEPTION) VALUES (@log_date, @log_level, @logger, @message, @program, @user, @machine, @exception)"
apndr.ConnectionString = connectionString
apndr.ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
apndr.CommandType = CommandType.Text
Dim logDate As New AdoNetAppenderParameter()
logDate.ParameterName = "@log_date"
logDate.DbType = DbType.DateTime
logDate.Layout = New RawTimeStampLayout()
apndr.AddParameter(logDate)
Dim logLevel As New AdoNetAppenderParameter()
logLevel.ParameterName = "@log_level"
'And so forth...
在为apndr
配置了所有参数之后,我首先尝试了以下方法
Dim hier As Hierarchy = DirectCast(LogManager.GetRepository(), Hierarchy)
hier.Root.AddAppender(apndr)
它不起作用。然后,在黑暗中,我尝试了这个
BasicConfigurator.Configure(apndr)
那也没用。关于如何在没有配置文件的情况下从头开始以编程方式配置log4net,有人有什么好的参考资料吗?我在过去做过的一种方法是将配置文件作为嵌入式资源包含进来,然后直接使用 这样,我就可以使用我熟悉的配置语法,不必担心部署文件。如前所述,使用资源是一个很好的解决方案 这有点限制,因为嵌入的资源内容将在编译时固定。我有一个日志组件,它使用定义为appSettings的变量(例如RollingFileAppender的文件名、默认日志记录级别,如果您想使用AdoNetAppender,可能是连接字符串名称),生成一个带有基本Log4Net配置的XmlDocument。然后我调用
log4net.Config.XmlConfigurator.Configure
来使用生成的XmlDocument的根元素配置log4net
然后,管理员可以通过修改一些应用设置(通常是级别、文件名等)自定义“标准”配置,或者可以指定一个外部配置文件以获得更多控制。奇怪的是,
BasicConfigurator.Configure(apndr)
不起作用。在我的情况下,它做了它的工作。。。但是,不管怎样,答案来了——你应该写hier.Configured=true代码>(c#代码)在完成所有设置之后。下面是一个示例类,它完全用代码创建log4net配置。我应该提到,通过静态方法创建记录器通常被认为是不好的,但在我的上下文中,这正是我想要的。无论如何,您可以分割代码以满足您的需要
using log4net;
using log4net.Repository.Hierarchy;
using log4net.Core;
using log4net.Appender;
using log4net.Layout;
namespace dnservices.logging
{
public class Logger
{
private PatternLayout _layout = new PatternLayout();
private const string LOG_PATTERN = "%d [%t] %-5p %m%n";
public string DefaultPattern
{
get { return LOG_PATTERN; }
}
public Logger()
{
_layout.ConversionPattern = DefaultPattern;
_layout.ActivateOptions();
}
public PatternLayout DefaultLayout
{
get { return _layout; }
}
public void AddAppender(IAppender appender)
{
Hierarchy hierarchy =
(Hierarchy)LogManager.GetRepository();
hierarchy.Root.AddAppender(appender);
}
static Logger()
{
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
TraceAppender tracer = new TraceAppender();
PatternLayout patternLayout = new PatternLayout();
patternLayout.ConversionPattern = LOG_PATTERN;
patternLayout.ActivateOptions();
tracer.Layout = patternLayout;
tracer.ActivateOptions();
hierarchy.Root.AddAppender(tracer);
RollingFileAppender roller = new RollingFileAppender();
roller.Layout = patternLayout;
roller.AppendToFile = true;
roller.RollingStyle = RollingFileAppender.RollingMode.Size;
roller.MaxSizeRollBackups = 4;
roller.MaximumFileSize = "100KB";
roller.StaticLogFileName = true;
roller.File = "dnservices.txt";
roller.ActivateOptions();
hierarchy.Root.AddAppender(roller);
hierarchy.Root.Level = Level.All;
hierarchy.Configured = true;
}
public static ILog Create()
{
return LogManager.GetLogger("dnservices");
}
}
}我无法在问题的代码片段中判断“'等等…”是否包括Todd Stout的答案中指出的非常重要的apndr.ActivateOptions()。如果没有ActivateOptions(),Appender将处于非活动状态,并且不会执行任何可以解释其失败原因的操作。//我已将三个配置文件作为嵌入式资源嵌入,并按如下方式访问它们:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Resources;
using System.IO;
namespace Loader
{
class Program
{
private static log4net.ILog CustomerLog = log4net.LogManager.GetLogger("CustomerLogging");
private static log4net.ILog OrderLog = log4net.LogManager.GetLogger("OrderLogging");
private static log4net.ILog DetailsLog = log4net.LogManager.GetLogger("OrderDetailLogging");
static void Main(string[] args)
{
// array of embedded log4net config files
string[] configs = { "Customer.config", "Order.config", "Detail.config"};
foreach (var config in configs)
{
// build path to assembly config
StringBuilder sb = new StringBuilder();
sb.Append(System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
sb.Append(".");
sb.Append(config);
// convert to a stream
Stream configStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(sb.ToString());
// configure logger with ocnfig stream
log4net.Config.XmlConfigurator.Configure(configStream);
// test logging
CustomerLog.Info("Begin logging with: " + config);
OrderLog.Info("Begin logging with: " + config);
DetailsLog.Info("Begin logging with: " + config);
for (int iX = 0; iX < 10; iX++)
{
CustomerLog.Info("iX=" + iX);
OrderLog.Info("iX=" + iX);
DetailsLog.Info("iX=" + iX);
}
CustomerLog.Info("Ending logging with: " + config);
OrderLog.Info("Ending logging with: " + config);
DetailsLog.Info("Ending logging with: " + config);
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
利用系统资源;
使用System.IO;
名称空间加载器
{
班级计划
{
私有静态log4net.ILog CustomerLog=log4net.LogManager.GetLogger(“CustomerLogging”);
私有静态log4net.ILog OrderLog=log4net.LogManager.GetLogger(“OrderLogging”);
私有静态log4net.ILog DetailsLog=log4net.LogManager.GetLogger(“OrderDetailLogging”);
静态void Main(字符串[]参数)
{
//嵌入式log4net配置文件数组
字符串[]configs={“Customer.config”、“Order.config”、“Detail.config”};
foreach(配置中的变量配置)
{
//程序集配置的生成路径
StringBuilder sb=新的StringBuilder();
sb.Append(System.Reflection.Assembly.GetExecutionGassembly().GetName().Name);
某人加上(“.”);
某人追加(配置);
//转换成流
Stream configStream=System.Reflection.Assembly.GetExecutionGassembly().GetManifestResourceStream(sb.ToString());
//使用ocnfig流配置记录器
log4net.Config.XmlConfigurator.Configure(configStream);
//测试记录
CustomerLog.Info(“以“+config”开始日志记录);
Info(“以“+config”开始日志记录);
DetailsLog.Info(“以“+config”开始日志记录);
对于(int-iX=0;iX<10;iX++)
{
CustomerLog.Info(“iX=”+iX);
OrderLog.Info(“iX=“+iX”);
DetailsLog.Info(“iX=”+iX);
}
CustomerLog.Info(“以“+config”结束日志记录);
Info(“以“+config”结束日志记录);
DetailsLog.Info(“以“+config”结束日志记录);
}
}
}
}
我最后用了这个:
4小时后,摆弄配置,越来越沮丧
希望它能帮助别人。有这样一个功能,用于以编程方式设置连接字符串:
// Get the Hierarchy object that organizes the loggers
log4net.Repository.Hierarchy.Hierarchy hier =
log4net.LogManager.GetLoggerRepository() as log4net.Repository.Hierarchy.Hierarchy;
if (hier != null)
{
//get ADONetAppender
log4net.Appender.ADONetAppender adoAppender =
(log4net.Appender.ADONetAppender)hier.GetLogger("MyProject",
hier.LoggerFactory).GetAppender("ADONetAppender");
if (adoAppender != null)
{
adoAppender.ConnectionString =
System.Configuration.ConfigurationSettings.AppSettings["MyConnectionString"];
adoAppender.ActivateOptions(); //refresh settings of appender
}
}
更简洁的解决方案:
var layout = new PatternLayout("%-4timestamp [%thread] %-5level %logger %ndc - %message%newline");
var appender = new RollingFileAppender {
File = "my.log",
Layout = layout
};
layout.ActivateOptions();
appender.ActivateOptions();
BasicConfigurator.Configure(appender);
不要忘记调用方法:
设置配置属性后,必须在此对象上调用ActivateOptions方法。在调用ActivateOptions之前,此对象处于未定义状态,不得使用
晚会有点晚了。但这里有一个对我有效的最小配置
样本类
public class Bar
{
private readonly ILog log = LogManager.GetLogger(typeof(Bar));
public void DoBar() { log.Info("Logged"); }
}
最小log4net跟踪配置(NUnit测试内部)
打印到跟踪侦听器
Namespace+Bar: Logged
下面是一个简单的示例,演示了如何在没有任何App.config
文件的情况下(甚至对于Common.Logging
),完全在代码中创建和使用AdoneAdapter
)。继续,删除它
这还有一个额外的好处,那就是可以重新调整
Namespace+Bar: Logged
CREATE TABLE [Log](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[Thread] [varchar](255) NOT NULL,
[Level] [varchar](20) NOT NULL,
[Source] [varchar](255) NOT NULL,
[Message] [varchar](max) NOT NULL,
[Exception] [varchar](max) NOT NULL
)
Imports log4net
Imports log4net.Core
Imports log4net.Layout
Imports log4net.Config
Imports log4net.Appender
Module Main
Sub Main()
Dim oLogger As ILog
Dim sInput As String
Dim iOops As Integer
BasicConfigurator.Configure(New DbAppender)
oLogger = LogManager.GetLogger(GetType(Main))
Console.Write("Command: ")
Do
Try
sInput = Console.ReadLine.Trim
Select Case sInput.ToUpper
Case "QUIT" : Exit Do
Case "OOPS" : iOops = String.Empty
Case Else : oLogger.Info(sInput)
End Select
Catch ex As Exception
oLogger.Error(ex.Message, ex)
End Try
Console.Clear()
Console.Write("Command: ")
Loop
End Sub
End Module
Imports log4net
Imports log4net.Core
Imports log4net.Layout
Imports log4net.Appender
Imports log4net.Repository.Hierarchy
Public Class DbAppender
Inherits AdoNetAppender
Public Sub New()
MyBase.BufferSize = 1
MyBase.CommandText = Me.CommandText
Me.Parameters.ForEach(Sub(Parameter As DbParameter)
MyBase.AddParameter(Parameter)
End Sub)
Me.ActivateOptions()
End Sub
Protected Overrides Function CreateConnection(ConnectionType As Type, ConnectionString As String) As IDbConnection
Return MyBase.CreateConnection(GetType(System.Data.SqlClient.SqlConnection), "Data Source=(local);Initial Catalog=Logger;Persist Security Info=True;User ID=username;Password=password")
End Function
Private Overloads ReadOnly Property CommandText As String
Get
Dim _
sColumns,
sValues As String
sColumns = Join(Me.Parameters.Select(Function(P As DbParameter) P.DbColumn).ToArray, ",")
sValues = Join(Me.Parameters.Select(Function(P As DbParameter) P.ParameterName).ToArray, ",")
Return String.Format(COMMAND_TEXT, sColumns, sValues)
End Get
End Property
Private ReadOnly Property Parameters As List(Of DbParameter)
Get
Parameters = New List(Of DbParameter)
Parameters.Add(Me.LogDate)
Parameters.Add(Me.Thread)
Parameters.Add(Me.Level)
Parameters.Add(Me.Source)
Parameters.Add(Me.Message)
Parameters.Add(Me.Exception)
End Get
End Property
Private ReadOnly Property LogDate As DbParameter
Get
Return New DbParameter("Date", DbType.Date, 0, New DbPatternLayout("%date{yyyy-MM-dd HH:mm:ss.fff}"))
End Get
End Property
Private ReadOnly Property Thread As DbParameter
Get
Return New DbParameter("Thread", DbType.String, 255, New DbPatternLayout("%thread"))
End Get
End Property
Private ReadOnly Property Level As DbParameter
Get
Return New DbParameter("Level", DbType.String, 50, New DbPatternLayout("%level"))
End Get
End Property
Private ReadOnly Property Source As DbParameter
Get
Return New DbParameter("Source", DbType.String, 255, New DbPatternLayout("%logger.%M()"))
End Get
End Property
Private ReadOnly Property Message As DbParameter
Get
Return New DbParameter("Message", DbType.String, 4000, New DbPatternLayout("%message"))
End Get
End Property
Private ReadOnly Property Exception As DbParameter
Get
Return New DbParameter("Exception", DbType.String, 2000, New DbExceptionLayout)
End Get
End Property
Private Const COMMAND_TEXT As String = "INSERT INTO Log ({0}) VALUES ({1})"
End Class
Imports log4net
Imports log4net.Core
Imports log4net.Layout
Imports log4net.Appender
Imports log4net.Repository.Hierarchy
Public Class DbParameter
Inherits AdoNetAppenderParameter
Private ReadOnly Name As String
Public Sub New(Name As String, Type As DbType, Size As Integer, Layout As ILayout)
With New RawLayoutConverter
Me.Layout = .ConvertFrom(Layout)
End With
Me.Name = Name.Replace("@", String.Empty)
Me.ParameterName = String.Format("@{0}", Me.Name)
Me.DbType = Type
Me.Size = Size
End Sub
Public ReadOnly Property DbColumn As String
Get
Return String.Format("[{0}]", Me.Name)
End Get
End Property
End Class
Imports log4net
Imports log4net.Core
Imports log4net.Layout
Imports log4net.Appender
Imports log4net.Repository.Hierarchy
Public Class DbPatternLayout
Inherits PatternLayout
Public Sub New(Pattern As String)
Me.ConversionPattern = Pattern
Me.ActivateOptions()
End Sub
End Class
Imports log4net
Imports log4net.Core
Imports log4net.Layout
Imports log4net.Appender
Imports log4net.Repository.Hierarchy
Public Class DbExceptionLayout
Inherits ExceptionLayout
Public Sub New()
Me.ActivateOptions()
End Sub
End Class
Private Shared EscanerLog As log4net.ILog = log4net.LogManager.GetLogger("Log4Net.Config")
Public Sub New(ByVal sIDSesion As String)
Dim sStream As Stream
Dim JsText As String
Using reader As New StreamReader((GetType(ClsGestorLogsTraza).Assembly).GetManifestResourceStream("Comun.Log4Net.Config"))
JsText = reader.ReadToEnd()
sStream = GenerateStreamFromString(JsText)
log4net.Config.XmlConfigurator.Configure(sStream)
End Using
End Sub
Public Function GenerateStreamFromString(ByVal s As String) As Stream
Dim stream = New MemoryStream()
Dim writer = New StreamWriter(stream)
writer.Write(s)
writer.Flush()
stream.Position = 0
Return stream
End Function
Public Function StreamFromResource(ByVal sFilename As String) As Stream
Dim nAssembly As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Dim s As Stream = nAssembly.GetManifestResourceStream(System.Reflection.MethodBase.GetCurrentMethod.DeclaringType, sFilename)
Return s
End Function