уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

После выхода RAD Studio XE в составе меню «Tools» появился ещё один инструмент для разработчика — CodeSite. Что такое CodeSite? Это система журналирования (logging system), которая позволяет вести удобный и, главное, максимально информативный лог работы приложения. Думаю, что когда-либо перед любым разработчиком встает вопрос о том, каким образом отслеживать работу своего продукта, как на этапе его разработки, так и после релиза, когда программой во всю используют другие люди. Соответственно, до RAD Studio XE, многие могли начать изобретать свой собственный «велосипед» — «движок для логирования» собственного производства. Может быть такой подход и оправдан в какой-то мере, но всё-таки имеет много недостатоков, например:

  1. Лишняя трата времени на разработку своей системы логирования. Вместо того, чтобы заниматься непосредственно работой по улучшению функциональности программы, исправлению ошибок и т.д. приходится «зависать» над разработкой модуля/компонента/библиотеки, которая будет использоваться исключительно в служебных целях, т.е. для рядового пользователя практически бесполезной.   Можно, конечно, максимально сократить время разработки и просто «втупую» писать в лог-файл всё подряд, но тут мы получим второй недостаток.
  2. Малая информативность. Здесь речь скорее не об объеме информации, а о её содержании и оформлении. Можно сделать в своей системе какой-нибудь шаблон записи типа «Дата — Действие — Результат» и по такому шаблону писать весь лог. Вроде бы быстро и просто, но потом как такой файл анализировать? Особенно учитывая то, что чаще всего смотреть лог в таких случаях приходится из txt-файлика. Когда объем небольшой, то вроде бы и не сложно, а если лог за целый день работы? Или за неделю?

В принципе, эти два недостатка и сподвигли меня уделить пару часиков своего времени на то, чтобы изучить работу инструмента CodeSite. Так как сейчас приходится успевать работать над двумя проектами, то тратить время на «велосипеды» совсем не хочется, тем более, что под рукой уже есть замечательное и эффективное решение от профессионалов.

Введение

Итак, что же такого интересного может предложить нам CodeSite?

CodeSite дает разработчику более полное понимание того, как выполняется его код. Благодаря имеющимся в составе продукта Viewer’ам, можно получить лог, который позволит с максимальной скоростью и удобством разобраться в том, что происходит в программе.  Можно «лёгким движением руки» (с) записать в лог целый объект и получать сведения по изменяющимся свойствам, быстро логировать работу сразу нескольких потоков в приложении, разделять сообщения по группам, свойствам, назначать сообщениям другие свойства (цвета шрифтов и фона), которые будут способствовать более комфортному и эффективному изучению лога. Но об этом чуть позже, а пока пару слов про viewer’ы в CodeSite.

Для просмотра логов мы можем использовать:

  • Live Viewer, который обновляется сразу же, после поступления новых сообщений в диспетчер сообщений. Этот вьювер очень удобно использовать на этапе разработки программы.
  • File Viewer — просмотрщик лог-файлов. Можно, например, долгое время записывать весь ход работы программы в отдельный файл, а потом, используя File Viewer просмотреть этот файл, отфильтровав сообщения по нескольким заданным критериям.

Кроме того, в состав CodeSite входит небольшая консольная утилита под названием CSFileExporter.exe, с помощью которой можно экспортировать лог-файл в другие форматы — XML, CSV, TSV.

От слов к делу. Посмотрим как работает CodeSite и, что мы можем сделать, используя бесплатную версию инструмента — CodeSite Express.

Первый лог с CodeSite. Использование класса TCodeSiteLogger.

Класс TCodeSiteLogger используется для отправки сообщений из программы в диспетчер CodeSite для дальнейшего их просмотра в одном из viewer’ов. Собственно, для нас этот класс будет основным. Класс содержится в модуле CodeSiteLogging, который необходимо подключить в uses того модуля работу которого мы будем логировать. Для наиболее общего использования возможностей этого класса от нас не требуется создавать собственные объекты, т.к. при инициализации модуля уже создается объект CodeSite: TCodeSiteLogger, который можно сразу же использовать. Однако никто нам и не запрещает сделать хоть 10 собственных объектов и работать с ними.

Для начала рассмотрим те методы класса, без которых лог — не лог. И первый метод:

procedure Send(const Msg: string ); overload;

Метод Send отправляет новое сообщение в логгер. Этот метод имеет несколько перегруженных вариантов, если быть точнее, то в CodeSite 5 (для Delphi XE2) содержится 39 вариантов метода Send, которые позволяют отправлять различные данные в логгер в их нативном формате. Например, следующий перегруженный метод:

CodeSite.Send('Main Form', Self);

Позволяет отправить сообщение, содержащее целиком весь объект формы. Другие варианты Send позволяют отправлять строки, числа, списки строк, картинки, иконки и т.д. В общем преобразования типов данных внутри кода программы нам вряд ли понадобится.

Для примера работы метода Send создадим новый проект Delphi, подключим в uses модуль CodeSiteLogging, бросим на форму кнопку и напишем на OnClick такой код:

  CodeSite.Send('Hello, CodeSite');//отправили строку
  CodeSite.Send('Form Height', Height);//отправили сообщение с числом
  CodeSite.Send(csmError, 'Сообщение типа "Ошибка"');

Теперь запустите программу и нажмите кнопку. Сразу же после нажатия кнопки запуститься Live Viewer, содержащий наши сообщения:

Как видите, то сообщение, для которого мы назначили иконку ошибки, выглядит иначе, чем два предыдущих сообщения. И надо сказать, что использование иконок — это конечно, мелочь, но эта мелочь очень неплохо повышает читабельность лога. Ведь согласитесь, что при просмотре лога первое, куда перемещается взгляд — на запись, которая выглядит «не так»? И тут главное не переборщить, чтоб лог не выглядел как новогодняя елка, иначе вся наглядность пойдет прахом.

Двигаемся далее по методам. Следующий метод:

  procedure Assert( Expression: Boolean; const Msg: string );

Этот метод проверяет выражение, записанное в Expression и, если оно равно False отправляет в логгер сообщение типа «Ошибка». На примере нашего приложения работу этого метода можно продемонстрировать так:

CodeSite.Assert(Height<Width, 'Высота окна больше его ширины')

Если высота окна будет больше ширины — в лог выведется строка, сообщающая нам об этом, иначе — сообщение об ошибке будет пропущено. Кстати, раз уж речь пошла про сообщения об ошибках и исключениях, то у TCodeSiteLogger для таких целей есть сразу два метода:

procedure SendError(const Msg: string); overload;
procedure SendException(E: Exception); overload;

Эти методы по части количества перегруженных версий не такие богатые как Send (всего по две версии), но зато сразу отправляют сообщение с необходимыми иконками. Перегруженные версии позволяют использовать в сообщениях шаблоны строк (аналогично CreateFmt у Exception). Сообщения, отправленные с помощью методов SendError и SendExceprion в Live Viewer выглядят следующим образом:

Следующие два метода позволяют нам записать в лог вход/выход из метода:

procedure EnterMethod( const MethodName: string ); overload; virtual;
procedure ExitMethod( const MethodName: string ); overload; virtual;

Использовать их можно так:

procedure TForm7.Button1Click(Sender: TObject);
begin
CodeSite.EnterMethod('Button1Click');
//Что-то тут делаем
CodeSite.ExitMethod('Button1Click');
end;

В этом случае мы получим вот такой лог работы программы:

Либо воспользоваться перегруженными версиями этих методов и передать в сообщении какой-нибудь объект:

procedure TForm7.Button1Click(Sender: TObject);
begin
CodeSite.EnterMethod(self,'Button1Click');
//Что-то тут делаем
CodeSite.ExitMethod(self,'Button1Click');
end;

В этом случае перед названием метода, которое мы передали во втором параметре также выведется и название объекта, т.е. лог будет выглядеть так:

Использование двух этих методов могут преследовать сразу две полезные задачи. Во-первых, использование Enter/ExitMethod повышает наглядность лога — в большом подробном логе сразу будет видно в каком методе что происходит. Во-вторых, используя функции viewer’а мы можем сворачивать все сообщения, находящиеся между блоками и, тем самым, быстро находить необходимую нам информацию в логе.

Вот, пожалуй, те методы, которые будут очень полезны и востребованы при логгировании работы программы. Это не все методы, которые имеются у класса TCodeSiteLogger. Есть так же и менее важные методы, например,

procedure AddCheckPoint;
procedure AddSeparator;

которые ещё больше повышают наглядность лога, но, не передают никакой информации о работе. Поэтому, если хотите, можете немного поэкспериментировать с различными методами класса и посмотреть, что в итоге получите в логе. А мы перейдем к следующей части статьи и рассмотрим свойства класса TCodeSiteLogger.

Свойства TCodeSiteLogger
Свойств у TCodeSiteLogger не много и все они, за исключением двух используются для повышения наглядности удобства чтения лога:

property Category: string;
property CategoryBackColor: Color;
property CategoryColor: TColor
property CategoryFontColor: TColor
property DateTimeFormat: string
property Destination: TCodeSiteDestination
property Enabled: Boolean;

Что касается первых пяти свойств, то тут лучше показать как они работают, чем рассказывать. Например, с помощью свойств Category, CategoryColor можно создать вот такой лог:

Обратите внимание — при использовании свойства Category мы получили не только то, что каждое сообщение в логе содержит строку в столбце Category, но также и разделение всего лога по вкладкам, где каждая вкладка содержит сообщения отдельной категории.

Свойство Destination используется для того, чтобы указать объекту где и как будут обрабатываться сообщения. Ниже будет показан пример того, как, используя свойство Destination можно записывать лог в отдельный файл. Например, мы можем создать несколько объектов для ведения лога и каждому из них назначить свою категорию, одному задать через Destination запись лога в файл, второму в Live Viewer и т.д.

Запись лога в файл

Когда мы разрабатываем программу, то, как уже было сказано выше, наиболее удобно и комфортно использовать возможности Live Viewer’а. Однако, когда программа уже разошлась по пользователям, то для ведения лога работы программы этот просмотрщик логов уже не подойдет — надо будет писать лог в файл. Для чтения лога из файла предназначен второй viewer — File Viewer. Как заставить его работать?

Во-первых, нам надо «сказать» логгеру (TCodeSiteLogger), что данные будут записываться в файл. Делается это следующим образом:

1. Создаем, например, на OnCreate формы объект типа TCodeSiteDestination и для него следующие свойства:

procedure TForm7.FormCreate(Sender: TObject);
var Dest: TCodeSiteDestination;
begin
  Dest:=TCodeSiteDestination.Create;
  Dest.LogFile.FilePath:=ExtractFilePath(Application.ExeName);
  Dest.LogFile.FileName:='Log.csl';
  Dest.LogFile.Active:=true;
end;

Таким образом мы указали, что лог будет содержаться в файле «Log.csl», который будет расположен в директории с программой. Теперь определим свойство Destination у CodeSite и запустим программу:

CodeSite.Destination:=Dest;

Можете закрыть Live Viewer, т.к. обновляться он не будет, а вместо этого открыть директорию с программой и убедиться, что по мере работы программы файл лога постепенно наполняется данными. В последствии, полученный лог можно будет открыть в File Viewer или добавить содержимое файла в Live Viewer.

При записи в файл Вы также можете указать ограничения на файл — максимальный размер в байтах или максимальное количество записей.
С записью в файл тоже вроде бы разобрались. Теперь более внимательно посмотрим на окно Viewer’а.

Работа с Live/File Viewer

Что касается работы с вьюверами, то тут, дума, для описания всех функций и возможностей даже в «урезанной» поставке CodeSite с RAD Studio XE2 не хватит ни сил не времени. Да и это, в принципе, незачем. Поэтому расскажу лишь про те функции, которые для меня сейчас наиболее полезны.

И первая функция — это сворачивание/разворачивание лога работы в отдельно методе. Как я уже говорил выше, для того, чтобы разграничить в логе места где выполняется како-либо код используются методы EnterMethod и ExitMethod. Для того, чтобы свернуть весь лог, находящийся между записями типа «вход/выход из метода» необходимо нажать Ctrl+Up или в выбрать в логе запись входа в метод и в контекстном меню нажать «Collapse Method«. Повторное нажатие Ctrl+Up развернет лог между метками входа/выхода. На рисунке ниже показан лог в котором часть сообщение «свернута»:

Как вы понимаете, функция сворачивания части лога будет очень полезна при работе с подробными логами работы, т.к. значительно облегчит поиск необходимой информации. Для работы же с самой информацией мне очень понравилась функция сравнения двух объектов одного типа. Работает она следующим образом.

На представленном выше рисунке Вы можете видеть, что в лог записывалась информация по объекту формы (Self). Если мы выберем в логе любую запись с этим объектом то в панели инспектора (справа) отобразятся все значения свойств этого объекта в момент отправки сообщения, т.е. инспектор будет выглядеть так:

Теперь зажимаем Ctrl и выбираем вторую запись с Self. В итоге в инспекторе будут отображены только те значения свойств, которые изменились:

Сразу видно, что у объекта сменились свойства ширины. По-моему отличная функция — экономит кучу времени при сравнении свойств объекта до и после какой-либо операции, а также помогает, в случае необходимости, быстро найти ошибки в работе и устранить их.

Вот пожалуй очень кратко о том, что за инструмент CodeSite и как им пользоваться. В заключение скажу, что после того как разобрался с работой CodeSite пожалел, что не использовал его ранее — инструмент очень даже неплохой, даже учитывая то, что это всего лишь Express-версия без таких «плюшек», как просмотр коллекция ScratchPad и т.д. По крайней мере, используя его для логирования работы программы для работы с Google Docs (а там и сетевые подключения и потоков куча) я не нашел к чему бы придраться. В общем, если Вам срочно нужна хорошая система логирования — используйте CodeSite.

 

Книжная полка

Описание Подробно рассматривается библиотека FM, позволяющая создавать полнофункциональное программное обеспечение для операционных систем Windows и OS X, а также для смартфонов и планшетных компьютеров, работающих под управлением Android и iOS
купить книгу delphi на ЛитРес
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес

 

5 1 голос
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
34 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
balmo
balmo
13/11/2011 00:17

Спасибо, очень полезно и актуально.

Важный вопрос: а можно ли настроить игнорирование вызов методов TCodeSiteLogger в Release-версии, подобно тому, как это реализовано для стандартных Assert (сомнительно, ну а вдруг)? Или же для этого придется применять условную компиляцию?

IL
IL
13/11/2011 02:04

Да, CodeSite очень хорош, не вижу причин его не использовать, разве что пока нет поддержки OS X, только Windows включая FireMonkey. После сессии Coderage6 было очень много вопросов. Кстати, Express можно обновить до полной версии CodeSite Studio по цене обновления. Хотя, только до конца ноября.
Влад, пожалуйста, проверьте пример «CodeSite.Assert(Height». По-моему, он сломался при вставке или форматировании.
P.S. Disclaimer: я не аффилирован с фирмой, просто инструмент понравился. Покупать для себя пока не вижу смысла, но может быть кому-то ссылка пригодится http://www.raize.com/DevTools/CodeRage6.asp

Slava
Slava
14/11/2011 13:54

> balmo
> а можно ли настроить игнорирование вызов методов TCodeSiteLogger

А TCodeSiteLogger.Enabled не подходит? 

balmo
balmo
14/11/2011 16:19

> Slava
Вызов стандартных команд Assert вообще не включаются в Release-версию (или при использовании $Assertions off). Это приятная особенность компилятора. В случае же TCodeSiteLogger.Enabled:=False вызовы все равно будут происходить и этот, по сути, отладочный код попадет в бинарник (хотя и не будет использоваться).

Собственно, вопрос был в том, что быть может CodeSite предоставляет какой-либо эксперт для автоматического заключения вызовов всех своих методов скажем в $IDDEF(CodeSite)…$ENDIF.

Slava
Slava
15/11/2011 10:55

> balmo

Да, это всё понятно. Просто, может быть, кому-то и это решение подходит.

Открыл для себя CodeSite только после этой статьи :) Огромное спасибо Автору!
Судя по всему методы TCodeSiteLogger потоконезависимы. Это огромный плюс. Хотя для себя пока не очень понял, как красиво структурировать логи, пишушие из разных потоков.

ЗЫ Пока доступен CodeSite из поставки Delphi XE, а там, например, нельзя написать CodeSite.Send(‘Main Form’, Self)

Slava
Slava
16/11/2011 10:07

> Vlad
> при логировании нескольких потоков можно каждому потоку назначить свою категорию и тогда можно будет лог отдельного потока читать на отдельной вкладке
Да, но! Для этого на каждый поток необходимо создавать по своему экземпляру TCodeSiteLogger.
Проверил, и это тоже отлично работает! Не вижу причин не использовать этот инструмент для ведения логов.
Единственный оставшийся вопрос — это вероятность порчи файла протокола…

Виталий
Виталий
18/11/2011 14:43

Спасибо за статью. Только из подобных статей я узнаю о всяких гженериках, кодесайтлоггерах и т.п. Прошу автора не стесняться и делиться своим опытом использования других инструментов/подходов в разработке. Даже если может показаться, что о них все знают. :)

Дима
Дима
09/12/2011 23:28

А можно дурацкий вопрос? Я новичок и не логировал ни когда, но идея очень классная и интересная. Спасибо за статью. А вопрос в следующем. В процессе разработки получится огромное кол-во кода вызовов логирования, «вычищать» код потом руками? или я не догнал чего-то…

Дима
Дима
10/12/2011 13:40

Влад, спасибо за ответ. А поясните тогда еще пожалуйста, как организовать логирование на клиенте? т.е. необходимо ему ставить CodeSite или как это происходит? извините если вопросы глупые…

Дима
Дима
10/12/2011 14:21

Все, растормозился… писать в файл, а потом смотреть… вот, что значит логами не занимался ни когда :)

Божко
17/12/2011 21:18

Спасибо, Влад.
У самого бы руки не дошли бы разобраться.
Хороший пост.

Сергей
Сергей
04/02/2012 00:25

Дмитрий, на вскидку что бы в будущем не выпиливать тонны кода вручную можно определить метод в котором будет проверка допустим на необходимость писать в лог или нет и соответственно сама запись. Тем самым мы введем дополнительную переменную писать нам лог или нет, а при записи будем вызывать наш метод.
Влад, спасибо за статью, да и не только эту, очень интересно и познавательно.

trackback

[…] логирование в процессе работы программы. Подробнее прочесть о Code Site вы можете в блоге WebDelphi.ru. Я же просто приведу сам […]

Владислав Иванов

Большое спасибо за поднятие темы. Сам я ещё под Delphi XE разобрался, как пользоваться CodeSite, так сказать, ради расширения кругозора. Хотелось бы добавить к вышеизложенному: на клиентских машинах можно ставить диспетчер, который будет собирать логи, а затем либо сохранять их в локальный файл, либо передавать по сети на заданный Вами адрес… Имхо, очень удобно для сбора логов (статистики крашей, ошибок) во время тестирования программы с привлечением большого количества народа. ;)
P.S. Может я немного неточно выразился… Подробная информация есть в самой справке к CodeSite. Изложено всё доступно и подробно, рекомендую почитать тем, кто хочет разобраться в нюансах.

Human Cat
Human Cat
27/02/2012 14:33

Наконец то появился логгер записи действий в программе, задолбало изобретать велосипед, я делаю все через dbgview, думаю может начать прикручивать эту штуку. Вроде удобная и объекты в лог кидает, чем самому логировать неизвестно что :)

skopas
skopas
08/03/2012 02:00

Подскажите пожалуйста как заставить работать логер на машине клиента, сделал все как в Вашем посте, на моей машине где установлен CodeSite работает все без проблем лог пишется в файл, но на машине клиента не создается и файл не пишится, подскажите куда копать. 

KingComp
14/04/2012 19:42

skopas, для того чтобы иметь возможность писать в лог-файл на машине клиента, необходимо положить файл «CSDispatcher.exe» рядом с исполняемым файлом вашего проекта. В этом случае диспетчер CodeSite запустится автоматически при попытке записать что-либо в лог-файл.

Vlad, большое тебе спасибо за познавательные статьи! В действительности так мало информации по Delphi XE2 в сети, ну и книг практически нет на русском языке. Учим английский. =)

KingComp
15/04/2012 00:09

А еще хотелось бы добавить следующее:
При завершении приложения, к примеру, в MainForm.Destroy, вписать CodeSite.CloseDispatcher.
Это остановит диспетчер CodeSite, т.е. закроет CSDispatcher.exe. Это необходимо проделывать, например, на клиентской машине, чтобы не висел в процессах этот файл.

KingComp
15/04/2012 20:47

Как сделать Add Reset Separate? В FileViewer эта возможность присутствует, но в Delphi нет его — это особенности не полной версии или как?
Допустим случай многократного вызова CodeSite.EnterMethod, после чего компьютер выключился (или еще чего) и не был вызван CodeSite.ExitMethod. В последующем при добавлении в лог записи будет уже все смещено вправо. Т.е. возмет последнюю позицию вхождений. Как реализовать все это «красиво»? Можно, конечно вызывать вначале CodeSite.ExitMethod несколько раз, но лог уже будет выглядеть не структурированным.

KingComp
15/04/2012 20:49

Нашел! CodeSite.AddResetSeparator.
Видимо мозг опух уже от этого огромного проекта.
 

Антон Белов
05/09/2012 16:03

Спасибо за обзор. Вот значит, что это. Буду использовать, а то как всегда некогда изучать самому.

Alex
Alex
04/12/2012 19:10

Почему то при компиляции в проектах FireMonkey(XE3) выдает ошибку out of memory.
При этом до кода дело не дошло, только прописал в uses CodeSiteLogging.

Ildar Khayrislamov
08/02/2013 17:21

Такая проблема:
На одном компьютере не пишет лог. CSDispatcher.exe висит в процессах и все, но в трее не отображается, как это должно быть.
На всех остальных компьютерах все в порядке. Система Windows 7 SP1. Не так много информации в Интернете об этом CodeSite.
Антивирус MSE вроде не причем. В журнале ничего нет. Брандмауэр отключен. Больше блокировок похоже там нет.
Из-за чего может быть такое?
Единственное на что могу грешить, так это на занятый порт. Ведь только вчера все было в порядке. Но как изменить порт, если в трее ее не видно? И из-за порта неужели интерфейс свой прятал бы?

KingComp
10/01/2014 16:04
Ответить на  Ildar Khayrislamov

Ха, наткнулся на свое же сообщение. Ну что же, отвечу себе спустя почти год. =)
Проблема оказалась в отсутствии проверки существования директории где создаются лог-файлы. После того, как создал каталог, все заработало. Это исправлено давно, ответил на всякий случай, может кому пригодится.

P.S.: Новый вопрос: как сделать, чтобы CodeSite Dispatcher не отображался в трее при запущенной программе? Все таки не очень приятно, когда трей «засоряется». Искал, но ответа не нашел.

Николай
Николай
19/02/2013 21:16

Юникодные строки, кстати, приводятся к ансистрокам, что может привести к потере данных при логировании. Печаль (

Alex
Alex
16/02/2017 22:17

Влад, обнови инфу — в последних версиях IDE CodeSite ставится через GetIt. А то я минут 30 его искал.