Зависимости касаются реализации EventSource для семантической регистрации в больших приложениях
Я работаю над большим продуктом, состоящим из трех служб Windows и нескольких обычных приложений Windows (.exe). Теперь мы хотим перейти к ETW и семантическому ведению журнала и использовать Microsoft.Diagnostics.Tracing.EventSource.
Я где-то читал, что все логически связанные части приложения должны использовать один и тот же источник событий. Это означает, что предпочтительно, чтобы мы хотели иметь в основном один EventSource для наших сервисов. Но как мы можем сделать это, не вводя зависимости практически во все сборки продукта?
Приложение в настоящее время состоит из около 70 сборок. И чтобы иметь возможность создать log-метод в EventSource, который, например, принимает enum-значение, сборка, содержащая источник события, должна ссылаться на сборку, определяющую перечисление, что означает, что определение перечисления должно быть перемещено из сборка с его использованием, возможно.exe, к чему-то, на что ссылаются все сборки.
Есть ли какой-нибудь способ иметь несколько классов, полученных из EventSource, в одном приложении, которые все еще используют один и тот же ETW EventSource? Или как можно было бы реализовать семантическую регистрацию с помощью ETW в таком сценарии, когда нежелательно вводить целую кучу новых зависимостей для создания вашего класса журнала?
3 ответа
Будь осторожен, EventSource
занятия должны быть запечатаны! Если вы хотите использовать внедрение зависимости с помощью EventSource
есть обходной путь...
Определите простой интерфейс:
// A simple interface to log what you need ...
public interface ILog
{
void Debug(string message);
void Info(string message);
void Warn(string message);
void Error(string message);
void Error(string message, Exception exception);
}
И реализация (реализация вашего интерфейса должна быть украшена NonEventAttribute
:
[EventSource(Name = "MyLogEventsource")]
public class Log : EventSource, ILog
{
public Log()
{
EventSourceAnalyzer.InspectAll(this);
}
[NonEvent]
public void Debug(string message)
{
DebugInternal(message);
}
[Event(1)]
private void DebugInternal(string message)
{
WriteEvent(1, message);
}
[NonEvent]
public void Info(string message)
{
InfoInternal(message);
}
[Event(2)]
private void InfoInternal(string message)
{
WriteEvent(2, message);
}
[NonEvent]
public void Warn(string message)
{
WarnInternal(message);
}
[Event(3)]
private void WarnInternal(string message)
{
WriteEvent(3, message);
}
[NonEvent]
public void Error(string message)
{
ErrorInternal(message, "", "");
}
[NonEvent]
public void Error(string message, Exception exception)
{
ErrorInternal(message, exception.Message, exception.ToString());
}
[Event(4)]
private void ErrorInternal(string message, string exceptionMessage, string exceptionDetails)
{
WriteEvent(4, message, exceptionMessage, exceptionDetails);
}
}
Теперь вы можете ввести свой класс журнала ^^
Я обычно делаю это так, чтобы была сегрегация интерфейсов, даже если они используют один экземпляр источника события. В моем ioc весь код с ISingletonDependency зарегистрирован как синглтон. Таким образом, вы можете вызывать интерфейсы с очень специфическими методами, но они все те же EventSource.
Надеюсь это поможет.
public MyCompanyEventSource: IMyCompanyEventSource, ISingletonDependency{
}
public IMyCompanyEventSource: IComponentLogger1, IComponentLogger2, IComponentLogger3{
}
public Component1{
public Component1(IComponentLogger logger){
}
}
Есть три стратегии:
- Создайте одну сборку, которая содержит только производный класс EventSource, который определяет события для всего приложения. Добавьте ссылку на эту сборку во все необходимые проекты. Для простоты вы можете обернуть его в пакет nuget.
- Создайте один тестовый проект только с одним производным классом EventSource. Используйте его только для проверки. Скопируйте этот класс во все необходимые проекты. Это в основном то же решение, но без бинарных зависимостей.
- Создайте новый производный класс EventSource для каждого проекта, но укажите для них один и тот же атрибут Guid. В этом случае вам необходимо убедиться, что все эти источники событий имеют одинаковое объявление для перекрывающихся (с одинаковым идентификатором) событий. И в этом случае вам нужно написать какой-нибудь инструмент слияния манифеста для создания комбинированного манифеста.