Службы WCF, ведение журнала по вертикали
Я рассматривал ведение журнала для служб WCF (включая такие технологии, как NLog и PostSharp), но у меня есть кое-что, что я еще не решил... Я не знаю, то ли я упускаю что-то очевидное, то ли это просто невозможно.
Допустим, у меня есть уровень обслуживания WCF с 100+ точками входа вызовов веб-служб. Один из них вызывает проблему. Ниже этого уровня находится уровень бизнес-логики и уровень базы данных. То, что я хочу сделать (я думаю), это включить ведение журнала для этого вызова службы (что было бы включите идентификатор действия для корреляции), так что любые вызовы этой службы регистрируются, и любые сообщения журнала на нижних уровнях также регистрируются. Я действительно не хочу включать ведение журнала на уровне сборки для нижних уровней, потому что они будут совместно использоваться многими методами веб-службы.
Возможно ли это вообще, через существующую структуру или используя что-то вроде CorrelationManager творческим способом?
2 ответа:
В log4net можно задать свойство контекста потока, которое будет включено во все события протоколирования для потока.
public class WcfServiceClass { public void ProblemServiceMethod() { using (log4net.ThreadContext.Stacks["logThisMethod"].Push("ProblemServiceMethod")) { // can also add the correlationId to the logs using this method. // call business logic... } } }
Затем Создайте пользовательский аппендер, который фильтрует по нему.
Это очень упрощенный (но ясный) пример идеи.public class IfContextSetFilterAppender : log4net.Appender.AppenderSkeleton { protected override void Append(LoggingEvent loggingEvent) { bool logThisEntry = false; string serviceMethodBeingLogged; foreach (object p in loggingEvent.GetProperties()) { System.Collections.DictionaryEntry dEntry = (System.Collections.DictionaryEntry)p; if (dEntry.Key == "logThisMethod") { logThisEntry = true; serviceMethodBeingLogged = dEntry.Value.ToString(); } } if (!logThisEntry) return; // don't log it. // log it. } }
Если бы я действительно строил это в таком крупномасштабном сервисе, как вы описываете, я бы:
Создайте поведение конечной точки IOperationInvoker , которое захватывает имя метода и задает значение контекста log4net для всех вызовов, к которым оно применяется.
(необязательно) попросите аппендер прочитать из приложения.настройте список фильтров для всех имен методов службы,которые должны быть зарегистрированы. (Если вы избирательны в том, к каким методам применяется поведение OperationInvoker, аппендеру не нужна эта сложность.)
Таким образом, у вас есть несколько вариантов управления входом в производственную службу только через конфигурацию, никогда не касаясь сервисный код.
Можно создать новый источник ведения журнала для этого конкретного вызова службы, а затем включить диагностику для его фильтрации.
<system.diagnostics> <sources> <source name="Your.Source.Here" switchValue="Verbose"> <listeners> <add name="xml" /> </listeners> </source> </sources> <sharedListeners> <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" traceOutputOptions="LogicalOperationStack" initializeData="l:\logs\N4S.MSO.ADC.Host.svclog" /> </sharedListeners> </system.diagnostics>