2009-10-08 25 views
65

Tôi hoàn toàn mới đối với Log4net.
Tôi đã quản lý để có được một cái gì đó bằng cách thêm một tập tin cấu hình và đăng nhập đơn giản.
Tôi đã mã hóa cứng giá trị thành "C:\temp\log.txt" nhưng điều này không đủ tốt.Làm cách nào để thay đổi vị trí tệp theo chương trình?

Các bản ghi phải đi đến các thư mục đặc biệt

path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); 

và con đường này thay đổi tùy thuộc cho dù bạn đang sử dụng Windows Server 2008 hoặc Windows XP hoặc Vista vv ...

Làm thế nào tôi có thể chỉ cần thay đổi vị trí của tập tin trong log4net lập trình?

Đây là những gì tôi đã làm:

<configSections> 
<section name="log4net" 
     type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/> 
</configSections> 
<log4net>   
    <root> 
     <level value="DEBUG" /> 
     <appender-ref ref="LogFileAppender" /> 
    </root> 
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender"> 
     <param name="File" value="C:\temp\log.txt" /> 
     <param name="AppendToFile" value="true" /> 
     <rollingStyle value="Size" /> 
     <maxSizeRollBackups value="10" /> 
     <maximumFileSize value="10MB" /> 
     <staticLogFileName value="true" /> 
     <layout type="log4net.Layout.PatternLayout"> 
      <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" /> 
     </layout> 
    </appender> 
</log4net> 

class Program 
{ 
    protected static readonly ILog log = LogManager.GetLogger(typeof(Program)); 

    static void Main(string[] args) 
    { 
     log4net.Config.XmlConfigurator.Configure(); 
     log.Warn("Log something"); 

     path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); 


     // How can I change where I log stuff? 
    } 
} 

Chỉ cần phải tìm ra làm thế nào tôi có thể thay đổi để đăng nhập công cụ để nơi tôi muốn.

Mọi đề xuất? Cảm ơn rất nhiều

+0

Bạn cần phải khai thác thông qua IAppenders của logger của bạn và thiết lập FileAppender.File đến con đường sản lượng yêu cầu của bạn. Đây là [ví dụ thực sự hay] (http://insario.com/blog/jfk/archive/2004/11/30/164.aspx). –

Trả lời

82

log4net có thể xử lý việc này cho bạn. Bất kỳ thuộc tính appender nào của chuỗi kiểu có thể được định dạng, trong trường hợp này, sử dụng trình xử lý tùy chọn log4net.Util.PatternString. PatternString thậm chí hỗ trợ enum SpecialFolder cho phép cấu hình thanh lịch sau đây:

<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" > 
    <file type="log4net.Util.PatternString" 
     value="%envFolderPath{CommonApplicationData}\\test.txt" /> 
    ... 
</appender> 

Dưới đây là một thử nghiệm đơn vị đó chứng minh pudding:

[Test] 
public void Load() 
{ 
    XmlConfigurator.Configure(); 
    var fileAppender = LogManager.GetRepository() 
     .GetAppenders().First(appender => appender is RollingFileAppender); 

    var expectedFile = 
     Path.Combine(
      Environment.GetFolderPath(
       Environment.SpecialFolder.CommonApplicationData), 
       "test.txt"); 

    Assert.That(fileAppender, 
     Is.Not.Null & Has.Property("File").EqualTo(expectedFile)); 
} 

Các thử nghiệm sau để kiểm chứng rằng log4net thực sự ghi vào đĩa (mà về cơ bản làm đây là bài kiểm tra "tích hợp", không phải là bài kiểm tra đơn vị, nhưng chúng tôi sẽ để lại nó tại thời điểm này):

[Test] 
public void Log4net_WritesToDisk() 
{ 
    var expectedFile = 
     Path.Combine(
      Environment.GetFolderPath(
       Environment.SpecialFolder.CommonApplicationData), 
       "test.txt"); 

    if (File.Exists(expectedFile)) 
     File.Delete(expectedFile); 

    XmlConfigurator.Configure(); 

    var log = LogManager.GetLogger(typeof (ConfigTest)); 
    log.Info("Message from test"); 

    LogManager.Shutdown(); 

    Assert.That(File.ReadAllText(expectedFile), 
     Text.Contains("Message from test")); 
} 

NB: Tôi khuyên bạn nên sử dụng comp Cú pháp thuộc tính hành động được thể hiện trong ví dụ trên. Xóa tất cả những "< tên thuộc tính =" này làm cho cấu hình của bạn dễ đọc hơn nhiều.

+1

Hi Cảm ơn tôi đã thử điều này nhưng vẫn không đăng nhập dữ liệu ứng dụng Tôi đã có một cái nhìn trên web tôi đã tìm thấy một cái gì đó gọi là PatternString nhưng tôi không có ý tưởng làm thế nào để sử dụng nó. Có ai có ví dụ không? –

+0

@brix - Câu trả lời ban đầu của tôi không hoạt động, vì vậy tôi phải tự chứng minh rằng log4net có thể thực hiện điều này. PatternString là giải pháp :) –

+0

hi, đã thử giải pháp của bạn nhưng vì một số lý do nó không đăng nhập ở tất cả. Tôi đã sao chép những gì bạn đã đề xuất.Không ứng dụng nhưng không có tệp nào được tạo. Bạn có thực sự tạo một tệp không? cảm ơn rất nhiều –

0

Để thay thế cho việc lập trình này, bạn có thể sử dụng các biến môi trường và các mẫu có thể tùy chỉnh trong tệp cấu hình. See this response to a similar question.

Xem "PatternString cho cấu hình dựa trên mẫu" trong the Log4Net V1.2.10 release notes.

Ngoài ra nếu bạn đang nghĩ đến việc viết vào một thư mục như Enviroment.SpecialFolder.CommonApplicationData bạn cần phải xem xét:

  • tất cả các trường hợp của ứng dụng của bạn cho tất cả người dùng sẽ có quyền ghi vào file log? Ví dụ. Tôi không tin rằng những người không phải là quản trị viên sẽ có thể viết thư cho Enviroment.SpecialFolder.CommonApplicationData.

  • Thận trọng nếu nhiều phiên bản của ứng dụng của bạn (cho cùng một hoặc những người dùng khác nhau) đang thử cùng một tệp. Bạn có thể sử dụng "mô hình khóa tối thiểu" (xem http://logging.apache.org/log4net/release/config-examples.html để cho phép nhiều quy trình ghi vào cùng một tệp nhật ký, nhưng có thể sẽ có tác động hiệu suất.Hoặc bạn có thể cung cấp cho mỗi quy trình một tệp nhật ký khác nhau, ví dụ: bằng cách bao gồm id tiến trình trong tên tệp bằng cách sử dụng mẫu có thể tùy chỉnh.

13

Có vẻ như Peter's answer không hoạt động đối với Log4net v1.2.10.0. Phương pháp thay thế được mô tả here.

Về cơ bản, phương pháp là triển khai trình chuyển đổi mẫu tùy chỉnh cho tệp cấu hình log4net.

Đầu tiên thêm lớp này để dự án của bạn:

public class SpecialFolderPatternConverter : log4net.Util.PatternConverter 
{ 
    override protected void Convert(System.IO.TextWriter writer, object state) 
    { 
     Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), base.Option, true); 
     writer.Write(Environment.GetFolderPath(specialFolder)); 
    } 
} 

Sau đó thiết lập các thông số tập tin của FileAppender của bạn như sau:

<file type="log4net.Util.PatternString"> 
    <converter> 
     <name value="folder" /> 
     <type value="MyAppName.SpecialFolderPatternConverter,MyAppName" /> 
    </converter> 
    <conversionPattern value="%folder{CommonApplicationData}\\SomeOtherFolder\\log.txt" /> 
    </file> 

Về cơ bản các %folder nói với nó để nhìn vào bộ chuyển đổi gọi folder trỏ nó đến lớp SpecialFolderPatternConverter. Sau đó nó gọi Convert trên lớp đó, chuyển vào giá trị enum của CommonApplicationData (hoặc bất kỳ) nào.

+0

Cảm ơn vì điều đó. btw, Ứng dụng trong MyAppName tôi nghĩ là đề cập đến Dự án thay vì Ứng dụng. –

34

Tôi tìm thấy một đột biến của mã này trong interwebs:

XmlConfigurator.Configure(); 
log4net.Repository.Hierarchy.Hierarchy h = 
(log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository(); 
foreach (IAppender a in h.Root.Appenders) 
{ 
    if (a is FileAppender) 
    { 
     FileAppender fa = (FileAppender)a; 
     // Programmatically set this to the desired location here 
     string logFileLocation = @"C:\MySpecialFolder\MyFile.log"; 

     // Uncomment the lines below if you want to retain the base file name 
     // and change the folder name... 
     //FileInfo fileInfo = new FileInfo(fa.File); 
     //logFileLocation = string.Format(@"C:\MySpecialFolder\{0}", fileInfo.Name); 

     fa.File = logFileLocation; 
     fa.ActivateOptions(); 
     break; 
    } 
} 

này làm việc cho tôi. Ứng dụng của chúng ta cần đặt tệp nhật ký vào một thư mục chứa số phiên bản của ứng dụng dựa trên tệp AssemblyInfo.cs.

Bạn có thể đặt logFileLocation theo lập trình (ví dụ: bạn có thể sử dụng Server.MapPath() nếu đây là ứng dụng web) cho phù hợp với nhu cầu của bạn.

+3

tôi nghĩ rằng đó là câu trả lời hay nhất :) –

+4

Tôi cảm thấy như thế này cho phép kiểm soát nhiều hơn đối với vị trí tệp. – fregas

3

này đã làm việc cho tôi:

<log4net> 
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> 
.. 
     <file value="${APPDATA}\MyApp\MyApp Client\logs\Log.txt"/> 
.. 
    </log4net> 

Nếu cần phải ghi vào thư mục đặc biệt tôi thấy sự giúp đỡ here (ví dụ 2 và 3).

Edit:

Để trả lời OP .. này làm việc cho khu vực 'tất cả người dùng':

 ... 
     <file value="${ALLUSERSPROFILE}\MyApp\MyApp Client\logs\Log.txt"/> 
     ... 

Đó là bình thường "C: \ ProgramData" trong các phiên bản mới hơn của Windows.

Xem những quá:
How to specify common application data folder for log4net? == https://stackoverflow.com/a/1889591/503621 và ý kiến ​​
&
https://superuser.com/q/405097/47628
https://stackoverflow.com/a/5550502/503621

+1

Tôi thích nó - đẹp và đơn giản. –

+0

'Environment.SpecialFolder.CommonApplicationData' và' $ (APPDATA) 'không phải là cùng một thư mục –

+0

Bạn cũng có thể thử" $ {ALLUSERSPROFILE} "để thay thế. . – bshea

5

Làm thế nào về một đơn giản:

XmlConfigurator.LogFullFilename = @"c:\ProgramData\MyApp\Myapp.log"; 

Tại sao nó quá phức tạp để làm một điều thực sự đơn giản?

+11

Bởi vì, thay đổi đường dẫn tùy thuộc vào việc bạn đang ở trong Windows Server 2008 hoặc winxp hay vista vv ... Trong XP không có thư mục c: \ ProgramData, chỉ trong Win7/Vista. Vì vậy, nếu chúng ta sẽ triển khai ứng dụng này, nó phải tương thích với mọi hệ điều hành. :-) Cứng mã hóa không phải là một thực hành tốt. – Irshad

+4

Tôi đang sử dụng log4net v2.0.3 và thuộc tính này không khả dụng trên XmlConfigurator. Phải được xóa vì câu trả lời đã được đăng. – Appetere

+0

Cảm ơn Jason đã sửa lỗi tiếng Anh của tôi, đây không phải là ngôn ngữ chính của tôi;) Cảm ơn! – Eric

0

Nếu bạn phải triển khai hệ thống không xác định và bạn muốn sử dụng giải pháp đơn giản của Philipp M ngay cả với các thư mục đặc biệt khác nhau, bạn có thể truy xuất đường dẫn thư mục đặc biệt mà bạn muốn và đặt biến env tùy chỉnh trước khi tải cấu hình log4net. string localData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); Environment.SetEnvironmentVariable("MY_FOLDER_DATA", localData); XmlConfigurator.Configure(...

... chỉ để chắc chắn biến env tồn tại và có giá trị bạn muốn.

2

Để cũng thay đổi con đường các bản ghi lỗi của (dựa trên câu trả lời JackAce của):

private static void SetLogPath(string path, string errorPath) 
{ 
    XmlConfigurator.Configure(); 
    log4net.Repository.Hierarchy.Hierarchy h = 
    (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository(); 
    foreach (var a in h.Root.Appenders) 
    { 
     if (a is log4net.Appender.FileAppender) 
     { 
      if (a.Name.Equals("LogFileAppender")) 
      { 
       log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a;      
       string logFileLocation = path; 
       fa.File = logFileLocation;     
       fa.ActivateOptions(); 
      } 
      else if (a.Name.Equals("ErrorFileAppender")) 
      { 
       log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a; 
       string logFileLocation = errorPath; 
       fa.File = logFileLocation; 
       fa.ActivateOptions(); 
      } 
     } 
    } 
} 
0

lớn trường hợp sử dụng cho LINQs OfType<T> lọc:

/// <summary> 
/// Applies a transformation to the filenames of all FileAppenders. 
/// </summary> 
public static void ChangeLogFile(Func<string,string> transformPath) 
{ 
    // iterate over all FileAppenders 
    foreach (var fileAppender in LogManager.GetRepository().GetAppenders().OfType<FileAppender>()) 
    { 
     // apply transformation to the filename 
     fileAppender.File = transformPath(fileAppender.File); 
     // notify the logging subsystem of the configuration change 
     fileAppender.ActivateOptions(); 
    } 
} 

Nếu tên tập tin trong app.config là log.txt điều này sẽ thay đổi kết xuất nhật ký thành logs/some_name_log.txt:

ChangeLogFile(path => Path.Combine("logs", $"some_name_{Path.GetFileName(path)}")); 

Để trả lời các Ops vấn đề ban đầu mà sẽ là:

ChangeLogFile(path => Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), path)); 
+0

Khi tôi đã làm điều này, nó chỉ đơn giản là tạo lại một tập tin rỗng với tên mới, nhưng sau đó 'Logger.GetLogger' tiếp tục ghi vào tên cũ thay thế. –

Các vấn đề liên quan