#.net #trace
#.net #трассировка
Вопрос:
В MSDN я нашел статью о том, как назначить некоторые трассировки определенному действию. Это удобно при просмотре журнала трассировки в средстве просмотра трассировки служб Microsoft, потому что вы можете щелкнуть по действию, чтобы увидеть, что происходит с этим конкретным действием.
Вот пример кода из статьи, как вы присваиваете некоторому событию трассировки действие:
Guid traceID = Guid.NewGuid();
ts.TraceTransfer(0, "transfer", traceID);
Trace.CorrelationManager.ActivityId = traceID; // Trace is static
ts.TraceEvent(TraceEventType.Start, 0, "Add request");
Проблема в том, что CorrelationManager является статическим и, следовательно, влияет на все приложение. Что вы делаете в многопоточном приложении?
К сожалению, я не нашел способа выполнить несколько параллельных действий.
Ответ №1:
Трассировка статична. Однако CorrelationManager хранит ActivityId и LogicalOperationStack в виде локального хранилища потока. CorrelationManager использует CallContext.LogicalSetData для хранения значений в CallContext.
Это означает, что каждый поток может иметь свой собственный ActivityId и LogicalOperationStack.
В псевдокоде реализация для трассировки.CorrelationManager и CorrelationManager.ActivityId выглядит примерно так:
public static class Trace
{
private static correlationManager = null;
public CorrelationManager CorrelationManager
{
get
{
if (correlationManager == null) correlationManager = new CorrelationManager();
return correlationManager;
}
}
}
public class CorrelationManager
{
public Guid ActivityId
{
get
{
object id = CallContext.LogicalGetData("CorelationManager.ActivityId");
if (id == null)
{
return Guid.Empty;
}
return (Guid) id;
}
set
{
CallContext.LogicalSetData("CorrelationManager.ActivityId", value);
}
}
}
Как вы можете видеть, существует только один «объект» трассировки (поскольку он статичен) и только один CorrelationManager (поскольку это свойство, экземпляр реального объекта, для объекта трассировки). Создание экземпляра контекстных данных для каждого потока (ActivityId и LogicalOperationStack) достигается с помощью объекта CallContext.
Данные, хранящиеся через CallContext.LogicalSetData, также «перетекают» в нижестоящие потоки. Итак, если вы задаете ActivityId в начале потока и этот поток впоследствии порождает потоки (которые могут порождать другие потоки), то все эти нижестоящие потоки будут иметь одинаковый ActivityId.
Вы можете увидеть исходный код для Trace и CorrelationManager здесь (не уверен, из какой версии .Net это, но я подозреваю, что это довольно близко к тому, как работают Trace и CorrelationManager сегодня:
Комментарии:
1. Хм, с этим есть какая-то проблема — мы попробовали трассировку. CorrelationManager. ActivityId в приложении MVC, и это работало нормально, пока мы не запустили несколько параллельных веб-запросов — тогда ActivityId иногда внезапно переходил к ‘00000000-0000-0000-0000-000000000000’. Кажется, там что-то сломано. Возможно, нам придется сохранить наш собственный ActivityId в HttpContext, но мы не уверены, поможет ли это.