/*
* Copyright 2023 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "livekit/logging.h"
#include
#include
#include
#include
namespace livekit {
namespace {
const char *kLoggerName = "livekit";
spdlog::level::level_enum toSpdlogLevel(LogLevel level) {
switch (level) {
case LogLevel::Trace:
return spdlog::level::trace;
case LogLevel::Debug:
return spdlog::level::debug;
case LogLevel::Info:
return spdlog::level::info;
case LogLevel::Warn:
return spdlog::level::warn;
case LogLevel::Error:
return spdlog::level::err;
case LogLevel::Critical:
return spdlog::level::critical;
case LogLevel::Off:
return spdlog::level::off;
}
return spdlog::level::info;
}
LogLevel fromSpdlogLevel(spdlog::level::level_enum level) {
switch (level) {
case spdlog::level::trace:
return LogLevel::Trace;
case spdlog::level::debug:
return LogLevel::Debug;
case spdlog::level::info:
return LogLevel::Info;
case spdlog::level::warn:
return LogLevel::Warn;
case spdlog::level::err:
return LogLevel::Error;
case spdlog::level::critical:
return LogLevel::Critical;
case spdlog::level::off:
return LogLevel::Off;
default:
return LogLevel::Info;
}
}
std::mutex &loggerMutex() {
static std::mutex mtx;
return mtx;
}
std::shared_ptr &loggerStorage() {
static std::shared_ptr logger;
return logger;
}
std::shared_ptr createDefaultLogger() {
auto sink = std::make_shared();
auto logger = std::make_shared(kLoggerName, sink);
logger->set_level(spdlog::level::info);
logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%^%l%$] %v");
return logger;
}
} // namespace
namespace detail {
std::shared_ptr getLogger() {
std::lock_guard lock(loggerMutex());
auto &logger = loggerStorage();
if (!logger) {
logger = createDefaultLogger();
spdlog::register_logger(logger);
}
return logger;
}
void shutdownLogger() {
std::lock_guard lock(loggerMutex());
auto &logger = loggerStorage();
if (logger) {
spdlog::drop(kLoggerName);
logger.reset();
}
}
} // namespace detail
void setLogLevel(LogLevel level) {
detail::getLogger()->set_level(toSpdlogLevel(level));
}
LogLevel getLogLevel() { return fromSpdlogLevel(detail::getLogger()->level()); }
void setLogCallback(LogCallback callback) {
std::lock_guard lock(loggerMutex());
auto &logger = loggerStorage();
auto current_level = logger ? logger->level() : spdlog::level::info;
if (logger) {
spdlog::drop(kLoggerName);
}
if (callback) {
auto sink = std::make_shared(
[cb = std::move(callback)](const spdlog::details::log_msg &msg) {
cb(fromSpdlogLevel(msg.level),
std::string(msg.logger_name.data(), msg.logger_name.size()),
std::string(msg.payload.data(), msg.payload.size()));
});
logger = std::make_shared(kLoggerName, sink);
} else {
logger = createDefaultLogger();
}
logger->set_level(current_level);
spdlog::register_logger(logger);
}
} // namespace livekit