Dicas do Log ULS
Dicas do Log ULS
ATUALIZAÇÃO 2-4-2011: recomendo que seja observado o exemplo atualizado em https://blogs.msdn.com/b/sharepoint_br/archive/2011/03/21/dicas-de-log-uls-servi-231-o-de-log-unificado-parte-2.aspx . O novo exemplo é melhor e mais funcional.
Quando adicionei um log ULS a um projeto recente, observei um pequeno efeito colateral irritante. Nos logs ULS, a Área estava aparecendo como “Desconhecida”. Percebo que alguns aspectos foram abordados em outros locais, mas eu gostaria de fazer uma postagem rápida que descrevesse o que eu acho que seja o forma mais rápida de lidar com isso (certamente muito menos complicado do que outras soluções descritas anteriormente). Algo que vale a pena ressaltar é que se você não quiser fazer isso, acredito que o Framework de Log que a equipe de práticas recomendadas colocou no CodePlex pode fazer isso por si mesmo. Mas eu geralmente escrevo meu próprio código sempre que possível, portanto, vou descrever resumidamente a solução aqui.
A primeira coisa a se notar é que a maior parte da documentação de SDK trabalha com a noção de criar uma nova SPDiagnosticsCategory. O construtor de uma nova instância da classe permite que você forneça o nome Categoria, e quando fizer isso, você definitivamente verá qualquer nome Categoria personalizado que deseja usar aparecendo no log ULS na coluna Categoria. Na maioria dos casos, se estiver fazendo seu próprio log personalizado, você também desejará ter uma Área personalizada junto com a(s) sua(s) Categoria(s) personalizada(s). Infelizmente, o SDK faz com que você faça um exercício consideravelmente mais complicado para conseguir que isso aconteça, pois você não pode usar um construtor simples para criar uma nova Área e usá-la. Você precisa escrever a sua própria classe que deriva de SPDiagnosticsServiceBase.
A forma que escolhi para implementar tudo foi criar um arquivo CS que contenha minha classe de log e minha classe de base de serviço de diagnóstico. Começarei primeiro com a classe de base de diagnóstico abaixo. Colei a classe inteira e depois vou percorrer os aspectos que vale a pena observar:
public class SteveDiagnosticService : SPDiagnosticsServiceBase
{
private const string LOG_AREA = "Steve Area";
public enum LogCategories
{
SteveCategory
}
public SteveDiagnosticService()
: base("Steve Diagnostics Service", SPFarm.Local)
{
}
public SteveDiagnosticService(string name, SPFarm parent)
: base(name, parent)
{
}
protected override bool HasAdditionalUpdateAccess()
{
return true;
}
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()
{
List<SPDiagnosticsCategory> categories = new List<SPDiagnosticsCategory>();
categories.Add(new SPDiagnosticsCategory(
LogCategories.SteveCategory.ToString(),
TraceSeverity.Medium, EventSeverity.Information));
SPDiagnosticsArea area = new SPDiagnosticsArea(
LOG_AREA, 0, 0, false, categories);
List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>();
areas.Add(area);
return areas;
}
}
Observemos as partes interessantes agora:
private const string LOG_AREA = "Steve Area";
Aqui é onde defino o nome da Área que vou gravar no log ULS.
public enum LogCategories
{
SteveCategory
}
Esta é a lista Categorias que vou adicionar à minha Área personalizada. Neste caso, tenho apenas uma categoria que vou usar com esta Área, mas se quiser várias categorias, basta que você expanda o conteúdo desta enumeração.
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);
}
}
Este é um dos dois métodos importantes de implementação, onde realmente gravamos o log ULS. A primeira linha é onde obtenho a SPDiagnosticCategory e faço referência à Área que ela pertence quando faço isso. Na segunda linha, estou apenas chamando o método de classe base na classe SPDiagnosticsServiceBase local para gravar no log ULS e como parte disso passo a minha Categoria que é associada à minha Área.
protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
List<SPDiagnosticsCategory> theCategories = new List<SPDiagnosticsCategory>();
theCategories.Add(new SPDiagnosticsCategory(
LogCategories.SteveCategory.ToString(),
TraceSeverity.Medium, EventSeverity.Information));
SPDiagnosticsArea theArea = new SPDiagnosticsArea(
LOG_AREA, 0, 0, false, theCategories);
List<SPDiagnosticsArea> theArea = new List<SPDiagnosticsArea>();
theArea.Add(area);
return theArea;
}
Nesta substituição, retorno para o SharePoint todas as minhas Áreas personalizadas. Neste caso, vou usar somente a minha Área, portanto, isso é tudo que envio de volta. Além disso, como mencionado acima, estou usando apenas uma Categoria personalizada com a minha Área. Se eu quisesse usar várias Categorias personalizadas, 1) adicionaria elas à enumeração descrita anteriormente e 2) adicionaria cada uma à minha instância da Lista theCategories que defini neste método.
Esta é a principal mágica por trás da adição de uma Área personalizada e fazer com que ela apareça na coluna apropriada nos logs ULS. A implementação da classe de log é muito direta também. Vou colar a parte principal dela aqui e explicarei um pouco mais:
public class Log
{
private const int LOG_ID = 11100;
public static void WriteLog(string Message, TraceSeverity TraceLogSeverity)
{
try
{
//in this simple example, I’m always using the same category
//you could of course pass that in as a method parameter too
//and use it when you call SteveDiagnosticService
SteveDiagnosticService.Local.LogMessage(LOG_ID,
SteveDiagnosticService.LogCategories.SteveCategory,
TraceLogSeverity, Message, null);
}
catch (Exception writeEx)
{
//ignore
Debug.WriteLine(writeEx.Message);
}
}
}
Este código é muito fácil de implementar entre os meus métodos aos quais faço referência. Já que WriteLog é um método estático, meu código é apenas Log.WriteLog(“This is my error message”, TraceSeverity.Medium); por exemplo. Neste exemplo, no ULS, é criada uma entrada na Área “Steve Area” e a Categoria “SteveCategory” com a mensagem “This is my error message (Esta é a minha mensagem de erro)”.
Esta é uma postagem de blog localizada. O artigo original está em Tips for ULS Logging