Un custom provider per Health Monitoring con output in formato RSS

di Marco Leoncini, in UserScript, ASP.NET 2.0, web.config,

Il sistema di Health Monitoring di ASP.NET 2.0 mette a disposizione un nutrito set di provider, progettati per processare i WebEvent generati a runtime.
Eccone una lista:
- EventLogWebEventProvider
- SqlWebEventProvider
- WmiWebEventProvider
- SimpleMailWebEventProvider
- TemplatedMailWebEventProvider
- TraceWebEventProvider

Se nessuno dei provider riuscisse a coprire i nostri requisiti, scrivendo una classe che erediti da WebEventProvider o BufferedWebEventProvider potremmo crearne uno personalizzato.
La scelta della classe base può ricadere su BufferedWebEventProvider, in modo da utilizzare il buffer del sistema di Health Monitoring per memorizzare i WebEvent prima del loro salvataggio, altrimenti si può usare la classe base WebEventProvider.

Il nostro obiettivo è scrivere un semplice provider per la memorizzazione dei WebEvent in un log conforme al formato RSS.

Creiamo una libreria di classi e aggiungiamo una classe che chiameremo RssProvider.
Per prima cosa, eseguiremo l'override del metedo Initialize, il quale riceve come argomento la collezione di impostazioni "config", dichiarate nella sezione di configurazione provider del web.config.
Affinché il runtime non generi un'eccezione, una volta recuperate le informazioni è necessario rimuovere dalla collezione config i valori appena letti, funzione affidata al metodo metodo FindEndDelete.

private void FindEndDelete(System.Collections.Specialized.NameValueCollection config)
{
  //recupero gli elementi dal config
  RssPath = config.Get("rssLogPath");
  RssTitle = config.Get("rssTitle");
  RssLink = config.Get("rssLink");
  RssDescrption = config.Get("rssDescription");
  RssLanguage = config.Get("rssLanguage");
  RssGenerator = config.Get("rssGenerator");
  RssManagingEditor = config.Get("rssManagingEditor");
  RssWebMaster = config.Get("rssWebMaster");
  RssCopyright = config.Get("copyright");

  //li rimuovo dalla collezione
  config.Remove("rssLogPath");
  config.Remove("rssTitle");
  config.Remove("rssLink");
  config.Remove("rssDescription");
  config.Remove("rssLanguage");
  config.Remove("rssGenerator");
  config.Remove("rssManagingEditor");
  config.Remove("rssWebMaster");
  config.Remove("rssCopyright");
}

Il passo successivo è eseguire l'override del metodo ProcessEvent, che viene richiamato quanto il runtime, un controllo utente o del codice custom generano un WebEvent.
Per prima cosa controlleremo se il provider è impostato per sfruttare un buffer e in caso affermativo richiameremo l'implementazione base del metodo, altrimenti le informazioni trasportate dal WebEvent verranno immediatamente scritte nel file XML:

public override void ProcessEvent(WebBaseEvent eventRaised)
{
  //se il provider usa il buffer
  if (UseBuffering)
  {
    //richiama implementazione classe base
    //che bufferizza l'evento
    base.ProcessEvent(eventRaised);
  }
  else
  {
    //creo una nuova lista di eventi
    List<WebBaseEvent> listevent = new List<WebBaseEvent>();

    //inserisco nella collezione l'evento appena generato
    listevent.Add(eventRaised);

    //scrivo nel file
    SaveToRss(listevent);
  }
}

Infine eseguiremo l'override del metodo ProcessEventFlush, il quale viene richiamato quando il buffer deve essere svuotato.
Il metodo SaveToRss si occuperà infine di memorizzare nel file XML i WebEvent rimossi dal buffer scorrendo la lista che riceve come argomento.

private void SaveToRss(ICollection eventCollection)
{
  //creo un nuovo XmlDocument
  XmlDocument document = new XmlDocument();
  //carico il file xml
  document.Load(path);
  //creo un nuovo XPathNavigator
  XPathNavigator navigator = document.CreateNavigator();
  //mi muovo
  navigator.MoveToChild("rss", "");
  navigator.MoveToChild("channel", "");
  //recupero un writer
  XmlWriter writer = navigator.AppendChild();
  CultureInfo cultureInfo = new CultureInfo("en-US");
  foreach (WebBaseEvent we in eventCollection)
  {
    writer.WriteStartElement("item");
    writer.WriteElementString("title", we.Message);
    writer.WriteElementString("link", string.Empty);
    writer.WriteElementString("pubDate", we.EventTime.ToString("r",cultureInfo.DateTimeFormat));
    writer.WriteElementString("description", we.ToString(false,true));
    writer.WriteEndElement();
  }
  writer.Flush();
  writer.Close();
  document.Save(path); 
}

Compilata la libreria di classi in una dll e copiata nella cartella bin, aggiungiamo le seguenti righe nel web.config per configurare il nostro provider:

<healthMonitoring enabled="true">
  <providers>
    <clear/>
     <add
       name="MyRssProvider"
       type="MyHealthMonitoring.RssProvider"
       bufferMode="BufferRss"
       buffer="true"
         rssLogPath="~/log/log2.xml"
      rssTitle="Log"
      rssLink="https://www.aspitalia.com"
      rssDescription="eventi registrati"
      rssLanguage="it-it"
      rssGenerator="RSS generato da RssProvider"
      rssManagingEditor="my@mysite.com"
      rssWebMaster="webMaster@mysite.com"
      rssCopyright="copyright"/>
  </providers>
<!-- impostazioni del buffer -->
  <bufferModes>
    <clear/>
    <add name="BufferRss" maxBufferSize="100" maxBufferThreads="1" regularFlushInterval="00:01:00" maxFlushSize="10" urgentFlushThreshold="10" urgentFlushInterval="00:00:30"/>
  </bufferModes>
<!-- mapping degli eventi -->
  <eventMappings>
    <clear/>
    <add name="Application Event" type="System.Web.Management.WebApplicationLifetimeEvent"/> <!-- startup/shutdown dell'app -->
    <add name="Generic Event" type="System.Web.Management.WebErrorEvent" /> <!-- errore generico -->
  </eventMappings>
<!-- mappe delle regole -->
  <rules>
    <clear/>
    <add eventName="Generic Event" provider="MyRssProvider" name="RSSRules 1"/>
    <add eventName="Application Event" provider="MyRssProvider" name="RSSRules 2"/>
  </rules>
</healthMonitoring>

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi