| 94 | } |
| 95 | |
| 96 | int main(void) { |
| 97 | SPDLOG_INFO("Starting MQTTManager."); |
| 98 | |
| 99 | std::filesystem::path log_partition_path = "/dev/shm/"; |
| 100 | std::filesystem::space_info log_partition_space_info = std::filesystem::space(log_partition_path); |
| 101 | const uintmax_t free_space = log_partition_space_info.free; |
| 102 | const uintmax_t free_space_10_percent = free_space * 0.10; // 10% of free space. |
| 103 | const uintmax_t max_log_size = 1048576 * 30; |
| 104 | |
| 105 | SPDLOG_INFO("/dev/shm has {} bytes free.", log_partition_space_info.free); |
| 106 | |
| 107 | // Setup logging |
| 108 | auto max_size = boost::minmax(free_space_10_percent, free_space).head; // Grow log file to 10% of free space or max 30MB and then rotate |
| 109 | |
| 110 | SPDLOG_INFO("Will log to /dev/shm/mqttmanager.log with a max size of {} bytes.", max_size); |
| 111 | |
| 112 | std::vector<spdlog::sink_ptr> spdlog_sinks; |
| 113 | spdlog_sinks.push_back(std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>()); // Log to console |
| 114 | if (max_size > 1024) { |
| 115 | spdlog_sinks.push_back(std::make_shared<spdlog::sinks::rotating_file_sink_st>("/dev/shm/mqttmanager.log", max_size, 1)); // Log to rotating log file |
| 116 | } else { |
| 117 | SPDLOG_ERROR("Not enough storage/momory available on /dev/shm partition. Will not log to file!"); |
| 118 | } |
| 119 | |
| 120 | // Setup logging to console and file |
| 121 | auto combined_logger = std::make_shared<spdlog::logger>("combined_logger", begin(spdlog_sinks), end(spdlog_sinks)); |
| 122 | spdlog::register_logger(combined_logger); |
| 123 | spdlog::set_default_logger(combined_logger); |
| 124 | spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%#] [%t] %v"); |
| 125 | |
| 126 | char *log_level = std::getenv("LOG_LEVEL"); |
| 127 | if (log_level != NULL) { |
| 128 | std::string log_level_str = log_level; |
| 129 | if (log_level_str.compare("error") == 0) { |
| 130 | spdlog::set_level(spdlog::level::err); |
| 131 | } else if (log_level_str.compare("warning") == 0) { |
| 132 | spdlog::set_level(spdlog::level::warn); |
| 133 | } else if (log_level_str.compare("info") == 0) { |
| 134 | spdlog::set_level(spdlog::level::info); |
| 135 | } else if (log_level_str.compare("debug") == 0) { |
| 136 | spdlog::set_level(spdlog::level::debug); |
| 137 | } else if (log_level_str.compare("trace") == 0) { |
| 138 | spdlog::set_level(spdlog::level::trace); |
| 139 | } else { |
| 140 | SPDLOG_INFO("No log level was set by 'LOG_LEVEL' environment variable. Will assume level debug."); |
| 141 | spdlog::set_level(spdlog::level::debug); |
| 142 | } |
| 143 | } else { |
| 144 | SPDLOG_INFO("No log level was set by 'LOG_LEVEL' environment variable. Will assume level debug."); |
| 145 | spdlog::set_level(spdlog::level::debug); |
| 146 | } |
| 147 | |
| 148 | // When a config change is made in the web interface the Django application |
| 149 | // will send a SIGUSR1 signal to the MQTTManager so that the manager |
| 150 | // know that it needs to reload the config. |
| 151 | struct sigaction sigUsr1Handler; |
| 152 | sigUsr1Handler.sa_handler = sigusr1_handler; |
| 153 | sigemptyset(&sigUsr1Handler.sa_mask); |