Лучше всего сделать интерфейс максимально простым.Полностью отделите пользовательский интерфейс ведения журнала от того, как на самом деле реализовано ведение журнала.
Межсекторальные проблемы всегда дороги в обслуживании, поэтому усложнение ситуации усложнит жизнь.
Некоторые библиотекитолько хочет что-то простое, как это:
void logDebug(const std::string &msg);
void logWarning(const std::string &msg);
void logError(const std::string &msg);
Они не должны добавлять или указывать больше контекста.Никто не может использовать информацию в любом случае, поэтому не переусердствуйте в ее создании.
Если вы начнете добавлять больше информации в свои журналы вызовов, это затруднит повторное использование клиентского кода, который его использует.Обычно вы увидите эту поверхность, когда компоненты используются на разных уровнях абстракции.Особенно, когда какой-то низкоуровневый код предоставляет отладочную информацию, относящуюся только к более высоким уровням.
Это не заставляет вашу реализацию протоколирования (или даже интерфейс, которому соответствует реализация протоколирования!) Ни к чему, так что выможет изменить его в любое время.
ОБНОВЛЕНИЕ:
Поскольку тегирование является проблемой высокого уровня.Я собираюсь предположить, что он не принадлежит журналу, но это ни здесь, ни там.
Не допускайте его в спецификации сообщения журнала.Код низкого уровня не должен сообщать летающему грузовику, кто вы или ваш менеджер.
Я не знаю, как вы указываете X
или Y
в своем примере.Как вы это делаете, не очень понятно из приведенного нами описания.Я собираюсь просто использовать строку для демонстрации, но вы должны заменить ее на что-то безопасное, если это возможно.
Если это всегда включено, то просто иметь контекст экземпляра (возможно, глобальную переменную)может быть уместным.Когда вы входите в систему, установите контекст и забудьте об этом.Если он не установлен, бросайте с предубеждением.Если вы не можете бросить, когда он не установлен, то он не всегда включен.
void setLoggingContext("X:");
Если это меняется на разных уровнях абстракции, я бы рассмотрел реализацию RAII на основе стека.
LoggingTag tag("X:");
Я не уверен, каковы ваши требования в сценарии, когда разные кадры стека принимают разные значения.Я мог видеть, где верх или низ стека будет подходящим для разных вариантов использования.
void foo() {
LoggingTag tag("X:");
logWarning("foo");
bar();
baz();
}
void bar() {
LoggingTag tag("Y:");
logWarning("bar");
baz();
}
void baz() {
logWarning("baz");
}
В любом случае это не должно влиять на то, как вы добавляете сообщение в журнал.Функция baz
не имеет контекста для указания LoggingTag
.По этой причине очень важно, чтобы logWarning
не знал о тегах.
Если вы хотите использовать теги на основе какого-либо типа, вы можете сделать что-то простое, как это.
struct LoggingTag {
LoggingTag(const std::string &tag_) : tag(tag_) {}
template<typename T>
static LoggingTag ByType() {
return LoggingTag(typeid(T).name());
}
std::string tag;
};
void foo() {
LoggingTag tag = LogginTag::ByType<int>();
}
Это не заставит кого-либо использовать typeid(T).name()
, если он не захочет, но даст вам удобство.