В библиотеку logme встроена мощная поддержка профилирования функций. Профилирование функций с logme это просто. Есть возможность, просто добавив один макрос, обеспечить вывод в лог информации о входе в функцию с указанием её имени, выходе из неё, а также при необходимости — печати параметров и возвращаемого значения. Это позволяет без особых усилий понять, как и когда функция вызывалась, что она вернула и сколько времени заняло её выполнение.
Для этого определена целая группа макросов LogmeP. Если не требуется логирование возвращаемого значения, добавляется суффикс void — V. Далее может указываться уровень логирования: debug — D, info — I, warning — W, error — E, critical — C. Суффикс уровня можно не указывать — в этом случае используется уровень Info по умолчанию. Таким образом, чтобы печатать вход и выход из функции без параметров и возвращаемого значения с уровнем Info, достаточно использовать LogmePVI (или просто LogmePV).
Пример ниже демонстрирует использование макроса для трассировки входа и выхода из функции:
#include <thread>
#include <chrono>
#include <Logme/Logme.h>
int MyProc(int i, const char* name)
{
LogmePV();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return i + 1;
}
int main()
{
MyProc(123, "abc");
return 0;
}
В лог будет выведено следующее
Чтобы дополнительно выводилось время выполнения функции, необходимо включить флаг Duration у канала. Ниже приведён пример, который включает этот флаг для канала по умолчанию:
int main()
{
auto ch = Logme::Instance->GetDefaultChannelPtr();
auto flags = ch->GetFlags();
flags.Duration = true;
ch->SetFlags(flags);
MyProc(123, "abc");
return 0;
}
Печать времени выполнения
Теперь в логе будет отображаться и время выполнения функции
Печать возвращаемого значения
Если требуется выводить возвращаемое значение, используется макрос без суффикса V, в который передаётся ссылка на переменную, содержащую результат. Например:
int MyProc(int i, const char* name)
{
int ret{};
LogmePW(ret);
ret = i + 1;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return ret;
}
В этом случае результат будет выглядеть так, как показано ниже
Печать значения аргументов
Если нужно видеть значения параметров функции, их можно перечислить через запятую после указания переменной возвращаемого значения. Для печати только значений используется макрос ARGS, например:
int MyProc(int i, const char* name)
{
LogmePV(ARGS(i, name));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return i + 1;
}
Если же требуется выводить не только значения, но и имена параметров, используются макросы ARGS1, ARGS2 и т.д., где число соответствует количеству аргументов:
int MyProc(int i, const char* name)
{
LogmePV(ARGS2(i, name));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return i + 1;
}
В примерах выше тип аргументов функции был стандартный и для таких типов есть встроенные функции преобразования значения в строку (в терминологии logme — Printer методы). Если нужно распечатывать значение комплексных типов, то нужно объявить где-то в области видимости соответствующий Printer. Например, в примере ниже объявляется Printer для типа Point и он используется для печати возвращаемого из функции MakePoint значения:
struct Point
{
int X;
int Y;
};
template<> std::string FormatValue<Point>(const Point& value)
{
return "Point(" + std::to_string(value.X) + ", " + std::to_string(value.Y) + ")";
}
static Point MakePoint(int x, int y)
{
Point r{ x, y };
LogmeP(r);
return r;
}
Выбор канала для печати
Во всех приведённых примерах использовался канал по умолчанию. Если необходимо явно указать канал, его можно передать перед списком аргументов, как показано ниже:
Logme::ID CHT{ "test" };
int MyProc(int i, const char* name)
{
int ret{};
LogmePI(ret, CHT, ARGS2(i, name));
ret = i + 1;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return ret;
}
int main()
{
auto ch = Logme::Instance->CreateChannel(CHT);
ch->AddLink(::CH);
MyProc(123, "abc");
return 0;
}
Профилирование функций с logme: выводы
Использование макросов LogmeP позволяет быстро и практически без изменения структуры кода добавить подробное логирование выполнения функций. Это особенно удобно при отладке и анализе поведения программы. Когда важно понимать порядок вызовов, значения параметров и время выполнения.
За счёт гибкой системы суффиксов и дополнительных макросов можно легко настроить уровень детализации логов. От простого трейсинга до полноценного профилирования с параметрами и возвращаемыми значениями. При этом код остаётся компактным и читаемым.
В итоге такой подход значительно снижает затраты на диагностику и упрощает сопровождение проекта, особенно в сложных или многопоточных системах.
Дополнительную информацию об использовании профилировщика библиотеки logme можно найти в wiki.
Рекомендуем также посмотреть статью о сравнении производительности топовых библиотек логирования по этой ссылке.

