Как организовать источники событий для блока приложения семантической регистрации?

Блок приложения семантической регистрации (SLAB) очень привлекателен для меня, и я хочу использовать его в большом, составном приложении, которое я пишу. Чтобы его использовать, пишется класс, производный от "EventSource", и в него включается один метод для каждого события, которое они хотят зарегистрировать как типизированное событие, вместо простой строки.

Такое приложение, как мое, может иметь сотни таких событий. Я мог бы иметь класс на основе EventSource с одним событием "SomethingHappened" и регистрировать все через него, в одном крайнем конце спектра усилий и точности, и у меня могло быть одно событие для каждой выполняемой мной операции.

Мне кажется хорошей идеей иметь производные EventSource для разных функциональных областей. Приложение мало знает бизнес-логику; все это обеспечивается подключаемыми модулями MEF, поэтому у меня могут быть источники событий для начальной загрузки, безопасности, изменений конфигурации и т. д., и любой подключаемый модуль может определять источник событий для любых событий, которые он хочет регистрировать.

Это хорошая стратегия или много EventSource производные логгеры нежелательная функция приложения?

4 ответа

Решение

Из твоего вопроса

... Я хочу использовать его в большом, составном приложении, которое я пишу...

Я могу сделать вывод, что большое значение подразумевается в контексте одного разработчика. В этом случае вы можете получить из EventSource и добавить все события, которые вы, возможно, захотите в этот класс. Не имеет особого смысла создавать дополнительный производный класс EventSource для каждой части вашего составного приложения, поскольку это загрязнит базу данных регистрации источника событий, в которой уже зарегистрировано 2 тыс. Провайдеров. Кроме того, было бы трудно включить ведение журнала для вашего приложения, если вам нужно запомнить 20 руководств, которые необходимо включить, чтобы следовать логике приложения через несколько уровней.

Компромиссом будет определение в вашем классе EventSource некоторого общего события, такого как

public void WriteViolation(string Subsystem, string Message, string Context)

где у вас есть в ваших компонентах класс логгера для каждого компонента

public static class NetworkLogger
{
   public static void Violation(string message)
   {
      GenericSource.Instance.Violation("Network", message, NetworkContext.Current);
   }
}

public static class DatabaseLogger
{
  public static void Violation(string message)
  {
      GenericSource.Instance.Violation("Database", message, DBContext.Current);
  }
}

Таким образом, вы можете сохранить специфический компонент регистраторов и при необходимости добавлять, например, автоматически контекстную информацию в общее событие. Другой подход заключается в использовании в вашей трассировке приложения, когда ваш метод трассировки ввод / вывод, информация, предупреждение, ошибка и ваш производный класс EventSource знают только эти события. Когда вы добавляете для каждой записи трассировки имя типа + имя метода, вы можете фильтровать по пространствам имен и группировать по классам в WPA, чтобы увидеть, что вы делали. Пример показан в Семантической трассировке для.NET 4.0. Для большого приложения вы можете проверить на своем компьютере файл

C:\Windows\Microsoft.NET\Framework\v4.0.30319\CLR-ETW.man

Вы можете открыть его с помощью ecmangen.exe из Windows SDK, чтобы получить приятный графический интерфейс для просмотра структуры событий. В.NET определены только два провайдера событий. Многие события сгруппированы по ключевым словам, чтобы включить определенные аспекты.NET, например, GC, Loader, Exceptions, .... Это важно, так как вы можете передать, включив в него ключевые слова, специфичные для поставщика, чтобы включить только некоторые события крупного поставщика.,

Вы также можете проверить Microsoft.Windows.ApplicationServer.Applications.45.man, чтобы узнать, как парни из Workflow думают о событиях ETW. Это должно помочь найти свой путь. Речь идет не столько о том, как именно вы структурируете свои события, поскольку реальным тестом является обнаружение производственных ошибок на сайтах клиентов. Высокая вероятность того, что вам нужно будет выполнить несколько итераций, пока не найдете правильный баланс для регистрации / отслеживания соответствующей информации, которая поможет вам диагностировать сбои в полевых условиях.

Это немного ручная работа, так как это слишком долго для комментария. Но как насчет шаблонов, а затем заводского сервиса?

Тогда это не изменится, и вы все перепутаете при запуске приложения и после загрузки плагинов.

interface IReportable
{
    void Report(object param);
}

interface IKernel
{
    T Get<T>();
}

class EventSource2 : EventSource
{
    private IKernel _factory;

    public EventSource2(IKernel factory)
    {
        _factory = factory;
    }

    public void Report<TReportable>(object param = null) where TReportable : IReportable
    {
        var reportable = _factory.Get<TReportable>();

        reportable.Report(param);

        //... Do what you want to do with EventSource
    }
}

Логически группируйте события в другого меньшего поставщика (классы EventSource), а не в 1 большой файл.

Преимущество этого заключается в том, что вы можете включить События только для тех поставщиков, которые вам нужны в особых случаях.

Не думайте, что EventSource - это список всех возможных событий журнала, которые вы можете выполнить в своем приложении. Помните, что есть способы отфильтровать ваши события, используя ключевые слова и подробности / уровни событий. Вы даже можете углубиться в детали и использовать коды операций и задачи. Версия 1.1 SLAB поддерживает ActivityID и RelatedActivityID. Версия 2.0 ( https://slab.codeplex.com/wikipage?title=SLAB2.0ReleaseNotes&version=2), выпущенная ранее на этой неделе, теперь поддерживает идентификатор процесса и потока.

Чтобы привести пример, у меня есть очень маленький производный класс EventSource и есть методы для StartLog, LogStatus, StopLogging, LogError, LogDebug и CreateDump, причем первые три используют один и тот же уровень события, но разные идентификаторы событий из-за различий в форматировании и оставшихся одни используют разные уровни событий, поэтому я не отлаживаю и не создаю дампы, если я не включу его динамически с настройкой файла конфигурации. Дело в том, что я могу использовать те же методы с сайта asp.net, а также библиотеки классов или консольные приложения. Не забывайте, что это только определяет события регистрации. Вам все еще нужно подписаться на событие, чтобы дать вам больше возможностей. Вы можете получить отладочные сообщения в файл, а сообщения об ошибках - в базу данных и / или электронную почту. Возможности безграничны.

Одна последняя вещь. Я думал, что загнал себя в угол, когда я провел тестирование и обнаружил, что несколько сборок записывают в журнал один и тот же файл, потому что они используют одни и те же методы события (и, следовательно, один и тот же идентификатор события, ключевое слово, уровень события и т. Д.). Я изменил свой код, чтобы передать имя вызывающей сборки, которое теперь используется в процессе фильтрации при определении того, следует ли записывать сообщение журнала (из настроек файла конфигурации) и где (в файл журнала на основе имени сборки). Надеюсь это поможет!

Другие вопросы по тегам