Модуль kernel — это ядро KusSysteam, обеспечивающее базовую функциональность для работы системы. Практически все компоненты программы так или иначе зависят от этого модуля. Можно выделить следующие части ядра:
- Логирование
- Консольные команды
- Хранилище глобальных переменных
- Организатор модулей
- Базовые fixtures для юнит-тестов
- Утилиты (utils)
Для использования любого компонента из kernel достаточно подключить файл include_me.hpp в соответствующей директории.
Например, подключение kernel/framework/include_me.hpp загружает все части модуля, кроме тестовых классов (kernel/tester) и утилит (kernel/utility).
Для работы с логами подключите kernel/framework/logger. Логер состоит из двух основных компонентов:
Расположен в kernel/framework/logger.
| Макрос | Описание |
|---|---|
LOG_CMD |
Сообщение команды |
LOG_INFO |
Информационное сообщение |
LOG_WARNING |
Предупреждение |
LOG_ERROR |
Ошибка |
LOG_EXEPT |
Исключение |
Особые макросы:
LOG_CMD- кроме вывода в логи, возвращает результат команды с тем же текстомLOG_EXEPT- кроме вывода в логи, выбрасывает исключение с тем же текстом
Уровни логирования (от минимального к максимальному):
- CMD
- INFO
- WARNING
- ERROR
- EXEPT
Сообщения с уровнем ниже текущего уровня логирования игнорируются.
Синтаксис сообщений логов аналогичен синтаксису printf, например:
std::string world = "word"; // std::string и ему подобные приводятся к const char*
LOG_INFO("Hello %s", world);Логер является threadlocal объектом, поэтому его инициализация должна выполняться отдельно для каждого потока с помощью макроса LOGGER_INIT, которому передается имя файла для записи логов.
Файлы сохраняются в директории data/logs/<имя файла>.
LOGGER_INIT("test.log");Расположен в kernel/framework/logger/table и позволяет выводить данные в виде таблиц. Сами данные должны находится в STL контейнере. Чтобы подключить и настроить табличную печать необходимо переопределить метод print наследуемый с классом TablePrinter.
Для класса в котором определён контейнер с выводимыми данными необходимо вызвать функцию addTableConrainer передав ей контейнер на вывод. Опционально можно передать набор ключей (std::unordered_set), которые требуется исключить при выводе таблицы.
class Data : TablePrinter;
class Storage : TablePrinter
{
std::unordered_map<std::string, Data> m_store;
void print() const override
{
addTableConrainer(m_store, std::unordered_set<std::string>{"__internal_key"});
}
}Для класса данных функция print позволяет указать какие его поля мы хотим вывести используя функцию addCell
Для обозначения конкретных полей класса для вывода используется функция addCell, принимающая выводимое поле. Порядок вызовов addCell определяет порядок столбцов в результирующей таблице. Также функция addCell возвращает объект для настройки отображения ячейки, предоставляя следующие возможности форматирования:
| Макрос | Описание |
|---|---|
| setName(const std::string&) | задаёт имя столбца |
| setSeparator(char) | задаёт символ разделителя ячеек |
| alignmentRight() | выравнивание по правому краю |
| alignmentMiddle() | выравнивание по центру |
| alignmentLeft() | выравнивание по левому краю (дефолтное значение) |
| addPrefix(const char*) | добавить префикс для выводимого значения |
| setDefault(const char*) | выводить дефолтное значение при "нулевом" (пустом) значении ячейки |
class Data : public TablePrinter
{
int id;
std::string name;
double price;
int quantity;
void print() const override
{
// Первый столбец таблицы - name
addCell(name).setName("Full name").alignmentRight().addPrefix("Mr. ");
// Второй столбец - id
addCell(id);
// Третий столбец - price
addCell(price).alignmentMiddle().setName("sellary");
// quantity не будет выведено, так как для него нет вызова addCell()
}
};
По умолчанию ключи контейнера не отображаются в таблице. Для их вывода в первом столбце необходимо использовать функцию getKeyInfo. Она также возвращает объект позволяющий настроить отображение столбца.
void print() const override
{
getKeyInfo().setName("ID").alignmentMiddle();
}После каждого столбца на печать выводится символ его разделителя, помимо задания разделителя для определённого столбца можно глобально задать базовый символ разделителя для таблицы с помощью функции setDefaultSeparator. По дефолту в таблице используется разделитель вертикальная черта '|'.
void print() const override
{
getKeyInfo().setSeparator('|').alignmentMiddle();
setDefaultSeparator(' ');
}Для создания многострочных ячеек в таблице необходимо в разделить вызовы addCell функцией addSubline. Первый её аргумент - информация ячейки для которой добавляется вторая строчка.
void print() const override
{
// Основная ячейка
auto& main_cell = addCell(primary_data);
// Добавление подстроки
addSubline();
addCell(main_cell, secondary_data); // Вторая строка в той же ячейке
// Можно добавить третью строку
addSubline(main_cell);
addCell(main_cell, tertiary_data);
}
Подробные примеры работы с таблицами можно увидеть в юнит тестах sources/kernel/_tests/table_print_test.cpp.