Ini Ide Buruk, saya tahu, tapi ... Saya ingin mengkonfigurasi log4net secara terprogram dari awal tanpa file konfigurasi. Saya sedang mengerjakan aplikasi logging sederhana untuk saya dan tim saya gunakan untuk banyak aplikasi departemen yang relatif kecil yang menjadi tanggung jawab kami. Saya ingin mereka semua masuk ke database yang sama. Aplikasi logging hanyalah pembungkus di sekitar log4net dengan AdoNetAppender yang telah dikonfigurasi sebelumnya.
Semua aplikasi ClickOnce disebarkan, yang menimbulkan masalah kecil dengan menyebarkan file konfigurasi. Jika file konfigurasi adalah bagian dari proyek inti, saya dapat mengatur propertinya untuk diterapkan dengan rakitan. Tapi itu bagian dari aplikasi yang ditautkan, jadi saya tidak memiliki opsi untuk menerapkannya dengan aplikasi utama. (Jika itu tidak benar, tolong beri tahu saya).
Mungkin karena ini Ide Buruk, sepertinya tidak banyak kode contoh yang tersedia untuk mengonfigurasi log4net secara terprogram dari awal. Inilah yang saya miliki sejauh ini.
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...
Setelah mengkonfigurasi semua parameter untuk apndr
, saya pertama kali mencoba ini ...
Dim hier As Hierarchy = DirectCast(LogManager.GetRepository(), Hierarchy)
hier.Root.AddAppender(apndr)
Tidak berhasil. Kemudian, sebagai bidikan dalam kegelapan, saya mencoba ini sebagai gantinya.
BasicConfigurator.Configure(apndr)
Itu juga tidak berhasil. Apakah ada yang punya referensi bagus tentang cara mengkonfigurasi log4net secara terprogram dari awal tanpa file konfigurasi?
Jawaban:
Salah satu cara saya melakukan ini di masa lalu adalah dengan memasukkan file konfigurasi sebagai sumber daya yang disematkan, dan hanya menggunakan log4net.Config.Configure (Stream) .
Dengan begitu, saya dapat menggunakan sintaks konfigurasi yang sudah saya kenal, dan tidak perlu khawatir file akan diterapkan.
sumber
Berikut adalah contoh kelas yang membuat konfigurasi log4net sepenuhnya dalam kode. Saya harus menyebutkan bahwa membuat logger melalui metode statis umumnya dipandang buruk, tetapi dalam konteks saya, inilah yang saya inginkan. Terlepas dari itu, Anda dapat membuat kode untuk memenuhi kebutuhan Anda.
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"); } }
}
sumber
hierarchy.Configured = true;
yang bermanfaat bagi sayaSolusi yang lebih ringkas:
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);
Jangan lupa untuk memanggil metode ActivateOptions :
sumber
ActivateOptions()
sudah pasti hilang atau setidaknya tidak cukup disebutkan di dokumen.Seperti yang dikatakan Jonathan , menggunakan sumber daya adalah solusi yang bagus.
Ini sedikit membatasi karena konten sumber daya yang disematkan akan diperbaiki pada waktu kompilasi. Saya memiliki komponen logging yang menghasilkan XmlDocument dengan konfigurasi Log4Net dasar, menggunakan variabel yang didefinisikan sebagai appSettings (misalnya nama file untuk RollingFileAppender, tingkat logging default, mungkin nama string koneksi jika Anda ingin menggunakan AdoNetAppender). Dan kemudian saya menelepon
log4net.Config.XmlConfigurator.Configure
untuk mengkonfigurasi Log4Net menggunakan elemen root dari XmlDocument yang dihasilkan.Kemudian administrator dapat menyesuaikan konfigurasi "standar" dengan memodifikasi beberapa appSettings (biasanya level, nama file, ...) atau dapat menentukan file konfigurasi eksternal untuk mendapatkan kontrol lebih.
sumber
Saya tidak tahu dalam cuplikan kode pertanyaan apakah "'Dan seterusnya ..." menyertakan apndr.ActivateOptions () yang sangat penting yang ditunjukkan dalam jawaban Todd Stout. Tanpa ActivateOptions () Appender tidak aktif dan tidak akan melakukan apa pun yang dapat menjelaskan mengapa itu gagal.
sumber
Agak terlambat untuk pesta. Tapi di sini adalah konfigurasi minimal yang berhasil untuk saya.
Kelas sampel
public class Bar { private readonly ILog log = LogManager.GetLogger(typeof(Bar)); public void DoBar() { log.Info("Logged"); } }
Minimal konfigurasi jejak log4net (di dalam pengujian 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(); }
Mencetak ke pemroses jejak
Namespace+Bar: Logged
sumber
Netjes memiliki ini untuk mengatur string koneksi secara terprogram:
// 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 } }
sumber
// Saya telah menyematkan tiga file konfigurasi sebagai Sumber Tertanam dan mengaksesnya seperti ini:
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); } } } }
sumber
Aneh itu
BasicConfigurator.Configure(apndr)
tidak berhasil. Dalam kasus saya itu melakukan tugasnya ... Tapi, bagaimanapun, inilah jawabannya - Anda harus menulishier.Configured = true;
(c # code) setelah Anda menyelesaikan semua pengaturan.sumber
Saya akhirnya menggunakan ini:
http://www.mikebevers.be/blog/2010/09/log4net-custom-adonetappender/
Setelah 4 jam mengutak-atik konfigurasi dan semakin frustrasi.
Semoga bisa membantu seseorang.
sumber
Berikut adalah contoh sup-to-kacang tentang bagaimana Anda dapat membuat dan menggunakan
AdoNetAdapter
sepenuhnya dalam kode, sepenuhnya tanpa adanyaApp.config
file apa pun (bahkan untukCommon.Logging
). Silakan, hapus!Ini memiliki manfaat tambahan karena tahan terhadap pembaruan di bawah konvensi penamaan baru , di mana nama assembly sekarang mencerminkan versi. (
Common.Logging.Log4Net1213
, dll.)[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 )
[Utama]
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
sumber
'Solusi untuk 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
sumber