Compartilhar via


Советы по ведению журналов 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