Cấu hình Log4Net trong tệp bên ngoài không hoạt động


91

Chúng tôi đang sử dụng log4net và muốn chỉ định cấu hình của nó trong một tệp cấu hình bên ngoài (như chúng tôi đã làm với các phần khác). Để làm điều này, chúng tôi đã thay đổi phần log4net trong App.config thành:

...
<section name="log4net" 
     type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
...
<log4net configSource="Log.config" />
...

Và trong tệp Log.Config (cùng thư mục với App.config), chúng ta có:

<log4net>
  <appender name="General" type="log4net.Appender.FileAppender">
    <file value="myapp.log" />
    <layout type="log4net.Layout.SimpleLayout" />
  </appender>
  <root>
    <appender-ref ref="General" />
  </root>
</log4net>

Tuy nhiên, khi chúng tôi chạy ứng dụng, không có tệp nhật ký nào được tạo (và không có quá trình ghi nhật ký nào được thực hiện). Không có thông báo lỗi xuất ra bảng điều khiển.

Nếu chúng tôi di chuyển nội dung của tệp Log.config trở lại App.config (thay thế dòng mã đầu tiên ở trên), nó sẽ hoạt động như mong đợi. Bất kỳ ý tưởng tại sao nó không hoạt động trong một tệp bên ngoài?


Tôi đã gặp phải vấn đề tương tự - chúng tôi có thể đã làm theo cùng một hướng dẫn (được hướng dẫn sai)!
Zach Burlingame

14
Đây là điều tôi không thích về log4net. Theo ý kiến ​​của tôi, khung ghi nhật ký phải là một trong những phần vững chắc nhất của ứng dụng của bạn - nhưng log4net thường có vẻ hơi lỏng lẻo.
UpTheCreek

Câu trả lời:


113

Bạn có thuộc tính sau trong AssemblyInfo.cstệp của mình không :

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]

và mã như thế này ở đầu mỗi lớp yêu cầu chức năng ghi nhật ký:

private static readonly ILog log = 
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

Tôi có một bài đăng trên blog chứa thông tin này và thông tin khác ở đây .


17
Điều này hoạt động, hãy đảm bảo bạn nếu bạn tạo tệp log4net.config để đặt thuộc tính "Sao chép vào Thư mục đầu ra" trên "Sao chép Luôn luôn".
E. van der Spoel

@mitchwheat Thật tuyệt vời, tôi đã chiến đấu với một giải pháp dựa trên ninja để làm chính xác những gì điều này làm cả ngày ... cảm ơn anh bạn!
Chiến tranh

39

Có một khiếm khuyết mở về vấn đề này. Log4Net không hỗ trợ thuộc tính configSource của các phần tử cấu hình. Để sử dụng giải pháp tệp cấu hình thuần túy, bạn sử dụng khóa log4net.Config trong appSettings.

Bước 1: Bao gồm định nghĩa phần cấu hình bình thường:

<configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>

Bước 2: Sử dụng phím log4net.Config kỳ diệu trong appSettings.

<appSettings>
      <add key="log4net.Config" value="log4net.simple.config" />
</appSettings>

Bước 3: Đóng góp một bản vá để sửa lỗi xử lý configSource.


5
Một cuộc gọi đến log4net.Config.XmlConfigurator.Configure (); nên vượt qua vấn đề này với nó không đọc configSource
Greg Domjan

Điều này không thay đổi bất cứ điều gì đối với tôi. Tôi vẫn chưa tìm ra sự cố nhưng tôi sẽ cố gắng theo dõi.
Don Rolling

5
Điều quan trọng là phải đánh dấu tệp cấu hình log4net là "sao chép nếu mới hơn". Nếu tệp cấu hình không được sao chép vào thư mục bin thì nó sẽ không hoạt động.
Francisco Goldenstein

Điều này làm việc với tôi hiện tại và tôi thích nó hơn giải pháp được chấp nhận vì một số thư viện của tôi được sử dụng trong một ứng dụng web, nơi ghi nhật ký được định cấu hình trong một log4net.config riêng biệt và đôi khi được sử dụng trong ứng dụng độc lập nơi ghi nhật ký. được định cấu hình trong app.exe.config. Bằng cách này, tất cả nằm trong cấu hình thay vì trong thông tin lắp ráp - Tôi không muốn "mã hóa" nó thành log4net.config
Danny

27

Bước đã bị bỏ lỡ là

log4net.Config.XmlConfigurator.Configure(); 

điều này sẽ làm cho configSource được sử dụng. Đảm bảo rằng bạn đã gọi nó một lần trước khi gọi GetLogger ();


Bạn không cần phải làm điều này nếu bạn sử dụng giải pháp của Mitch Wheat.
Robert Wagner

4
@Robert: Chắc chắn rồi, mặc dù giải pháp của Mitch Wheat yêu cầu mã hóa cứng tệp cấu hình bên ngoài app.config - Tôi đã đọc câu hỏi ban đầu là tại sao configSource không hoạt động, nó hoạt động nếu bước bổ sung này được làm theo.
Greg Domjan

Tôi thích cách tiếp cận này hơn, đặc biệt là vì tôi tạo một trình xử lý nhật ký trình bao bọc sử dụng nội bộ log4net (có thể được thay thế sau này), sau đó trong trình xử lý nhật ký trình bao bọc này, tôi dễ dàng gọi log4net.Config.XmlConfigurator.Configure (). Bằng cách này, bất kỳ dự án với app.config riêng của mình có thể sử dụng bộ xử lý log wrapper này, mà không cần phải thay đổi assembler.cs
zheng yu

19

Đảm bảo rằng tệp log4net.config của bạn được đặt với các thuộc tính sau:

Xây dựng Hành động: Nội dung

Sao chép vào thư mục đầu ra: Sao chép Luôn luôn


10

Hoặc sử dụng,

<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<appSettings>
<add key="log4net.Config" value="Log4Net.config" />
</appSettings>

hoặc chỉ,

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo("Log4Net.config"));

Trong cả hai trường hợp, tệp, Log4Net.config, phải ở đó trong thư mục đầu ra. Bạn có thể thực hiện việc này bằng cách đặt thuộc tính tệp Log4Net.config trong trình khám phá giải pháp. Xây dựng Hành động - Nội dung và Sao chép vào Thư mục Đầu ra - Sao chép luôn


bạn không cần <configSections> thẻ đối với trường hợp đầu tiên
disklosr

2

Hãy coi chừng vấn đề này ...

Trong trường hợp của tôi, mọi thứ đã được định cấu hình chính xác. Vấn đề là tôi đã sử dụng Web Deploy bên trong Visual Studio 2013 để tải trang web lên WinHost.com và nó đặt lại ACL trên máy chủ. Điều này đã thu hồi tất cả quyền trên các thư mục và tệp - log4net không thể ghi tệp.

Bạn có thể đọc thêm về nó ở đây:

Cách ngăn Triển khai Web / MSBuild làm xáo trộn quyền máy chủ

Tôi đã yêu cầu nhóm hỗ trợ ở đó đặt lại ACL và sau đó log4net bắt đầu đăng nhật ký. :)


1

Giả sử bạn có một tệp cấu hình bên ngoài được gọi là log4net.config được sao chép vào thư mục triển khai của bạn, bạn có thể định cấu hình nó như sau:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Reflection;

using log4net;

namespace MyAppNamespace {
    static class Program {
        //declare it as static and public so all classes in the project can access it
        //like so: Program.log.Error("got an error");
        public static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
             //configure it to use external file
            log4net.Config.XmlConfigurator.Configure(new Uri(Application.StartupPath + "\\log4net.config"));
            //use it
            log.Debug("#############   STARING APPLICATION    #################");


            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormMain());
        }
    }
}

1

Tôi đã có cùng một vấn đề, ngoài việc có

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net")]

trong dự án đang chạy, tôi cũng có dòng sau trong một dự án tham chiếu:

[assembly: log4net.Config.XmlConfigurator]

Khi tôi loại bỏ dòng này trong các dự án được tham chiếu, các bản ghi bắt đầu xuất hiện.


1

Cũng có thể bật chế độ Gỡ lỗi cho log4net. Chèn cái này vào tệp App.config:

 <appSettings>
      <add key="log4net.Internal.Debug" value="true"/>
 </appSettings>
 <system.diagnostics>
      <trace autoflush="true">
      <listeners>
           <add
             name="textWriterTraceListener"
             type="System.Diagnostics.TextWriterTraceListener"
             initializeData="link\to\your\file.log" />
      </listeners>
      </trace>
 </system.diagnostics>

và ít nhất bạn sẽ nhận được thông báo lỗi, từ đó bạn có thể tìm ra chính xác những gì đã xảy ra. Trong trường hợp của tôi, tôi chỉ đơn giản là quên đặt Copy to output directorythành Copy Always.


0

@Mitch, Hóa ra là có một tệp với khai báo [assembly: ...], nhưng nó không có thuộc tính ConfigFile.

Sau khi tôi thêm nó và trỏ nó vào Log.config, nó bắt đầu hoạt động. Tôi đã nghĩ rằng nó sẽ hoạt động giống như tất cả các phần cấu hình khác (tức là AppSettings) và chấp nhận các tệp cấu hình bên ngoài mà không cần sửa đổi.

Chúng tôi không có tuyên bố thứ hai mà bạn đã đề cập, vì chúng tôi gói nó trong một nhà cung cấp nhật ký tĩnh toàn cầu.


0

Trong trường hợp của tôi, tôi nhận được thông báo lỗi này:

log4net: config file [C:\........\bin\Debug\log4net.config] not found.

log4net.configtệp nằm trong dự án Visual Studio 2017, nhưng khi tôi kiểm tra tệp trong bin\Debugthư mục, tôi không thể tìm thấy nó.

Thiết lập lắp ráp ban đầu của tôi như thế này:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]

Sau một thời gian nghiên cứu, tôi thay đổi nó thành như sau và nó hoạt động:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"..\..\log4net.config", Watch = true)]

0
  1. thêm sau vào AssemblyInfo.cs

[assembly: log4net.Config.XmlConfigurator (ConfigFile = "Log4Net.config")]

  1. Đảm bảo rằng log4net.config được bao gồm trong dự án
  2. Trong thuộc tính của log4net.config

thay đổi Sao chép thành Đầu ra Xám thành Sao chép nếu mới hơn

  1. Kiểm tra kỹ giá trị cấp cấp nhật ký = "TẤT CẢ"

0

Cũng cần chỉ ra rằng trong một ứng dụng web, nó nằm trong thư mục gốc chứ không phải thư mục bin, vì vậy hãy đảm bảo rằng đó là nơi bạn đặt tệp cấu hình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.