Описание отчетов
Введение
Панель управления имеет встроенный механизм для формирования различных отчетов. Под отчетом понимается представление статистических данных в виде списков с графиками или без них.
Дальнейшее изложение предполагает, что читатель знаком с общей структурой метаданных, по которым строится UI ispmanager, обзор ее приведен в статье “Структура и возможности плагинов”.
Если перед вами стоит задача создания нового отчета в ispmanager, то возможны два варианта ее решения:
- написать обработчик, который вернет XML-описание страницы с отчетом. Об обработчиках и приемах их написания можно прочесть по ссылке выше. В этой статье данный способ рассматривается как базовый, раздел об элементе
<reportdata>
применим только при использовании этого варианта создания отчетов. - добавить метаданные отчета в XML-описание плагина и использовать элементы
<action>
или<query>
для получения данных. Пример кода для этого варианта приведен в конце статьи.
Ниже приведено описание структуры метаданных в формате XML, по которым строятся отчеты, а также структуры данных, передаваемых для отображения в отчетах.
Общая структура страницы отчета
- Форма: нужна для выбора периода или объекта отображаемых данных. Описывается тегом
<form>
внутри элемента<metadata>
- Таблица: отображает данные. Описывается тегом
<band>
внутри элемента<metadata>
. Таблица в отчете несколько отличается от обычного списка. У нее есть сортировка, на странице может быть более одной таблицы; ячейки таблицы могут содержать ссылки на вложенные отчеты, а также якоря на ниже расположенные отчеты.
Таблица может быть скрыта или показана с помощью специальной кнопки над таблицей. - Диаграмма: строится по данным из таблицы, описывается тегом
<diagram>
внутри элемента<band>
. Таким образом, диаграмма в отчете всегда привязана к какой-либо таблице.
По данным из одной таблицы может быть построено несколько диаграмм.
Элемент <band>
может содержать вложенные элементы <band>
, соответствующие дочерним отчетам, которые отражаются ниже “родительского” на той же странице. Предполагается, что дочерние отчеты так же, как родительский, отображают данные, соответствующие выбранным в форме параметрам отчета.
<metadata name="test.report" type="report" level="admin+" mgr="core">
<toolbar>
<toolbtn func="journal" type="back" img="t-back" name="back"/>
</toolbar>
<text name="title" />
<band name="game" psort="game_name">
<diagram name="games_chart" label="game_name" data="game_size" type="pie" />
<col name="game_name" type="data" total="count" link="yes" />
<col name="game_size" type="data" total="sumsuffix" convert="bytes" sorted="-1" />
<col name="game_price" type="data" total="sumsuffix" convert="money" sort="digit"/>
<band name="sales" psort="game_name">
<diagram name="games_per_country_chart" label="country_name" type="histogram">
<line data="sold_count" />
</diagram>
<col name="country_name" type="data" total="count" />
<col name="sold_count" type="data" sort="digit" total="sum" sorted="-1" />
</band>
</band>
</metadata>
Комментарии к приведенному выше коду:
- Приведенный выше код не содержит данных для отчета, как и строк локализации, таких, как заголовок отчета, - только метаданные, описывающие структуру отчета. Данные отчета и строки локализации будут обсуждаться в последующих разделах этой статьи.
- Элемент
<toolbar>
не имеет прямого отношения к отчету и выполняет ту же функцию, что в формах - содержит кнопки, которые могут выполнять различные действия. В данном случае тулбар содержит кнопку “Назад” - Элемент
<band>
верхнего уровня описывает основной отчет. Таблица основного отчета содержит три столбца, описываемых элементами<col>
- Вложенный элемент
<band>
описывает дочерние таблицы, количество которых будет соответствовать количеству строк в таблице основного отчета - Как родительский, так и вложенный элемент
<band>
содержат по элементу<diagram>
, таким образом будет отображена круговая диаграмма для основного отчета и по одной диаграмме-гистограмме для каждой из дочерних таблиц.
Пример отчета, построенного для приведенных метаданных:
Элемент <metadata>
Элемент <metadata>
, содержащий метаданные отчета, имеет ряд атрибутов, важных для этого типа страниц:
type="report"
- сообщает ispmanager, что данные элемента должны интерпретироваться как описание отчета
name
- обязательный атрибут, как и в случае других типов страниц, указывает на func (функцию) в ispmanager, обрабатывающую данный отчет. При отправке данных формы внутри отчета эти данные будут переданы обработчику, связанному с указанным func.
firstrun
- при firstrun="no"
отчет не будет формироваться при открытии страницы, то есть страница не будет содержать таблиц и диаграмм отчета до тех пор, пока не будут отправлены данные формы с параметрами отчета. Может быть полезным, когда отчет формируется долго.
Строки локализации
С помощью сообщений в разделе messages
можно задать описания ко всему отчету и к отдельным таблицам и графикам.
Описание отчета
Можно добавить текстовое описание отчета, которое будет отображаться под заголовком и над формой. Для этого в список сообщений messages в xml отчета необходимо добавить сообщение с именем report_info
, например:
<msg name="report_info">Подробный отчет об использовании ресурсов сервера</msg>
Описание к таблице
Чтобы добавить описание к отдельной таблице с данными, в раздел messages XML отчета нужно добавить сообщение с именем в формате table_[BANDNAME]
, например:
<msg name="table_used_disk”>Использование дискового пространства</msg>
Описание к графику
Чтобы добавить описание к отдельному графику, в раздел messages XML отчета нужно добавить сообщение с именем в формате diagram_[DIAGRAMNAME]
, например:
<msg name="diagram_used_disk_chart”>График изменения использованного дискового пространства</msg>
Элемент <form>
В этом элементе описывается форма, если ее необходимо отображать. Форма отображается вверху страницы сразу после заголовка и может использоваться для выбора пользователем параметров для построения отчета. Структура этого элемента такая же, как в описании обычных форм.
Обязательно используйте валидаторы для проверки вводимых значений. Так, валидатор check="date"
в сочетании с маской mask="9999-99-99"
проверяет вводимые значения на соответствие формату “дата YYYY-MM-DD”, валидатор check="int"
проверяет, что было введено целое число. Подробнее: Валидаторы
Элемент <band>
Элемент <band>
содержит информацию о структуре данных отчета и формате их вывода на странице. Он имеет следующую структуру:
<band>
<query/>
<action/>
<diagram>
[[<line/>]]
</diagram>
<col/>
[[<band>]]
</band>
Элементы <band>
могут быть вложенными в <band>
более высокого уровня. Данные для отображения в <band>
задаются либо посредством элементов <query>
или <action>
, либо передачей данных в элементе <reportdata>
(см. ниже в соответствующем разделе). Элементы <query>
и <action>
не могут находиться вместе в одном и том же <band>
.
Атрибуты элемента <band>
:
name
- имя band, ключевой атрибут
hidden
- при hidden="yes"
таблица с данными будет скрыта.
Элемент <col>
Представляет столбец данных в таблице отчета.
Атрибуты:
name
- имя столбцa, по которому он заполняется данными, ключевой атрибут.
convert
- алгоритм кодирования значений в ячейках при подсчете итогов (см. атрибут total
). Единственное возможное значение: "bytes"
- формат размера данных, например "128 MB"
.
link
- при link="yes"
в столбце будет ссылка (якорь) на дочерние элементы данных, а значения из столбца будут заголовками дочерних таблиц.
sort
- задаёт тип сортировки данных в столбце. Возможные значения: alpha (алфавитная сортировка; по умолчанию), digit (сортировка в порядке числового возрастания).
total
- задаёт тип итогов, отображаемых внизу таблицы с данными. Возможные значения: count
(количество строк, имеющих данные в этом столбце), sum
(сумма значений ячеек в данном столбце (для числовых столбцов)), sumsuffix
(cумма значений ячеек в данном столбце с обработкой суффиксов и convert="money"
), avg
(среднее значений ячеек в данном столбце).
nestedreport
- добавляет ссылку в столбце на другой отчет (функцию), который будет указан в значение атрибута. Также странице другого отчета будут переданы параметры elid
— значение в ячейке (или атрибут id
из elem
), colname
— имя столбца, и все параметры формы отчета.
Элемент <query>
Содержит sql-запрос, по которому предоставляются данные для отображения в отчете.
Элемент <query>
может быть использован только в XML-описании плагина (см. примеры в конце данной статьи), но не в XML-данных, возвращаемых обработчиком.
В двойных квадратных скобках: [[значение]]
- можно передавать в запрос значения из формы или в запрос для дочерней таблицы - значение из основной таблицы (как правило, id записи).
В запросе необходимо использовать псевдонимы для столбцов, чтобы привязать их к элементу <col>
.
Пример использования псевдонимов и значений в двойных квадратных скобках см. ниже:
.....
<form>
<!-- получаем от пользователя значение ip-адреса, по которому нужно вывести отчет -->
<field name="ip">
<input name="ip" type="text"/>
</field>
</form>
<band name="emaildomain">
<!-- запрос к БД ispmanager с использованием введенного значения ip-адреса, используются псевдонимы -->
<query>SELECT emaildomain.id AS id, emaildomain.name AS name, emaildomain.ip AS ip as email_cnt FROM emaildomain WHERE ip=[[ip]]</query>
<!-- в атрибут name элемента <col> передается псевдоним из запроса выше -->
<col name="name" type="data" link="yes"/>
<col name="ip" type="data"/>
<band name="email" psort="used">
<!-- запрос для дочерних таблиц с использованием id домена, для которого строится таблица -->
<query>SELECT name AS emailname, used FROM email WHERE domain=[[emaildomain.id]]</query>
<col name="emailname" type="data"/>
<col name="used" type="data"/>
</band>
</band>
.....
При использовании отчетов с заданными запросами к БД, необходимо указать источник данных для этих запросов. Чтобы установить источник данных в программе, воспользуйтесь функцией isp_api::SetReportSource(). По умолчанию, все запросы обращаются к текущей базе данных панели без дополнительных уточнений.
Элемент <action>
Содержит запрос к какой-либо функции в программе. Данная функция должна возвращать список, который будет использован как данные для отчета.
Элемент <action>
может быть использован только в XML-описании плагина (см. примеры в конце данной статьи), но не в XML-данных, возвращаемых обработчиком.
Значения атрибута name на элементах <col>
должны соответствовать именам полей в строках списка.
Кроме имени функции в строке внутри элемента <action>
можно передать параметры вызова функции, как продемонстрировано в примере ниже:
.....
<band name="testdata">
<!-- запрашиваем данные об активных сайтах -->
<action>
webdomain?filter=on&active=on
</action>
<!-- используем в таблице отчета имя и папку сайта -->
<col name="name"/>
<col name="docroot"/>
</band>
.....
Элемент <diagram>
Содержит описание диаграммы к таблице, заданной родительским элементом <band>
Атрибуты:
name
- имя диаграммы.
label
- говорит, из какого столбца таблицы брать подписи к диаграмме.
type
- задает тип диаграммы. Возможные значения: "pie"
(круговая), "histogram"
(вертикальные столбцы), "line"
(линии).
Типы диаграмм
pie
- круговая диаграмма
histogram
- диаграмма с вертикальными столбцами
line
- диаграмма с одной или несколькими линиями, соединяющими точки значений
Элемент <line>
Содержит информацию о том, откуда брать данные для диаграммы, используется только внутри элементов <diagram>
с type="histogram"
и type="line"
. У диаграммы может быть несколько элементов line.
Атрибуты:
data
- говорит, из какого столбца брать данные для построения диаграммы
XML данных отчета: элемент <reportdata>
Кроме метаданных, описывающих структуру отчета (элемент <band>
внутри <metadata>
), для построения отчета требуются данные для отображения в нем, которые передаются в элементе <reportdata>
. Этот элемент используется только в случае, когда данные отчета формируются обработчиком. Его не нужно использовать, если данные для отчета формируются с помощью элементов <query>
или <action>
в метаданных отчета.
<reportdata>
является непосредственным родителем для элементов, имена которых соответствуют значению атрибута name
элементов <band>
верхнего уровня. Таким образом, если в <metadata>
есть элемент <band name="traffic">
, то внутри <reportdata>
будет элемент <traffic>
.
Каждая строка таблицы данных описывается элементом <elem>
, внутри которого имена элементов соответствуют значениям атрибута name
на элементах <col>
. Кроме того, в элементах <elem>
могут содержаться элементы, описывающие данные для дочерней таблицы, их имена будут соответствовать значениям атрибута name
на дочерних элементах <band>
.
Проиллюстрируем сказанное выше примером XML, содержащим и метаданные, и данные для построения отчета:
<metadata name="journal.stat" type="report" level="30" firstrun="no" mgr="core">
<!-- <band> верхнего уровня, значение атрибута name соответствует элементу <function> внутри <reportdata> -->
<band name="function">
<diagram name="func" label="funcname" data="percentage" type="pie"/>
<!-- столбец верхнего уровня, значение атрибута name соответствует элементу <funcname> внутри <elem> верхнего уровня -->
<col name="funcname" type="data" total="count" link="yes"/>
<col name="percentage" type="data" sort="digit" sorted="desc" total="sum"/>
<!-- <band> второго уровня, значение атрибута name соответствует элементу <user> внутри <elem> верхнего уровня -->
<band name="user">
<diagram name="user" label="username" type="histogram">
<line data="percentage"/>
</diagram>
<!-- столбец второго уровня, значение атрибута name соответствует элементу <username> внутри <elem> второго уровня -->
<col name="username" type="data" total="count"/>
<col name="percentage" type="data" sort="digit" sorted="desc" total="sum"/>
</band>
</band>
</metadata>
<reportdata>
<!-- данные для таблицы верхнего уровня, описываемой <band name="function"> -->
<function>
<elem>
<!-- значение ячейки в столбце <col name="funcname"> в таблице верхнего уровня -->
<funcname>mgr.edit</funcname>
<percentage>100.00</percentage>
<!-- данные для дочерней таблицы, описываемой <band name="user"> -->
<user>
<elem>
<!-- значение ячейки в столбце <col name="username"> в дочерней таблице -->
<username>root</username>
<percentage>100.00</percentage>
</elem>
</user>
</elem>
</function>
</reportdata>
Пример добавления метаданных в XML-описание плагина и использования <query> и <action>
Два приведенных ниже примера выполняют одну и ту же задачу: отобразить информацию о почтовых доменах. Первый пример делает это с помощью элемента <action>
, второй - с помощью элемента <query>
. Оба варианта предполагают, что XML-метаданные отчета добавляются в XML плагина без использования обработчика. Поскольку обработчик не используется, элемент <handler>
в XML-описании плагина в этом случае не нужен. Подробнее о работе с XML-описаниями плагинов читайте в статье “Структура и возможности плагинов”.
Пример с использованием элемента <action>
, который позволяет использовать для отчета данные какого-либо существующего списка, в нашем случае - со страницы "Почтовые домены" (func=emaildomains
):
<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
<!-- добавляем в главное меню новую группу и новый пункт -->
<mainmenu level="admin+">
<modernmenu>
<node name="reports">
<node name="emaildomain_report" />
</node>
</modernmenu>
</mainmenu>
<!-- метаданные отчета -->
<metadata name="emaildomain_report" type="report" level="admin+">
<band name="emaildomain" psort="name">
<action>emaildomain?filter=on&active=on</action>
<col name="name" type="data"/>
<col name="owner" type="data"/>
</band>
</metadata>
<lang name="ru">
<!-- сообщения локализации для главного меню -->
<messages name="desktop">
<!-- название группы в modern_menu-->
<msg name="modernmenu_reports">Отчеты</msg>
<!-- название пункта меню -->
<msg name="modernmenu_emaildomain_report">Почтовые домены</msg>
</messages>
<!-- сообщения локализации для страницы отчета -->
<messages name="emaildomain_report">
<msg name="msg_hidedata">Скрыть данные</msg>
<msg name="msg_nodata">Нет данных</msg>
<msg name="msg_showdata">Показать данные</msg>
<msg name="name">Домен</msg>
<msg name="owner">Владелец</msg>
<msg name="email_cnt">Количество почтовых ящиков</msg>
<msg name="report_info">Статистика почтовых доменов</msg>
<msg name="title">Отчёт: Почтовые домены</msg>
</messages>
</lang>
</mgrdata>
Пример с использованием элемента <query>
, формой, диаграммой и вложенными таблицами:
<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
<!-- добавляем в главное меню новую группу и новый пункт -->
<mainmenu level="admin+">
<modernmenu>
<node name="reports">
<node name="emaildomain_report" />
</node>
</modernmenu>
</mainmenu>
<!-- метаданные отчета -->
<metadata name="emaildomain_report" type="report" level="admin+" firstrun="no">
<form>
<field name="ip">
<input name="ip" type="text"/>
</field>
</form>
<band name="emaildomain" psort="name">
<query>SELECT emaildomain.id AS id, emaildomain.name AS name, emaildomain.ip AS ip, COUNT(email.id) as email_cnt FROM emaildomain, email WHERE email.domain=emaildomain.id AND ip=[[ip]] GROUP BY emaildomain.id</query>
<col name="name" type="data" link="yes"/>
<col name="email_cnt" type="data"/>
<diagram type="pie" name="emaildomain" data="email_cnt" label="name" />
<band name="email" psort="used">
<query>SELECT name AS emailname, used FROM email WHERE domain=[[emaildomain.id]]</query>
<col name="emailname" type="data"/>
<col name="used" type="data"/>
</band>
</band>
</metadata>
<lang name="ru">
<!-- сообщения локализации для главного меню -->
<messages name="desktop">
<!-- название группы в modern_menu-->
<msg name="modernmenu_reports">Отчеты</msg>
<!-- сообщения для modern_menu, название пункта -->
<msg name="modernmenu_emaildomain_report">Почтовые домены</msg>
</messages>
<!-- сообщения локализации для страницы отчета -->
<messages name="emaildomain_report">
<msg name="msg_hidedata">Скрыть данные</msg>
<msg name="msg_nodata">Нет данных</msg>
<msg name="msg_showdata">Показать данные</msg>
<msg name="name">Домен</msg>
<msg name="ip">IP</msg>
<msg name="email_cnt">Количество почтовых ящиков</msg>
<msg name="emailname">Имя ящика</msg>
<msg name="used">Использовано места на диске</msg>
<msg name="report_info">Статистика почтовых доменов</msg>
<msg name="title">Отчёт: Почтовые домены</msg>
</messages>
</lang>
</mgrdata>
Отчет, созданный кодом из второго примера: