我最终使用了这个:
http://www.mikebevers.be/blog/2010/09/log4net-custom-adonetappender/
4小时后摆弄配置并逐渐变得更加沮丧。
希望它可以帮助某人。
如 乔纳森 说,使用资源是一个很好的解决方案。
这有点限制,因为嵌入式资源内容将在编译时修复。我有一个日志组件,它使用基本的Log4Net配置生成一个XmlDocument,使用定义为appSettings的变量(例如,RollingFileAppender的文件名,默认日志记录级别,如果你想使用AdoNetAppender,可能是连接字符串名称)。然后我打电话 log4net.Config.XmlConfigurator.Configure 使用生成的XmlDocument的根元素配置Log4Net。
log4net.Config.XmlConfigurator.Configure
然后,管理员可以通过修改一些appSettings(通常是level,filename,...)来自定义“标准”配置,或者可以指定外部配置文件以获得更多控制。
我过去做过这种方法的一种方法是将配置文件包含为嵌入式资源,并且只是使用它 log4net.Config.Configure(流) 。
这样,我可以使用我熟悉的配置语法,并且不必担心部署文件。
派对有点晚了。但这是一个适合我的最小配置。
样班
public class Bar { private readonly ILog log = LogManager.GetLogger(typeof(Bar)); public void DoBar() { log.Info("Logged"); } }
最小的log4net跟踪配置(在NUnit测试中)
[Test] public void Foo() { var tracer = new TraceAppender(); var hierarchy = (Hierarchy)LogManager.GetRepository(); hierarchy.Root.AddAppender(tracer); var patternLayout = new PatternLayout {ConversionPattern = "%m%n"}; tracer.Layout = patternLayout; hierarchy.Configured = true; var bar = new Bar(); bar.DoBar(); }
打印到跟踪侦听器
Namespace+Bar: Logged
很奇怪 BasicConfigurator.Configure(apndr) 不工作。在我的情况下,它完成了它的工作......但是,无论如何,这里有答案 - 你应该写的 hier.Configured = true; 完成所有设置后(c#代码)。
BasicConfigurator.Configure(apndr)
hier.Configured = true;
//我已经嵌入了三个配置文件作为嵌入式资源,并按如下方式访问它们:
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); } } } }
这是一个在代码中完全创建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"); } }
}
'Vb.Net的解决方案
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
这是一个关于如何创建和使用的坚果示例 AdoNetAdapter 完全在代码中,完全没有任何代码 App.config 文件(甚至不是 Common.Logging )。来吧,删除它!
AdoNetAdapter
App.config
Common.Logging
这具有额外的好处,可以抵御更新 新的命名约定 ,程序集名称现在反映了版本。 ( Common.Logging.Log4Net1213 等)
Common.Logging.Log4Net1213
[SQL]
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
[DbAppender]
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
[的DbParameter]
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
[DbPatternLayout]
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
[DbExceptionLayout]
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
我无法在问题的代码片段中说出“'等等......”包含非常重要的apndr.ActivateOptions(),这在Todd Stout的回答中有说明。如果没有ActivateOptions(),Appender将处于非活动状态,并且不会做任何可以解释失败原因的事情。
Netjes博士 有此用于以编程方式设置connectionstring:
// 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 } }