Dicas de Log ULS (Serviço de Log Unificado) parte 2
Dicas de Log ULS (Serviço de Log Unificado) parte 2
Na parte 1 das dicas de Log ULS (https://blogs.msdn.com/b/sharepoint_br/archive/2011/03/21/dicas-do-log-uls.aspx) incluí um código para adicionar uma área de log ULS personalizada e demonstrei como usá-la em seu projeto. Depois de trabalhar um pouco nela, observei algumas coisas:
1. Havia algum código lá que não era compatível com o SDK mais recente. Basicamente algumas partes do código implementadas que o SDK considerava desnecessárias e algumas coisas que eu estava fazendo de forma um pouco diferente do exemplo do SDK (que, a propósito, precisa ser atualizado e trabalharei nisso separadamente).
2. O log só ocorreria quando eu definisse TraceSeverity como Médio; não havia uma forma efetiva de colocar em camadas os diferentes níveis de rastreamento.
3. A parte muito mais chata é que, quando eu tentava invocar a classe personalizada necessária para a minha Área personalizada, ela falhava quando eu tentava gerar qualquer log durante uma atividade de POST. Ocorria o erro muito comum relacionado à impossibilidade de atualizar um SPWeb durante um POST a não ser que propriedade AllowUnsafeUpdates fosse definida como verdadeira. Defini-la em um SPWeb durante um evento de log, apenas para fazer meu evento de log funcionar, parecia totalmente insano (minhas desculpas para as pessoas insanas, a propósito). Então, decidi que deveria haver uma forma muito melhor.
Nesta postagem, vou aprimorar o exemplo anterior. Aqui está o que vamos mostrar:
1. Uma classe aprimorada da Área personalizada. Na verdade, ela está um pouco menor nesta versão.
2. Integração com Configurar log de diagnóstico na seção Monitoramento da Administração Central. Esta integração permitirá maior suporte para a configuração de níveis de rastreamento na Área e Categoria personalizadas.
3. Informações de registro: uma forma muito simples de registrar e cancelar o registro da classe de log ULS personalizada de forma que ela se integre à Central de Administração e possa ser removida da Central de Administração.
Para começar, vamos observar a nova versão simplificada da classe. Existem muitas semelhanças entre esta e a versão que mostrei na primeira postagem, mas esta é um pouco mais resumida e simples. Veja como ela está agora.
[Guid("833B687D-0DD1-4F17-BF6A-B64FBC1AC6A8")]
public class SteveDiagnosticService : SPDiagnosticsServiceBase
{
private const string LOG_AREA = "Steve Area";
public enum LogCategories
{
SteveCategory
}
public SteveDiagnosticService()
{
}
public SteveDiagnosticService(string name, SPFarm parent)
: base(name, parent)
{
}
public static SteveDiagnosticService Local
{
get
{
return SPDiagnosticsServiceBase.GetLocal<SteveDiagnosticService>();
}
}
public void LogMessage(ushort id, LogCategories LogCategory,
TraceSeverity traceSeverity, string message,
params object[] data)
{
if (traceSeverity != TraceSeverity.None)
{
SPDiagnosticsCategory category
= Local.Areas[LOG_AREA].Categories[LogCategory.ToString()];
Local.WriteTrace(id, category, traceSeverity, message, data);
}
}
protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
yield return new SPDiagnosticsArea(LOG_AREA, 0, 0, false,
new List<SPDiagnosticsCategory>()
{
new
SPDiagnosticsCategory(LogCategories.AzureConfig.ToString(),
TraceSeverity.Medium, EventSeverity.Information, 1,
Log.LOG_ID)
});
}
}
Aqui estão as alterações importantes em relação à primeira versão:
1. O atributo Guid foi adicionado à classe:
[Guid("833B687D-0DD1-4F17-BF6A-B64FBC1AC6A8")]
Adicionei um atributo Guid à classe porque o SharePoint necessita dele para identificá-lo de forma exclusiva no banco de dados de configuração.
2. O construtor padrão foi alterado:
public SteveDiagnosticService()
{
}
Agora ele é apenas um construtor padrão vazio. Antes eu chamava a outra carga do construtor que leva um nome do serviço e um SPFarm. Menos código é tudo o que basta, o que é muito bom quando você consegue fazer.
3. A substituição de HasAdditionalUpdateAccess foi excluída. Novamente, descobri que não a estava usando, portanto, continuando com a máxima menos é mais, eu a removi.
4. O método ProvideAreas foi reduzido significativamente. Agora ele segue o mesmo padrão usado no SDK:
yield return new SPDiagnosticsArea(LOG_AREA, 0, 0, false,
new List<SPDiagnosticsCategory>()
{
new
SPDiagnosticsCategory(LogCategories.AzureConfig.ToString(),
TraceSeverity.Medium, EventSeverity.Information, 1,
Log.LOG_ID)
});
Tudo foi para tratar do problema número 1 acima. Meu código agora está um pouco mais limpo e significativo. Outros problemas, como os níveis de rastreamento que geravam uma exceção ao criarem um log durante um POST e a integração com a administração central foram finalmente corrigidos ao detalhar mais o código e registrá-lo. O exemplo do SDK no momento está um pouco fraco nessa área mas consegui fazer o que eu queria. Para simplificar as coisas, criei um novo recurso para o meu assembly que contém minha classe ULS personliazada descrita acima. Adicionei um receptor de recursos. Registro o assembly ULS personalizado durante o evento FeatureInstalled e cancelo o registro dele durante o evento FeatureUninstalling. Esta foi uma boa solução no meu caso porque meu recurso ficou no escopo do Farm de forma que seja ativado automaticamente quando a solução é adicionada e implantada. Como parece, o código para registrar e cancelar o registro é extremamente simples; aqui está:
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
try
{
SteveDiagnosticsService.Local.Update();
}
catch (Exception ex)
{
throw new Exception("Error installing feature: " + ex.Message);
}
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
try
{
SteveDiagnosticsService.Local.Delete();
}
catch (Exception ex)
{
throw new Exception("Error uninstalling feature: " + ex.Message);
}
}
A outra coisa a ser mostrada aqui é que eu consegui fazer referência a “SteveDiagnosticService” porque a) adicionei uma referência ao assembly com minha classe de registro personalizada em meu projeto, onde empacotei o recurso e b) adicionei uma declaração de uso à classe receptora do meu recurso do assembly com minha classe de registro personalizada.
Registrando minha classe de registro ULS obtenho vários benefícios:
· Não obtenho mais erros sobre problemas de atualização do SPWeb quando escrevo o log ULS durante um POST
· Minha Área e Categoria de log personalizadas aparece na administração central, sendo assim, posso ir para Configurar log de diagnóstico e alterar o nível de evento e de rastreamento. Por exemplo, quando está no nível de rastreamento padrão Médio, todas as minhas gravações ULS no log que são TracingSeverity.Medium são gravadas no log, mas as que são TracingSeverity.Verbose não são. Se eu quiser que as minhas entradas TracingSeverity.Verbose comecem a aparecer no log, simplesmente vou para Configurar log de diagnóstico e altere o nível de Rastreamento para Detalhado.
Em geral, a solução é mais simples e mais funcional. Acho que esta é uma daquelas situações ganhar ou ganhar que sempre ouço.
Obs. Eu gostaria de registrar meu voto de protesto aqui para LaMarcus Aldridge do Portland Trailblazers. Ele não ter conseguido entrar no time das Estralas da NBA da Conferência Oeste foi realmente estúpido. Chega de comentários pessoais! Eu sei que você quer encontrar aqui informações concretas sobre o sobre Share-n-Dipity. Espero que isso seja útil.
Esta é uma postagem de blog localizada. O artigo original está em Tips for ULS Logging Part 2