mirror of
https://github.com/pavel-odintsov/fastnetmon
synced 2024-11-23 09:12:14 +01:00
Unified InfluxDB host traffic export logic with templates
This commit is contained in:
parent
e8c97d3314
commit
f5b7cd8e31
@ -1898,7 +1898,7 @@ uint64_t get_current_unix_time_in_nanoseconds() {
|
||||
}
|
||||
|
||||
// Joins data to format a=b,d=f
|
||||
std::string join_by_comma_and_equal(std::map<std::string, std::string>& data) {
|
||||
std::string join_by_comma_and_equal(const std::map<std::string, std::string>& data) {
|
||||
std::stringstream buffer;
|
||||
|
||||
for (auto itr = data.begin(); itr != data.end(); ++itr) {
|
||||
|
@ -115,7 +115,7 @@ bool write_data_to_influxdb(std::string database,
|
||||
std::string influx_password,
|
||||
std::string query);
|
||||
|
||||
std::string join_by_comma_and_equal(std::map<std::string, std::string>& data);
|
||||
std::string join_by_comma_and_equal(const std::map<std::string, std::string>& data);
|
||||
bool parse_meminfo_into_map(std::map<std::string, uint64_t>& parsed_meminfo);
|
||||
bool read_uint64_from_string(const std::string& line, uint64_t& value);
|
||||
bool read_integer_from_file(const std::string& file_path, int& value);
|
||||
|
@ -136,17 +136,63 @@ bool push_total_traffic_counters_to_influxdb(std::string influx_database,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Simple helper function to add additional metrics easily
|
||||
void add_counter_to_influxdb(std::map<std::string, uint64_t>& plain_total_counters_map,
|
||||
const traffic_counter_element_t& counter,
|
||||
const std::string& counter_name) {
|
||||
plain_total_counters_map[counter_name + "_packets_incoming"] = counter.in_packets;
|
||||
plain_total_counters_map[counter_name + "_bits_incoming"] = counter.in_bytes * 8;
|
||||
plain_total_counters_map[counter_name + "_packets_outgoing"] = counter.out_packets;
|
||||
plain_total_counters_map[counter_name + "_bits_outgoing"] = counter.out_bytes * 8;
|
||||
}
|
||||
|
||||
|
||||
// Fills special structure which we use to export metrics into InfluxDB
|
||||
void fill_per_protocol_countres_for_influxdb(const subnet_counter_t& current_speed_element,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map) {
|
||||
|
||||
add_counter_to_influxdb(plain_total_counters_map, current_speed_element.dropped, "dropped");
|
||||
add_counter_to_influxdb(plain_total_counters_map, current_speed_element.fragmented, "fragmented");
|
||||
add_counter_to_influxdb(plain_total_counters_map, current_speed_element.tcp, "tcp");
|
||||
add_counter_to_influxdb(plain_total_counters_map, current_speed_element.tcp_syn, "tcp_syn");
|
||||
add_counter_to_influxdb(plain_total_counters_map, current_speed_element.udp, "udp");
|
||||
add_counter_to_influxdb(plain_total_counters_map, current_speed_element.icmp, "icmp");
|
||||
}
|
||||
|
||||
// Fills counters for standard fixed counters
|
||||
void fill_fixed_counters_for_influxdb(const subnet_counter_t& counter,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map,
|
||||
bool populate_flow) {
|
||||
fill_main_counters_for_influxdb(counter, plain_total_counters_map, populate_flow);
|
||||
|
||||
bool influxdb_per_protocol_counters = false;
|
||||
|
||||
if (influxdb_per_protocol_counters) {
|
||||
fill_per_protocol_countres_for_influxdb(counter, plain_total_counters_map);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Push host traffic to InfluxDB
|
||||
bool push_hosts_ipv6_traffic_counters_to_influxdb(std::string influx_database,
|
||||
std::string influx_host,
|
||||
std::string influx_port,
|
||||
bool enable_auth,
|
||||
std::string influx_user,
|
||||
std::string influx_password) {
|
||||
std::vector<std::pair<subnet_ipv6_cidr_mask_t, subnet_counter_t>> speed_elements;
|
||||
template <typename T, typename C>
|
||||
// Apply limitation on type of keys because we use special string conversion function inside and we must not instantiate it for other unknown types
|
||||
requires(std::is_same_v<T, subnet_ipv6_cidr_mask_t> || std::is_same_v<T, uint32_t>) &&
|
||||
(std::is_same_v<C, subnet_counter_t>)bool push_hosts_traffic_counters_to_influxdb(abstract_subnet_counters_t<T, C>& host_counters,
|
||||
const std::string& influx_database,
|
||||
const std::string& influx_host,
|
||||
const std::string& influx_port,
|
||||
bool enable_auth,
|
||||
const std::string& influx_user,
|
||||
const std::string& influx_password,
|
||||
const std::string& measurement,
|
||||
const std::string& tag_name) {
|
||||
|
||||
std::vector<std::pair<T, C>> speed_elements;
|
||||
|
||||
// TODO: preallocate memory here for this array to avoid memory allocations under the lock
|
||||
ipv6_host_counters.get_all_non_zero_average_speed_elements_as_pairs(speed_elements);
|
||||
host_counters.get_all_non_zero_average_speed_elements_as_pairs(speed_elements);
|
||||
|
||||
// Structure for InfluxDB
|
||||
std::vector<std::pair<std::string, std::map<std::string, uint64_t>>> hosts_vector;
|
||||
@ -154,9 +200,21 @@ bool push_hosts_ipv6_traffic_counters_to_influxdb(std::string influx_database,
|
||||
for (const auto& speed_element : speed_elements) {
|
||||
std::map<std::string, uint64_t> plain_total_counters_map;
|
||||
|
||||
std::string client_ip_as_string = print_ipv6_address(speed_element.first.subnet_address);
|
||||
std::string client_ip_as_string;
|
||||
|
||||
fill_main_counters_for_influxdb(&speed_element.second, plain_total_counters_map, true);
|
||||
if constexpr (std::is_same_v<T, subnet_ipv6_cidr_mask_t>) {
|
||||
// We use pretty strange encoding here which encodes IPv6 address as subnet but
|
||||
// then we just discard CIDR mask because it does not matter
|
||||
client_ip_as_string = print_ipv6_address(speed_element.first.subnet_address);
|
||||
} else if constexpr (std::is_same_v<T, uint32_t>) {
|
||||
// We use this encoding when we use
|
||||
client_ip_as_string = convert_ip_as_uint_to_string(speed_element.first);
|
||||
} else {
|
||||
logger << log4cpp::Priority::ERROR << "No match for push_hosts_traffic_counters_to_influxdb";
|
||||
return false;
|
||||
}
|
||||
|
||||
fill_fixed_counters_for_influxdb(speed_element.second, plain_total_counters_map, true);
|
||||
|
||||
hosts_vector.push_back(std::make_pair(client_ip_as_string, plain_total_counters_map));
|
||||
}
|
||||
@ -165,12 +223,14 @@ bool push_hosts_ipv6_traffic_counters_to_influxdb(std::string influx_database,
|
||||
if (hosts_vector.size() > 0) {
|
||||
influxdb_writes_total++;
|
||||
|
||||
std::string error_text;
|
||||
|
||||
bool result = write_batch_of_data_to_influxdb(influx_database, influx_host, influx_port, enable_auth, influx_user,
|
||||
influx_password, "hosts_ipv6_traffic", "host", hosts_vector);
|
||||
influx_password, measurement, tag_name, hosts_vector);
|
||||
|
||||
if (!result) {
|
||||
influxdb_writes_failed++;
|
||||
logger << log4cpp::Priority::DEBUG << "InfluxDB batch operation failed for hosts_traffic";
|
||||
logger << log4cpp::Priority::DEBUG << "InfluxDB batch operation failed for hosts_traffic with error ";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -179,7 +239,6 @@ bool push_hosts_ipv6_traffic_counters_to_influxdb(std::string influx_database,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This thread pushes data to InfluxDB
|
||||
void influxdb_push_thread() {
|
||||
// Sleep for a half second for shift against calculation thread
|
||||
@ -231,8 +290,9 @@ void influxdb_push_thread() {
|
||||
influxdb_auth, influxdb_user, influxdb_password);
|
||||
|
||||
// Push per host IPv6 counters to InfluxDB
|
||||
push_hosts_ipv6_traffic_counters_to_influxdb(influxdb_database, current_influxdb_ip_address, std::to_string(influxdb_port),
|
||||
influxdb_auth, influxdb_user, influxdb_password);
|
||||
push_hosts_traffic_counters_to_influxdb(ipv6_host_counters, influxdb_database,
|
||||
current_influxdb_ip_address, std::to_string(influxdb_port), influxdb_auth,
|
||||
influxdb_user, influxdb_password, "hosts_ipv6_traffic", "host");
|
||||
|
||||
// Push total IPv6 counters
|
||||
push_total_traffic_counters_to_influxdb(influxdb_database, current_influxdb_ip_address, std::to_string(influxdb_port),
|
||||
@ -284,7 +344,7 @@ bool push_hosts_ipv4_traffic_counters_to_influxdb(std::string influx_database,
|
||||
continue;
|
||||
}
|
||||
|
||||
fill_main_counters_for_influxdb(current_speed_element, plain_total_counters_map, true);
|
||||
fill_main_counters_for_influxdb(*current_speed_element, plain_total_counters_map, true);
|
||||
|
||||
// Key: client_ip_as_string
|
||||
hosts_vector.push_back(std::make_pair(client_ip_as_string, plain_total_counters_map));
|
||||
@ -355,7 +415,7 @@ bool push_network_traffic_counters_to_influxdb(std::string influx_database,
|
||||
const subnet_counter_t* speed = &itr.second;
|
||||
std::string subnet_as_string = convert_subnet_to_string(itr.first);
|
||||
|
||||
fill_main_counters_for_influxdb(speed, plain_total_counters_map, false);
|
||||
fill_main_counters_for_influxdb(*speed, plain_total_counters_map, false);
|
||||
|
||||
influxdb_writes_total++;
|
||||
|
||||
@ -397,50 +457,20 @@ bool write_line_of_data_to_influxdb(std::string influx_database,
|
||||
}
|
||||
|
||||
// Fills special structure which we use to export metrics into InfluxDB
|
||||
void fill_per_protocol_countres_for_influxdb(const subnet_counter_t* current_speed_element,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map) {
|
||||
plain_total_counters_map["fragmented_packets_incoming"] = current_speed_element->fragmented.in_packets;
|
||||
plain_total_counters_map["tcp_packets_incoming"] = current_speed_element->tcp.in_packets;
|
||||
plain_total_counters_map["tcp_syn_packets_incoming"] = current_speed_element->tcp_syn.in_packets;
|
||||
plain_total_counters_map["udp_packets_incoming"] = current_speed_element->udp.in_packets;
|
||||
plain_total_counters_map["icmp_packets_incoming"] = current_speed_element->icmp.in_packets;
|
||||
|
||||
plain_total_counters_map["fragmented_bits_incoming"] = current_speed_element->fragmented.in_bytes * 8;
|
||||
plain_total_counters_map["tcp_bits_incoming"] = current_speed_element->tcp.in_bytes * 8;
|
||||
plain_total_counters_map["tcp_syn_bits_incoming"] = current_speed_element->tcp_syn.in_bytes * 8;
|
||||
plain_total_counters_map["udp_bits_incoming"] = current_speed_element->udp.in_bytes * 8;
|
||||
plain_total_counters_map["icmp_bits_incoming"] = current_speed_element->icmp.in_bytes * 8;
|
||||
|
||||
|
||||
// Outgoing
|
||||
plain_total_counters_map["fragmented_packets_outgoing"] = current_speed_element->fragmented.out_packets;
|
||||
plain_total_counters_map["tcp_packets_outgoing"] = current_speed_element->tcp.out_packets;
|
||||
plain_total_counters_map["tcp_syn_packets_outgoing"] = current_speed_element->tcp_syn.out_packets;
|
||||
plain_total_counters_map["udp_packets_outgoing"] = current_speed_element->udp.out_packets;
|
||||
plain_total_counters_map["icmp_packets_outgoing"] = current_speed_element->icmp.out_packets;
|
||||
|
||||
plain_total_counters_map["fragmented_bits_outgoing"] = current_speed_element->fragmented.out_bytes * 8;
|
||||
plain_total_counters_map["tcp_bits_outgoing"] = current_speed_element->tcp.out_bytes * 8;
|
||||
plain_total_counters_map["tcp_syn_bits_outgoing"] = current_speed_element->tcp_syn.out_bytes * 8;
|
||||
plain_total_counters_map["udp_bits_outgoing"] = current_speed_element->udp.out_bytes * 8;
|
||||
plain_total_counters_map["icmp_bits_outgoing"] = current_speed_element->icmp.out_bytes * 8;
|
||||
}
|
||||
|
||||
// Fills special structure which we use to export metrics into InfluxDB
|
||||
void fill_main_counters_for_influxdb(const subnet_counter_t* current_speed_element,
|
||||
void fill_main_counters_for_influxdb(const subnet_counter_t& current_speed_element,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map,
|
||||
bool populate_flow) {
|
||||
// Prepare incoming traffic data
|
||||
plain_total_counters_map["packets_incoming"] = current_speed_element->total.in_packets;
|
||||
plain_total_counters_map["bits_incoming"] = current_speed_element->total.in_bytes * 8;
|
||||
plain_total_counters_map["packets_incoming"] = current_speed_element.total.in_packets;
|
||||
plain_total_counters_map["bits_incoming"] = current_speed_element.total.in_bytes * 8;
|
||||
|
||||
// Outdoing traffic
|
||||
plain_total_counters_map["packets_outgoing"] = current_speed_element->total.out_packets;
|
||||
plain_total_counters_map["bits_outgoing"] = current_speed_element->total.out_bytes * 8;
|
||||
plain_total_counters_map["packets_outgoing"] = current_speed_element.total.out_packets;
|
||||
plain_total_counters_map["bits_outgoing"] = current_speed_element.total.out_bytes * 8;
|
||||
|
||||
if (populate_flow) {
|
||||
plain_total_counters_map["flows_incoming"] = current_speed_element->in_flows;
|
||||
plain_total_counters_map["flows_outgoing"] = current_speed_element->out_flows;
|
||||
plain_total_counters_map["flows_incoming"] = current_speed_element.in_flows;
|
||||
plain_total_counters_map["flows_outgoing"] = current_speed_element.out_flows;
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,8 +478,8 @@ void fill_main_counters_for_influxdb(const subnet_counter_t* current_speed_eleme
|
||||
// Prepare string to insert data into InfluxDB
|
||||
std::string craft_line_for_influxdb_line_protocol(uint64_t unix_timestamp_nanoseconds,
|
||||
std::string measurement,
|
||||
std::map<std::string, std::string>& tags,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map) {
|
||||
const std::map<std::string, std::string>& tags,
|
||||
const std::map<std::string, uint64_t>& plain_total_counters_map) {
|
||||
std::stringstream buffer;
|
||||
buffer << measurement << ",";
|
||||
|
||||
|
@ -80,12 +80,12 @@ bool write_line_of_data_to_influxdb(std::string influx_database,
|
||||
void fill_per_protocol_countres_for_influxdb(const subnet_counter_t* current_speed_element,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map);
|
||||
|
||||
void fill_main_counters_for_influxdb(const subnet_counter_t* current_speed_element,
|
||||
void fill_main_counters_for_influxdb(const subnet_counter_t& current_speed_element,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map,
|
||||
bool populate_flow);
|
||||
|
||||
// Prepare string to insert data into InfluxDB
|
||||
std::string craft_line_for_influxdb_line_protocol(uint64_t unix_timestamp_nanoseconds,
|
||||
std::string measurement,
|
||||
std::map<std::string, std::string>& tags,
|
||||
std::map<std::string, uint64_t>& plain_total_counters_map);
|
||||
const std::map<std::string, std::string>& tags,
|
||||
const std::map<std::string, uint64_t>& plain_total_counters_map);
|
||||
|
Loading…
Reference in New Issue
Block a user