2012-11-26 33 views
5

Tôi đang sử dụng Nlog để đăng nhập các chiến lược Ninjatrader của mình. Tôi muốn có thể thêm id chiến lược làm tiền tố cho tất cả thư nLog của mình để tôi có thể lọc các mục nhập liên quan đến từng tài khoản trên chiến lược riêng biệt.Thêm biến làm tiền tố cho tất cả thư nLog

fileTarget.Layout = "${longdate} ${callsite} ${level} ${event-context:item=MyValue} ${message}";` 

Bố cục hiện tại của tôi như trên. Tôi đã cố gắng sử dụng bối cảnh sự kiện: mục nhưng không biết cách in mục ngữ cảnh cho tất cả thư.

tôi đã cố gắng như sau

Logger log = LogManager.GetCurrentClassLogger(); 
LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
logger.Log(theEvent); 

Nhưng nó đã kết thúc in chỉ có một phù hợp với các thông tin bối cảnh trên dòng đầu tiên Sim101 và không phải trên các dòng khác.

2012-11-26 15:09:47.9777 NinjaTrader.Strategy.LODHOD.OnStartUp Debug Sim101 
2012-11-26 15:09:48.3996 NinjaTrader.Strategy.LODHOD.OnBarUpdate Trace BAR UPDATE 
2012-11-26 15:09:49.7902 NinjaTrader.Strategy.LODHOD.EntryOrders Info PLACED ENTRY ORDERS 

Làm cách nào để in Sim101 trên tất cả các dòng ghi?

Trả lời

22

{event-context}LayoutRenderer ghi giá trị từ thuộc tính LogEventInfo của đối tượng Properties.

Thuộc tính là từ điển nơi bạn có thể lưu trữ các giá trị được đặt tên mà bạn muốn NLog thêm vào mỗi thông điệp tường trình.

Nếu bạn muốn gắn thẻ mỗi tin nhắn đăng nhập với "StrategyId" có nghĩa là có hiệu lực khi thông điệp được đăng nhập, bạn nên tạo LogEventInfo của bạn đối tượng một cái gì đó như thế này:

LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
theEvent.Properties["StrategyId"] = "Sim101"; 
Logger.Log(theEvent); 

bố trí của bạn sẽ trông như thế này :

fileTarget.Layout = "${longdate} ${callsite} ${level} ${event-context:item=StrategyId} ${message}"; 

Nếu bạn muốn các trang web gọi nhật ký của mình ít chi tiết hơn, bạn có thể sử dụng GlobalDiagnosticContext hoặc MappedDiagnosticContext.

private void ApplyStrategyABC() 
{ 
    NLog.GlobalDiagnosticContext.Set("StrategyId","ABC"); 
    //Do some stuff 
    LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
    Logger.Log(theEvent); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId"); 
} 

private void ApplyStrategyDEF() 
{ 
    NLog.GlobalDiagnosticContext.Set("StrategyId","DEF"); 
    //Do some stuff 
    LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
    Logger.Log(theEvent); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId"); 
} 

Sử dụng một bố cục như thế này:

fileTarget.Layout = "${longdate} ${callsite} ${level} ${gdc:item=StrategyId} ${message}"; 

có gây ra mỗi tin nhắn đăng nhập để được gắn thẻ với giá trị hiện tại của "StrategyId" trong từ điển toàn cầu.

Để giải trí, bạn cũng có thể tạo một phương thức mở rộng API thông thạo sẽ áp dụng các thuộc tính của bạn cho các đối tượng LogEventInfo mà bạn tạo. Một cái gì đó như thế này (chưa được kiểm tra):

LogEventInfo WithProperty(this LogEventInfo theEvent, string name, string value) 
{ 
    theEvent.Properties[name] = value; 
    return theEvent; 
} 

Sau đó, bạn có thể sử dụng nó như thế này:

var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name).WithProperty("StrategyId", "ABC"); 

Và đây:

var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name).WithProperty("StrategyId", "ABC").WithProperty("SomethingElse", someLocalVariable); 

Nếu bạn muốn trở thành rõ ràng hơn (và giảm khả năng lỗi chính tả), bạn có thể tạo các phương thức mở rộng cụ thể hơn như sau:

LogEventInfo WithStrategy(this LogEventInfo theEvent, string strategy) 
{ 
    theEvent.Properties["StrategyId"] = strategy; 
    return theEvent; 
} 

LogEventInfo WithCurrency(this LogEventInfo theEvent, string currency) 
{ 
    theEvent.Properties["Currency"] = currency; 
    return theEvent; 
} 

var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name).WithStrategy("ABC").WithCurrency("US dollars"); 

EDIT: Hầu hết mọi người sử dụng các phương pháp Logger.Info, Logger.Debug, Logger.Trace, v.v. để viết thông điệp tường trình của họ thay vì tạo LogEventInfo và Nhật ký gọi cho từng thư.Có lẽ sự linh hoạt hơn có sẵn nếu bạn tạo các đối tượng LogEventInfo một cách rõ ràng, nhưng nó cũng làm cho công việc của bạn phức tạp hơn.

Nếu bạn muốn sử dụng các phương pháp Logger.Info, Logger.Debug, v.v ... và trang trí từng thông điệp tường trình với các thuộc tính bổ sung, bạn vẫn có thể làm điều đó.

Hãy nói rằng bạn có hai phương pháp (như tôi đã mô tả ở trên) để áp dụng hai chiến lược khác nhau: ABC và DEF:

Sử dụng một bố cục như thế này:

fileTarget.Layout = "${longdate} ${callsite} ${level} ${gdc:item=StrategyId} ${message}"; 

public class MyClass 
{ 
    private static readonly Logger logger = LogManager.GetCurrentClassLogger(); 

    private void ApplyStrategyABC() 
    { 
    NLog.GlobalDiagnosticContext.Set("StrategyId","ABC"); 
    //Do some stuff 

    logger.Debug("Hello from ABC!"); 

    var x = CalculateSomeValue(); 

    logger.Debug("Value = {0}", x); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId");  
    } 

    private void ApplyStrategyDEF() 
    { 
    NLog.GlobalDiagnosticContext.Set("StrategyId","DEF"); 
    //Do some stuff 

    logger.Debug("Hello from DEF"); 

    var x = CalculateSomeValue(); 

    logger.Debug("Value = {0}", x); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId");  
    } 
} 

In you program call your two strategies: 

var myClass = new MyClass(); 

myClass.ApplyStrategyABC(); 
myClass.ApplyStrategyDEF(); 

Trong mỗi trường hợp, các thông điệp đăng nhập sẽ được gắn thẻ với "StrategyId" được đặt bên trong hàm tương ứng.

Nếu bạn muốn tạo và sử dụng đối tượng LogEventInfo để tạo thư, thì bạn phải nhận ra rằng Thuộc tính của một đối tượng LogEventInfo đối tượng áp dụng CHỈ cho cá thể đó. Nếu bạn tạo một LogEventInfo, đặt thuộc tính của nó, đăng nhập nó, sau đó đăng nhập một tin nhắn bằng cách sử dụng Logger.Info, Logger.Debug, vv sau đó bạn S NOT KHÔNG thấy các thuộc tính mà bạn đặt trên LogEventInfo gốc.

Ví dụ,

var logger = LogManager.GetCurrentClassLogger(); 
var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", "Hello 1"); 
theEvent.Properties["StrategyId"] = "ABC"; 
//This message will be tagged with StrategyId = ABC if the layout uses the event-context LayoutRenderer 
logger.Log(theEvent); 

//This message will NOT be tagged with StrategyId = ABC because that value was only added to the LogEventInfo 
//object that was created above. Another way to think about this is that internally 
//NLog creates a LogEventInfo for each message that is logged via the Debug, Trace, etc 
//methods. 
logger.Debug("Hello 2"); 

Tôi muốn giới thiệu cách sử dụng Logger.Info, Logger.Debug, Logger.Trace, vv phương pháp để đăng nhập tin nhắn của bạn và sử dụng một trong hai GlobalDiagnosticsContext hoặc MappedDiagnosticsContext để xác định các thông tin bổ sung mà bạn muốn được bao gồm trong mỗi thông điệp tường trình.

Nói chung, tôi nghĩ rằng tôi cũng sẽ khuyên bạn nên sử dụng một trong hai Logger.Info, Logger.Debug, Logger.Trace phương pháp HOẶC LogEventInfo + Logger.Log, nhưng không phải cả hai. Sử dụng cả hai, đặc biệt nếu bạn đang cố gắng thêm các giá trị ngữ cảnh bổ sung (StrategyId) có thể trở nên khó hiểu.

Tôi có thể thực hiện tương tự để cài đặt phần mềm. Thông thường, khi bạn cài đặt phần mềm trên máy tính, bạn có thể chọn cài đặt "Typical" để cài đặt các thành phần mà nó muốn cài đặt hoặc "Custom" nơi bạn chọn và chọn các thành phần bạn muốn cài đặt. Tôi không biết về bạn, nhưng tôi thường chọn cài đặt "Điển hình". Sử dụng Logger.Info, Logger.Debug, Logger.Trace giống như cài đặt "Điển hình". Đây là những phương pháp được sử dụng phổ biến nhất để ghi nhật ký. Sử dụng LogEventInfo + Logger.Log giống như chọn cài đặt "Tùy chỉnh". Hàm ý nếu bạn đang sử dụng LogEventInfo là phương pháp ghi nhật ký "điển hình" không đáp ứng được nhu cầu của bạn.

Khi bạn làm việc với NLog, bạn sẽ trở nên quen thuộc hơn với cách hoạt động và một số vấn đề này sẽ trở nên rõ ràng hơn với bạn.

Lưu ý rằng GlobalDiagnosticsContext thực sự là toàn cầu. Nó là một đối tượng tĩnh. Vì vậy, nếu bạn đa luồng, bạn có khả năng xung đột nếu hai chủ đề đang cố thêm một giá trị có cùng tên cho từ điển.

MappedDiagnosticsContext là chuỗi địa phương (nó sử dụng từ điển tĩnh chủ đề để lưu trữ giá trị của nó), vì vậy có thể tốt hơn nên sử dụng trong trường hợp đa luồng.

Nếu bạn muốn nhận được ưa thích và tự động phạm vi các giá trị mà bạn đặt trong GlobalDiagnosticsContext (hoặc MappedDiagnosticsContext), bạn có thể tạo ra một lớp như thế này:

public class ScopedGlobalContext : IDisposable 
{ 
    private string n; 
    private string v; 

    public ScopedGlobalContext(string name, string value) 
    { 
    n = name; 
    v = value; 
    NLog.GlobalDiagnosticsContext.Set(n, v); 
    } 

    public void Dispose() 
    { 
    NLog.GlobalDiagnosticsContext.Remove(n); 
    } 
} 

Và bạn có thể sử dụng nó như thế này:

private void ApplyStrategyDEF() 
    { 
    using (new ScopedGlobalContext("StrategyId", "DEF")) 
    { 
     //Do some stuff 

     logger.Debug("Hello from DEF"); 

     var x = CalculateSomeValue(); 

     logger.Debug("Value = {0}", x); 
    } 
    } 

này sẽ đưa StrategyId, DEF cặp giá trị tên trong từ điển GlobalDiagnosticsContext khi phạm vi using bắt đầu và sẽ loại bỏ nó khi using phạm vi thoát.

+0

đây là câu hỏi đầy đủ của tôi: Tôi có phải thêm sự kiện trước khi gọi hàm theo dõi mọi lúc không? Tôi thêm thuộc tính sự kiện và thực hiện một logger.info (theEvent), nó ngay lập tức in hậu tố cho nhật ký của tôi. cho ví dụ: 2012-11-28 14: 18: 52.3277 NinjaTrader.Strategy.LODHOD.OnStartUp Thông tin Nhật ký Sự kiện: Logger = '' Level = Thông báo Thông báo = 'd4d0d3849c2440f5b41de65d744ede61' SequenceID = 270 Tuy nhiên logger.info tiếp theo không chụp tài sản của tôi 2012-11-28 14: 18: 52.9996 NinjaTrader.Strategy.LODHOD.OnBarUpdate Info BAR UPDATE Mã mà tôi đã sử dụng ở đây. http://codeviewer.org/view/code:2c95 – junkone

+0

và nhật ký tôi đã sử dụng ở đây. http://codeviewer.org/view/code:2c96 – junkone

+0

Bạn không phải sử dụng lớp LogEventInfo để tạo thư và phương thức Đăng nhập để ghi nhật ký chúng. Thông thường, hầu hết mọi người không. Họ sử dụng các phương thức .Info, .Debug, .Trace, vv để viết mã đăng nhập của họ. Tôi sẽ thêm một số ví dụ cho câu trả lời của tôi. – wageoghe

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