2016-08-19 3 views
6

मैं NLog 4.3.5 और नेट ढांचा 4.6.1NLog MappedDiagnosticsLogicalContext async में काम नहीं कर/ConfigureAwait (गलत) के साथ इंतजार है

उपयोग कर रहा हूँ जब मैं एक सर्वर साइड आपरेशन मैं फोन शुरू:

NLog.MappedDiagnosticsLogicalContext.Set("OperationId", Guid.NewGuid()); 

यह मैप हो जाता है और मेरी लॉग फ़ाइलों में प्रकट होता है। सब अच्छा है .... या यह है? मेरी लॉग फ़ाइलों की समीक्षा करते समय, मैंने देखा कि यह ऑपरेशन आईडी मान काम नहीं कर रहा है जैसा कि मैंने उम्मीद की थी।

उदाहरण:

  1. धागा 19 में एक ऑपरेशन शुरू होता है और संदर्भ सेट।

  2. यह सब का इंतजार कॉल

  3. यह प्रदर्शन एक

    var tasks = items.Select(item => Task.Run(() => { /* do stuff */} 
    await Task.WhenAll(tasks).ConfigureAwait(false) 
    
  4. धागे इन कार्यों के लिए इस्तेमाल में से एक धागा 31 है पर .ConfigureAwait (गलत) का उपयोग करता है (ध्यान रखें कि बाद के लिए)
  5. इस बीच, थ्रेड 36 में, एक अलग सर्वर विधि को बुलाया जाता है और एक नया ऑपरेशन शुरू होता है। कई लॉग संदेशों इसके साथ लिखा जाता है अद्वितीय आपरेशन आईडी
  6. इस आपरेशन ConfigureAwait (गलत)
  7. अगले लॉग बयान धागा 31. पर होता है तब से, यह आपरेशन आईडी उस के लिए बनाया गया था लॉग के साथ 2 अलग इंतजार कॉल करता है ऑपरेशन जो थ्रेड 1 9 पर शुरू हुआ!

मुझे ऐसा होने की उम्मीद नहीं थी और यह कैसे हुआ यह अनिश्चित है। लेकिन, जैसा कि मैंने अपने लॉग इतिहास को देखा है, मैं देखता हूं कि इस तरह की चीज पहले हुई है।

मैंने सोचा कि तार्किक कॉल संदर्भ को संभालना था। क्या यह मेरा उपयोग कॉन्फ़िगरएवाइट (झूठा) है जो इस व्यवहार का कारण बन रहा है? यही एकमात्र चीज है जिसके बारे में मैं सोच सकता हूं ....

उत्तर

1

आप इस के आसपास काम कर सकता था इस प्रकार है: कॉन्फ़िग फ़ाइल में

public static class LogicalThreadContext 
{ 
    private const string KeyPrefix = "NLog.LogicalThreadContext"; 

    private static string GetCallContextKey(string key) 
    { 
     return string.Format("{0}.{1}", KeyPrefix, key); 
    } 

    private static string GetCallContextValue(string key) 
    { 
     return CallContext.LogicalGetData(GetCallContextKey(key)) as string ?? string.Empty; 
    } 

    private static void SetCallContextValue(string key, string value) 
    { 
     CallContext.LogicalSetData(GetCallContextKey(key), value);   
    } 

    public static string Get(string item) 
    { 
     return GetCallContextValue(item); 
    } 

    public static string Get(string item, IFormatProvider formatProvider) 
    { 
     if ((formatProvider == null) && (LogManager.Configuration != null)) 
     { 
      formatProvider = LogManager.Configuration.DefaultCultureInfo; 
     } 

     return string.Format(formatProvider, "{0}", GetCallContextValue(item)); 
    } 

    public static void Set(string item, string value) 
    { 
     SetCallContextValue(item, value); 
    } 
} 

[LayoutRenderer("mdlc2")] 
public class LogicalThreadContextLayoutRenderer : LayoutRenderer 
{ 
    [DefaultParameter] 
    public bool Name {get;set;} 

    protected override void Append(StringBuilder builder, LogEventInfo logEvent) 
    { 
     builder.Append(LogicalThreadContext.Get(Name, null)); 
    } 
} 

//or application_start for ASP.NET 4 
static void Main(string[] args) 
{ 
    //layout renderer 
    ConfigurationItemFactory.Default.LayoutRenderers 
      .RegisterDefinition("mdlc2", typeof(LogicalThreadContextLayoutRenderer)); 
} 

उपयोग:

${mdlc2:OperationId} 
+0

हाँ, कि समाधान लिंक मैंने ऊपर पोस्ट में था। – Keith

+0

यह आंशिक रूप से लिंक से है। मैंने आपकी आवश्यकताओं के लिए अद्यतन और विस्तार किया है। – Julian

संबंधित मुद्दे