Советы по ведению журналов ULS, часть 2
Советы по ведению журналов ULS, часть 2
В 1-й части советов по ведению журналов ULS (https://blogs.msdn.com/b/sharepoint_ru/archive/2011/03/21/uls.aspx) я представил код для добавления настраиваемой области ведения журналов ULS и показал, как использовать его в проекте. После работы с этим кодом я заметил несколько вещей:
1. В предыдущей части был код, который не соответствовал последнему пакету SDK, — по сути, некоторые фрагменты кода, реализованные в соответствии с SDK, оказались излишними, а кое-что из сделанного отличалось от примера в SDK (который, кстати, следует обновить — я поработаю над этим отдельно).
2. Ведение журнала осуществляется только в случае, если задать для TraceSeverity значение "Medium"; другого эффективного способа на других уровнях трассировки не было.
3. Больше всего раздражало, что когда я пытался вызвать свой класс, необходимый для настраиваемой области, он выполнялся с ошибкой, если ведение журнала происходило во время действий, связанных с запросом POST. Код вызывал знакомую ошибку — невозможность обновить SPWeb во время запроса POST, если для значение свойства AllowUnsafeUpdates не было задано значение true. Задание этого значения в SPWeb во время события журнала, чтобы оно работало, казалось безрассудной идеей (приношу мои извинения всем безрассудным людям). Поэтому я решил, что есть метод получше.
В этой записи блога я собираюсь улучшить предыдущий пример и добавить в него новый код. Вот что я хочу показать:
1. Улучшенный класс для настраиваемой области — в этой версии произведены некоторые сокращения.
2. Интеграция с настройкой средств сбора данных диагностики в разделе "Мониторинг" центра администрирования. Эта интеграция позволит в дальнейшем обеспечить поддержку настройки уровней трассировки в настраиваемой области и категории.
3. Сведения о регистрации — очень простой способ регистрировать и отменять регистрацию настраиваемого класса ведения журнала ULS, поэтому его можно интегрировать с центром администрирования и можно удалить из центра администрирования.
Для начала рассмотрим новую упрощенную версию класса. Она многим похожа на класс из первой части записи блога, но поменьше и попроще. Вот как выглядит этот класс теперь:
[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)
});
}
}
Вот важные изменения по сравнению с первой версией:
1. Атрибут Guid добавлен в класс:
[Guid("833B687D-0DD1-4F17-BF6A-B64FBC1AC6A8")]
Я добавил атрибут Guid в класс, так как он требуется SharePoint для его уникальной идентификации в базе данных конфигурации.
2. Изменен конструктор по умолчанию:
public SteveDiagnosticService()
{
}
Теперь это просто стандартный пустой конструктор. Раньше я вызывал другую перегрузку конструктора, который принимает имя службы и параметр SPFarm. Просто стало меньше кода, что хорошо.
3. Удалена перегрузка метода HasAdditionalUpdateAccess. Опять же, я фактически не использовал эту перегрузку, поэтому, следуя девизу "меньше, но лучше", я удалил ее.
4. Значительно укорочен метод ProvideAreas; теперь он соответствует шаблону, который используется в пакете 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)
});
Это решило 1-ю проблему, описанную выше — теперь мой код стал немного понятнее. Другие проблемы (отсутствие уровней трассировки, вызов исключения при ведении журнала во время запроса POST и интеграция с центром администрирования) были устранены дальнейшим улучшением и регистрацией кода. Пример в пакете SDK, касающиеся этой области, довольно слаб, но мне удалось заставить его делать, что нам нужно. Для простоты я создал новый компонент для моей сборки с настраиваемым классом ULS, описанным выше. Я добавил приемник компонентов, регистрирую настраиваемую сборку ULS в течение события FeatureInstalled и отменяю ее регистрацию в течение события FeatureUninstalling. Это довольно хорошее решение в моем случае, так как я сделал свой компонент компонентом в области фермы, поэтому он автоматически активируется при добавлении и развертывании решения. Как оказалось, код для регистрации и отмены регистрации неприлично прост:
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);
}
}
Еще один момент, который я хотел бы отметить, состоит в том, что мне удалось указать ссылку на "SteveDiagnosticService", потому что я: а) добавил ссылку на сборку с моим настраиваемым классом в проект, в котором размещен компонент; и б) я добавил оператор using в класс приемника компонентов для сборки с моим настраиваемым классом ведения журнала.
Регистрируя свой настраиваемый класс ведения журнала ULS, я получаю множество преимуществ:
· Ошибки, связанные с проблемами обновления SPWeb при записи в журнал ULS во время запроса POST, больше не возникают.
· Настраиваемая область и категория ведения журнала отображаются в центре администрирования, поэтому я могу зайти в раздел "Настройка средств сбора данных диагностики" и изменить уровень трассировки и событий. Например, если по умолчанию задан средний уровень трассировки, все операции записи в журнал с параметром TracingSeverity.Medium записываются в журнал, но операции с параметром TracingSeverity.Verbose не записываются. Если мне нужно записывать записи с уровнем TracingSeverity.Verbose в журнал, я просто захожу в раздел "Настройка средств сбора данных диагностики" и изменяю уровень трассировки на "Подробно".
Итоговое решение получилось проще и функциональнее. Я думаю, что это одна из тех беспроигрышных штук, о которых я все время слышу.
П. С. Я хочу заявить свой протест относительно Ламаркуса Олдриджа из команды Портланд Трейлблейзерс. То, что он не попал в команду всех звезд западной конференции НБА, трагическая нелепость. Ладно, достаточно личных комментариев, я знаю, что вам всем нужны по-настоящему полезные сведения. Надеюсь, эта статья вам пригодится.
Это локализованная запись блога. Исходная статья доступна по адресу Tips for ULS Logging Part 2