Skip to content

Commit c93a0ef

Browse files
committed
fix: configuration parsing error mmap_log_buffer_size
1 parent 11853e1 commit c93a0ef

File tree

4 files changed

+518
-103
lines changed

4 files changed

+518
-103
lines changed

utils/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ CLICKHOUSE_BUILD_DIR := $(CLICKHOUSE_DIR)/build
2121
CLICKHOUSE_REPO_URL := https://github.com/ClickHouse/clickhouse-cpp.git
2222

2323
CXX := g++
24-
LDFLAGS := -lfmt -lboost_program_options
24+
LDFLAGS := -lfmt -lboost_program_options -lboost_filesystem
2525
LDFLAGS += -lclickhouse-cpp-lib -L $(CLICKHOUSE_BUILD_DIR)/clickhouse
2626
LDFLAGS += -lcityhash -L $(CLICKHOUSE_BUILD_DIR)/contrib/cityhash/cityhash
2727
LDFLAGS += -lzstdstatic -L $(CLICKHOUSE_BUILD_DIR)/contrib/zstd/zstd
@@ -33,7 +33,7 @@ CXXFLAGS := -O3 -Wall -Wextra -std=c++23 -DPAGE_SIZE=$(PAGE_SIZE)
3333
CXXFLAGS += $(shell pkgconf -cflags spdlog)
3434
CXXFLAGS += -I $(CLICKHOUSE_DIR)
3535
CXXFLAGS += -I $(CLICKHOUSE_DIR)/contrib/absl
36-
SRCS := tfw_logger.cc mmap_buffer.cc clickhouse.cc
36+
SRCS := tfw_logger.cc mmap_buffer.cc clickhouse.cc config.cc
3737
OBJS := $(SRCS:.cc=.o)
3838
TARGET := tfw_logger
3939

utils/config.cc

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
/**
2+
* Tempesta FW
3+
*
4+
* Copyright (C) 2024-2025 Tempesta Technologies, Inc.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License,
9+
* or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along with
17+
* this program; if not, write to the Free Software Foundation, Inc., 59
18+
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+
*/
20+
21+
#include "config.hh"
22+
#include "error.hh"
23+
24+
#include <boost/property_tree/json_parser.hpp>
25+
#include <boost/program_options.hpp>
26+
#include <thread>
27+
#include <iostream>
28+
#include <sstream>
29+
30+
namespace pt = boost::property_tree;
31+
namespace po = boost::program_options;
32+
33+
std::optional<TfwLoggerConfig>
34+
TfwLoggerConfig::load_from_file(const fs::path &path)
35+
{
36+
if (!fs::exists(path))
37+
{
38+
std::cerr << "Config file not found: " << path << std::endl;
39+
return std::nullopt;
40+
}
41+
42+
try
43+
{
44+
pt::ptree tree;
45+
pt::read_json(path.string(), tree);
46+
47+
TfwLoggerConfig config;
48+
config.parse_from_ptree(tree);
49+
return config;
50+
}
51+
catch (const pt::json_parser_error &e)
52+
{
53+
std::cerr << "Error parsing config file: " << e.what() << std::endl;
54+
return std::nullopt;
55+
}
56+
catch (const pt::ptree_error &e)
57+
{
58+
std::cerr << "Error in config structure: " << e.what() << std::endl;
59+
return std::nullopt;
60+
}
61+
catch (const std::exception &e)
62+
{
63+
std::cerr << "Error loading config: " << e.what() << std::endl;
64+
return std::nullopt;
65+
}
66+
}
67+
68+
TfwLoggerConfig
69+
TfwLoggerConfig::from_cli_args(int argc, char *argv[])
70+
{
71+
TfwLoggerConfig config;
72+
po::options_description desc("Tempesta Logger options");
73+
74+
std::string mode_str;
75+
std::string ch_host;
76+
77+
desc.add_options()("help,h", "Show help message")("mode,m", po::value<std::string>(&mode_str)->default_value("daemon"),
78+
"Operating mode (daemon or handle)")("log-path,l", po::value<fs::path>(&config.log_path),
79+
"Path to the log file")("pid-file,p", po::value<fs::path>(&config.pid_file),
80+
"Path to the PID file")("buffer-size,b", po::value<size_t>(&config.buffer_size),
81+
"Buffer size in bytes")("cpu-count,c", po::value<size_t>(&config.cpu_count),
82+
"Number of CPUs to use (0 = auto)")("debug,d", po::bool_switch(&config.debug),
83+
"Enable debug logging")("clickhouse-host,H", po::value<std::string>(&config.clickhouse.host)->required(),
84+
"ClickHouse server host")("clickhouse-port", po::value<uint16_t>(&config.clickhouse.port),
85+
"ClickHouse server port")("clickhouse-user,u", po::value<std::string>(),
86+
"ClickHouse username")("clickhouse-password", po::value<std::string>(),
87+
"ClickHouse password")("clickhouse-table", po::value<std::string>(&config.clickhouse.table_name),
88+
"ClickHouse table name")("clickhouse-database", po::value<std::string>(&config.clickhouse.database),
89+
"ClickHouse database name")("clickhouse-max-events", po::value<size_t>(&config.clickhouse.max_events),
90+
"Maximum events in a batch")("clickhouse-max-wait", po::value<int>(),
91+
"Maximum wait time for batch (ms)");
92+
93+
po::variables_map vm;
94+
95+
try
96+
{
97+
po::store(po::parse_command_line(argc, argv, desc), vm);
98+
99+
if (vm.count("help"))
100+
{
101+
std::cout << desc << std::endl;
102+
exit(0);
103+
}
104+
105+
po::notify(vm);
106+
107+
// Process mode
108+
if (mode_str == "daemon")
109+
{
110+
config.mode = Mode::DAEMON;
111+
}
112+
else if (mode_str == "handle")
113+
{
114+
config.mode = Mode::HANDLE;
115+
}
116+
else
117+
{
118+
throw std::runtime_error("Invalid mode: " + mode_str);
119+
}
120+
121+
// Process optional parameters
122+
if (vm.count("clickhouse-user"))
123+
{
124+
config.clickhouse.user = vm["clickhouse-user"].as<std::string>();
125+
}
126+
127+
if (vm.count("clickhouse-password"))
128+
{
129+
config.clickhouse.password = vm["clickhouse-password"].as<std::string>();
130+
}
131+
132+
if (vm.count("clickhouse-max-wait"))
133+
{
134+
int ms = vm["clickhouse-max-wait"].as<int>();
135+
config.clickhouse.max_wait = std::chrono::milliseconds(ms);
136+
}
137+
}
138+
catch (const po::error &e)
139+
{
140+
std::cerr << "Error parsing command line: " << e.what() << std::endl;
141+
std::cerr << "Use --help for usage information" << std::endl;
142+
exit(1);
143+
}
144+
catch (const std::exception &e)
145+
{
146+
std::cerr << "Error: " << e.what() << std::endl;
147+
exit(1);
148+
}
149+
150+
return config;
151+
}
152+
153+
void TfwLoggerConfig::parse_from_ptree(const pt::ptree &tree)
154+
{
155+
// Parse mode
156+
std::string mode_str = tree.get<std::string>("mode", "daemon");
157+
if (mode_str == "daemon")
158+
{
159+
mode = Mode::DAEMON;
160+
}
161+
else if (mode_str == "handle")
162+
{
163+
mode = Mode::HANDLE;
164+
}
165+
else
166+
{
167+
throw std::runtime_error("Invalid mode: " + mode_str);
168+
}
169+
170+
// Parse paths
171+
log_path = tree.get<std::string>("log_path", log_path.string());
172+
pid_file = tree.get<std::string>("pid_file", pid_file.string());
173+
174+
// Parse buffer and CPU settings
175+
buffer_size = tree.get<size_t>("buffer_size", buffer_size);
176+
cpu_count = tree.get<size_t>("cpu_count", cpu_count);
177+
178+
// Parse debug flag
179+
debug = tree.get<bool>("debug", debug);
180+
181+
// Parse ClickHouse config if present
182+
if (auto ch_node = tree.get_child_optional("clickhouse"))
183+
{
184+
clickhouse.host = ch_node->get<std::string>("host");
185+
clickhouse.port = ch_node->get<uint16_t>("port", clickhouse.port);
186+
187+
if (auto user = ch_node->get_optional<std::string>("user"))
188+
{
189+
clickhouse.user = *user;
190+
}
191+
192+
if (auto password = ch_node->get_optional<std::string>("password"))
193+
{
194+
clickhouse.password = *password;
195+
}
196+
197+
clickhouse.table_name = ch_node->get<std::string>("table_name", clickhouse.table_name);
198+
clickhouse.database = ch_node->get<std::string>("database", clickhouse.database);
199+
clickhouse.max_events = ch_node->get<size_t>("max_events", clickhouse.max_events);
200+
201+
int max_wait_ms = ch_node->get<int>("max_wait_ms", clickhouse.max_wait.count());
202+
clickhouse.max_wait = std::chrono::milliseconds(max_wait_ms);
203+
}
204+
}
205+
206+
bool TfwLoggerConfig::save_to_file(const fs::path &path) const
207+
{
208+
try
209+
{
210+
pt::ptree tree;
211+
212+
// Save mode
213+
tree.put("mode", mode == Mode::DAEMON ? "daemon" : "handle");
214+
215+
// Save paths
216+
tree.put("log_path", log_path.string());
217+
tree.put("pid_file", pid_file.string());
218+
219+
// Save buffer and CPU settings
220+
tree.put("buffer_size", buffer_size);
221+
tree.put("cpu_count", cpu_count);
222+
223+
// Save debug flag
224+
tree.put("debug", debug);
225+
226+
// Save ClickHouse config
227+
pt::ptree ch_node;
228+
ch_node.put("host", clickhouse.host);
229+
ch_node.put("port", clickhouse.port);
230+
231+
if (clickhouse.user)
232+
{
233+
ch_node.put("user", *clickhouse.user);
234+
}
235+
236+
if (clickhouse.password)
237+
{
238+
ch_node.put("password", *clickhouse.password);
239+
}
240+
241+
ch_node.put("table_name", clickhouse.table_name);
242+
ch_node.put("database", clickhouse.database);
243+
ch_node.put("max_events", clickhouse.max_events);
244+
ch_node.put("max_wait_ms", clickhouse.max_wait.count());
245+
246+
tree.put_child("clickhouse", ch_node);
247+
248+
// Write to file
249+
pt::write_json(path.string(), tree);
250+
return true;
251+
}
252+
catch (const std::exception &e)
253+
{
254+
std::cerr << "Error saving config: " << e.what() << std::endl;
255+
return false;
256+
}
257+
}

utils/config.hh

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Tempesta FW
3+
*
4+
* Copyright (C) 2024-2025 Tempesta Technologies, Inc.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License,
9+
* or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along with
17+
* this program; if not, write to the Free Software Foundation, Inc., 59
18+
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+
*/
20+
21+
#pragma once
22+
23+
#include <string>
24+
#include <chrono>
25+
#include <filesystem>
26+
#include <optional>
27+
#include <boost/property_tree/ptree.hpp>
28+
29+
namespace fs = std::filesystem;
30+
31+
/**
32+
* Configuration for Tempesta FW Logger
33+
*/
34+
class TfwLoggerConfig
35+
{
36+
public:
37+
enum class Mode
38+
{
39+
DAEMON, // Run as a daemon
40+
HANDLE // Run in foreground for debugging
41+
};
42+
43+
struct ClickHouseConfig
44+
{
45+
std::string host; // ClickHouse server host
46+
uint16_t port{9000}; // ClickHouse server port
47+
std::optional<std::string> user; // Optional username
48+
std::optional<std::string> password; // Optional password
49+
std::string table_name{"access_log"}; // Table name
50+
std::string database{"default"}; // Database name
51+
size_t max_events{1000}; // Maximum events in a batch
52+
std::chrono::milliseconds max_wait{100}; // Maximum wait time for batch
53+
};
54+
55+
/**
56+
* Load configuration from a JSON file
57+
*
58+
* @param path Path to the configuration file
59+
* @return Loaded configuration or empty optional on error
60+
*/
61+
static std::optional<TfwLoggerConfig> load_from_file(const fs::path &path);
62+
63+
/**
64+
* Create configuration from command line arguments
65+
* Used for quick setup and testing
66+
*/
67+
static TfwLoggerConfig from_cli_args(int argc, char *argv[]);
68+
69+
/**
70+
* Write configuration to a file
71+
*
72+
* @param path Path to the configuration file
73+
* @return True if successful, false otherwise
74+
*/
75+
bool save_to_file(const fs::path &path) const;
76+
77+
// Getters
78+
Mode get_mode() const { return mode; }
79+
fs::path get_log_path() const { return log_path; }
80+
fs::path get_pid_file() const { return pid_file; }
81+
size_t get_buffer_size() const { return buffer_size; }
82+
size_t get_cpu_count() const { return cpu_count; }
83+
const ClickHouseConfig &get_clickhouse() const { return clickhouse; }
84+
bool get_debug() const { return debug; }
85+
86+
private:
87+
Mode mode{Mode::DAEMON}; // Default to daemon mode
88+
fs::path log_path{"/var/log/tempesta/tfw_logger.log"}; // Log file path
89+
fs::path pid_file{"/var/run/tfw_logger.pid"}; // PID file path
90+
size_t buffer_size{4 * 1024 * 1024}; // 4MB default buffer size
91+
size_t cpu_count{0}; // 0 means auto-detect
92+
ClickHouseConfig clickhouse; // ClickHouse configuration
93+
bool debug{false}; // Debug mode flag
94+
95+
void parse_from_ptree(const boost::property_tree::ptree &pt);
96+
};

0 commit comments

Comments
 (0)