How to store per thread contextual data in c#? -
my concrete need store remote ip can printed while logging, without explicitly passing down every method call. sort of per thread environment variable scope.
i thought of having per thread singleton logger can access it. there better/safer way?
make work async plus.
my ideal api should this:
using (new logscope("key1", "value1")) { call1(); } using (new logscope("key1", "value1")) { call1(); } void call1() { using (new logscope("key2", "value2")) { call2(); // key1:value1 key2:value2 using (new logscope("key1", "value3")) { call2(); // key1:value3 key2:value2 } } using (new logscope("key1", "value3")) { call2(); // key1:value3 } } void call2() { foreach (var kv in logscope.context) console.write("'{0}':'{1}' "); console.writeline(); }
not optimal implementation. should looking for. , should @ least demonstrate principles can reuse.
public class logscope : idisposable { private static readonly threadlocal<stack<dictionary<string, string>>> currentdictionary = new threadlocal<stack<dictionary<string, string>>>(() => new stack<dictionary<string, string>>()); public logscope(string key, string value) { var stack = currentdictionary.value; dictionary<string, string> newdictionary = null; if (stack.count == 0) { newdictionary = new dictionary<string, string>(); } else { newdictionary = new dictionary<string, string>(stack.peek()); } newdictionary[key] = value; stack.push(newdictionary); } public void dispose() { currentdictionary.value.pop(); } public static ienumerable<keyvaluepair<string, string>> context { { var stack = currentdictionary.value; if (stack.count == 0) { return enumerable.empty<keyvaluepair<string, string>>(); } else { return stack.peek(); } } } }
edit: should specify in implementation of logscope
, instance of logscope
work if instantiated , disposed on same thread. if create logscope
in 1 thread, , dispose in thread, results undefined. likewise, while logscope
instance in effect, key/values visible within thread.
Comments
Post a Comment