Советы по ведению журналов ULS
Советы по ведению журналов ULS
Обновление от 04.02.2011: я рекомендую взглянуть на обновленный пример по адресу https://blogs.msdn.com/b/sharepoint_ru/archive/2011/03/21/uls-2.aspx . Он лучше и функциональнее.
Когда я добавил функции ведения журнала ULS в последний проект, я заметил один раздражающий побочный эффект. В журналах ULS область отображается как "Неизвестное". Я понимаю, что некоторые аспекты этой проблемы описаны в других материалах, но я просто хотел написать короткую запись блога с описанием самого простого способа устранения этой проблемы (определенно менее болезненного, чем другие известные мне решения). Следует отметить, что если вы вообще не хотите этим заниматься, в платформе Logging Framework, в которой применяются рекомендации группы разработчиков CodePlex, это проблема решается автоматически. Но обычно я пишу как можно больше собственного кода, поэтому я кратко опишу способ устранения проблемы.
Первое, что я заметил — то, что в большей части документации пакета SDK создается новый объект SPDiagnosticsCategory. Конструктор нового экземпляра класса позволяет указать имя категории, а при этом любое пользовательское имя категории, которое нужно использовать, записывается в журнал ULS в столбце "Категория". В большинстве случаев при написании собственной функции ведения журнала также требуется настраиваемая область для своих категорий. К сожалению, SDK заставляет выполнить гораздо более сложную задачу для реализации такого механизма, так как нельзя использовать простой конструктор для создания новой области и ее применения — необходимо написать собственный класс, производный от SPDiagnosticsServiceBase.
Я решил создать один CS-файл с классом ведения журнала и базовым классом службы диагностики. Я начну с базового класса диагностики — далее я вставил весь класс. После него я опишу самые важные сведения о нем:
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;
}
}
Рассмотрим самые интересные части:
private const string LOG_AREA = "Steve Area";
Здесь я определяю имя области, которое я запишу в журнал ULS.
public enum LogCategories
{
SteveCategory
}
Это список категорий, которые я добавлю в настраиваемую область. В этом случае у меня только одна категория, которая будет использована в этой области, но если нужно несколько категорий, просто расширьте это перечисление.
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);
}
}
Это один из двух важных методов, которые мы реализуем — здесь производится запись в журнал ULS. В первой строке я получаю объект SPDiagnosticCategory и указываю ссылку на область, которой он принадлежит. Во второй строке я просто вызываю метод базового класса в классе SPDiagnosticsServiceBase для записи в журнал ULS и при этом передаю категорию, связанную с областью.
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;
}
В этой перегрузке я возвращаю в SharePoint все настраиваемые области. В этом случае я использую только одну область, поэтому ее и возвращаю. Кроме того, как я упомянул выше, я использую в области только одну собственную категорию. Если бы требовалось несколько настраиваемых категорий, то я 1) добавил бы их в перечисление, описанное ранее и 2) добавил каждую из них в экземпляр списка theCategories, определенный в этом методе.
Вот, в принципе, и вся суть добавления настраиваемой области и ее отображения в соответствующем столбце в журналах ULS. Реализация класса ведения журнала также довольно простая, я вставлю основную часть здесь и опишу ее чуть дальше.
public class Log
{
private const int LOG_ID = 11100;
public static void WriteLog(string Message, TraceSeverity TraceLogSeverity)
{
try
{
//в этом примере я всегда использую одну и ту же категорию
//ее можно было бы, конечно, передать также в параметр метода
//и использовать при вызове SteveDiagnosticService
SteveDiagnosticService.Local.LogMessage(LOG_ID,
SteveDiagnosticService.LogCategories.SteveCategory,
TraceLogSeverity, Message, null);
}
catch (Exception writeEx)
{
//игнорировать
Debug.WriteLine(writeEx.Message);
}
}
}
Этот код легко реализуется в любом из методов, в которых есть ссылка на него. Так как WriteLog — это статический метод, мой код,например, будет следующим: Log.WriteLog(“This is my error message”, TraceSeverity.Medium); . В этом примере в журнале ULS создается запись в области "Steve Area" и категория "SteveCategory" с сообщением "This is my error message".
Это локализованная запись блога. Исходная статья доступна по адресу Tips for ULS Logging