2014-10-12 9 views
7

Sto lavorando a un prodotto di grandi dimensioni costituito da tre servizi Windows e diverse applicazioni Windows normali (.exe). Ora vogliamo passare a ETW e Semantic Logging e utilizzare Microsoft.Diagnostics.Tracing.EventSource.La dipendenza riguarda l'implementazione di EventSource per la registrazione semantica nell'applicazione di grandi dimensioni

Ho letto da qualche parte che tutte le parti logicamente connesse dell'applicazione devono utilizzare la stessa origine evento. Ciò significa che preferibilmente vorremmo avere praticamente una sola EventSource per i nostri servizi. Ma come possiamo farlo senza introdurre dipendenze tra praticamente tutti gli assembly nel prodotto?

Attualmente l'applicazione è composta da circa 70 gruppi. E per essere in grado di creare un metodo di log in EventSource che ad esempio accetta un valore enum, l'assembly che contiene l'origine evento deve fare riferimento all'assembly che definisce l'enum, il che significa che la definizione enum deve essere spostata dal assembly che usa, ad esempio .exe, a qualcosa a cui fa riferimento tutti gli assembly.

C'è un modo per avere diverse classi derivate da EventSource in un'applicazione che utilizza ancora la stessa ETS EventSource? O quale sarebbe un buon modo per implementare la registrazione semantica con ETW in uno scenario come questo, quando è indesiderabile introdurre un sacco di nuove dipendenze per creare la tua classe di log?

+0

io di solito uso un GUID univoco, un unico codice categoria di registrazione, con un enum unico (che definisce dire "una componente di registrazione") più una TraceLevel (errore, avvertimento, informazioni, etc.). Quindi, il metodo Log può utilizzare cool [CallerMemberName] in modo da impostare automaticamente il nome del metodo tracciato. Questo crea solo un riferimento a una classe comune (che puoi anche condividere con un link sorgente in Visual Studio se non vuoi un riferimento a un assembly solido). –

+0

@SimonMourier Questo funzionerebbe per i log "generici", ma non sembra funzionare bene per la registrazione semantica? – DeCaf

+0

sì, quello era più un commento :) –

risposta

0

ci sono tre strategie:

  1. Creare un assieme che contiene solo classe derivata EventSource che definisce gli eventi per tutte le applicazioni. Aggiungi riferimento a quell'assieme a tutti i progetti richiesti. Per semplicità, puoi avvolgerlo in un pacchetto nuget.
  2. Creare un progetto di test con una sola classe derivata da EventSource. Usalo solo a scopo di validazione. Copia questa classe per tutti i progetti richiesti. Questa è fondamentalmente la stessa soluzione ma senza dipendenze binarie.
  3. Creare una nuova classe derivata da EventSource per ciascun progetto, ma specificare lo stesso attributo Guid per loro. In questo caso è necessario assicurarsi che tutte le origini di eventi abbiano la stessa dichiarazione per gli eventi sovrapposti (con lo stesso ID). E in questo caso devi scrivere alcuni strumenti di fusione manifest per produrre manifest combinati.
+0

Nessuno di questi è tutto ciò che è attraente, ma immagino che l'opzione 3 ° sopra almeno risponda alla mia domanda; è possibile, ma non senza molto lavoro. :/ – DeCaf

+0

Mentre speravo davvero di implementare la soluzione 3 sopra, sembra che non funzioni. Poiché non è possibile creare due istanze di una classe EventSource con lo stesso GUID, verrà generato un evento di errore che dice 'ERRORE: Eccezione nell'elaborazione comandi per EventSource XXXX: un'istanza di EventSource con Guid c64e6d39-ff1f-4620-8041-e3f9cca908c9 già esistere. :( – DeCaf

0

Attenzione, le classi EventSource devono essere sigillate! Se si desidera utilizzare l'iniezione di dipendenza utilizzando EventSource, c'è una soluzione ...

Definire una semplice interfaccia:

// 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); 
} 

e l'implementazione (implementazione dell'interfaccia deve essere decorato con la 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); 
    } 
} 

ora è possibile iniettare la classe di registrazione ^^

0

I usua fatelo in modo che ci sia una separazione delle interfacce anche se usano una singola istanza di una fonte di eventi. Nel mio codice ioc tutto con ISingletonDependency sono registrati come singleton. Quindi puoi chiamare le interfacce con metodi molto specifici ma sono sempre la stessa EventSource.

Spero che questo aiuti.

public MyCompanyEventSource: IMyCompanyEventSource, ISingletonDependency{ 
} 
public IMyCompanyEventSource: IComponentLogger1, IComponentLogger2, IComponentLogger3{ 
} 
public Component1{ 
     public Component1(IComponentLogger logger){ 
     } 
    } 
Problemi correlati