From 9ef9ba34f43c9dc56bb4ee3dcbec80f5c4ada81f Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 8 Aug 2026 15:26:38 -0400 Subject: [PATCH] implement support to log collision events to the metrics DB; --- .../network/TrafficNetwork.MetricsLogging.cpp | 385 +++++++++++++----- src/fne/network/TrafficNetwork.h | 22 + src/fne/network/callhandler/TagAnalogData.cpp | 1 + src/fne/network/callhandler/TagDMRData.cpp | 1 + src/fne/network/callhandler/TagNXDNData.cpp | 1 + src/fne/network/callhandler/TagP25Data.cpp | 1 + 6 files changed, 298 insertions(+), 113 deletions(-) diff --git a/src/fne/network/TrafficNetwork.MetricsLogging.cpp b/src/fne/network/TrafficNetwork.MetricsLogging.cpp index 0c0e04cf..866d6d36 100644 --- a/src/fne/network/TrafficNetwork.MetricsLogging.cpp +++ b/src/fne/network/TrafficNetwork.MetricsLogging.cpp @@ -66,6 +66,7 @@ namespace { DIAG, CALL_EVENT, CALL_ERROR_EVENT, + CALL_COLLISION_EVENT, TSBK_EVENT, CSBK_EVENT, COUNTER_EVENT @@ -98,6 +99,13 @@ namespace { std::string counterKey; uint64_t counterValue; + uint32_t rxPeerId; + uint32_t rxStreamId; + uint32_t rxSrcId; + uint32_t rxDstId; + uint8_t rxSlot; + bool hasRxSlot; + /** * @brief Default constructor for MetricEvent. Initializes all members to default values. */ @@ -112,7 +120,13 @@ namespace { slotNo(0U), hasSlot(false), counterKey(), - counterValue(0U) + counterValue(0U), + rxPeerId(0U), + rxStreamId(0U), + rxSrcId(0U), + rxDstId(0U), + rxSlot(0U), + hasRxSlot(false) { /* stub */ } @@ -130,6 +144,7 @@ namespace { sqlite3_stmt* diag; sqlite3_stmt* callEvent; sqlite3_stmt* callErrorEvent; + sqlite3_stmt* callCollisionEvent; sqlite3_stmt* tsbkEvent; sqlite3_stmt* csbkEvent; sqlite3_stmt* counterUpsert; @@ -144,6 +159,7 @@ namespace { callErrorEvent(nullptr), tsbkEvent(nullptr), csbkEvent(nullptr), + callCollisionEvent(nullptr), counterUpsert(nullptr) { /* stub */ @@ -233,6 +249,10 @@ namespace { sqlite3_finalize(stmts.callErrorEvent); stmts.callErrorEvent = nullptr; } + if (stmts.callCollisionEvent != nullptr) { + sqlite3_finalize(stmts.callCollisionEvent); + stmts.callCollisionEvent = nullptr; + } if (stmts.tsbkEvent != nullptr) { sqlite3_finalize(stmts.tsbkEvent); stmts.tsbkEvent = nullptr; @@ -281,6 +301,8 @@ namespace { return false; if (!prepareStatement(db, "INSERT INTO call_error_event(ts_ns, peer_id, stream_id, src_id, dst_id, message, slot) VALUES(?, ?, ?, ?, ?, ?, ?);", &stmts.callErrorEvent)) return false; + if (!prepareStatement(db, "INSERT INTO call_collision_event(ts_ns, peer_id, stream_id, src_id, dst_id, slot, rx_peer_id, rx_stream_id, rx_src_id, rx_dst_id, rx_slot) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", &stmts.callCollisionEvent)) + return false; if (!prepareStatement(db, "INSERT INTO tsbk_event(ts_ns, peer_id, lco, tsbk, raw) VALUES(?, ?, ?, ?, ?);", &stmts.tsbkEvent)) return false; if (!prepareStatement(db, "INSERT INTO csbk_event(ts_ns, peer_id, lco, csbk, raw) VALUES(?, ?, ?, ?, ?);", &stmts.csbkEvent)) @@ -396,6 +418,43 @@ namespace { } return execStepAndReset(stmt); + case MetricEventType::CALL_COLLISION_EVENT: + stmt = stmts.callCollisionEvent; + if (stmt == nullptr) return false; + if (sqlite3_bind_int64(stmt, 1, (sqlite3_int64)e.tsNs) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 2, (int)e.peerId) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 3, (int)e.streamId) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 4, (int)e.srcId) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 5, (int)e.dstId) != SQLITE_OK) + return false; + if (e.hasSlot) { + if (sqlite3_bind_int(stmt, 6, (int)e.slotNo) != SQLITE_OK) + return false; + } else { + if (sqlite3_bind_null(stmt, 6) != SQLITE_OK) + return false; + } + if (sqlite3_bind_int(stmt, 7, (int)e.rxPeerId) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 8, (int)e.rxStreamId) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 9, (int)e.rxSrcId) != SQLITE_OK) + return false; + if (sqlite3_bind_int(stmt, 10, (int)e.rxDstId) != SQLITE_OK) + return false; + if (e.hasRxSlot) { + if (sqlite3_bind_int(stmt, 11, (int)e.rxSlot) != SQLITE_OK) + return false; + } else { + if (sqlite3_bind_null(stmt, 11) != SQLITE_OK) + return false; + } + return execStepAndReset(stmt); + case MetricEventType::TSBK_EVENT: stmt = stmts.tsbkEvent; if (stmt == nullptr) return false; @@ -499,6 +558,7 @@ namespace { "diag", "call_event", "call_error_event", + "call_collision_event", "tsbk_event", "csbk_event" }; @@ -754,20 +814,10 @@ void TrafficNetwork::MetricsLogging::initialize(TrafficNetwork* network) } } - // is this a new SQLite metrics database? - if (isSQLiteBlank(network)) { - initializeSQLite(network); - } + // ensure SQLite metrics schema is present for both new and existing databases + initializeSQLite(network); if (network->m_sqliteDB != nullptr) { - // ensure the SQLite counter table exists - if (!ensureSQLiteCounterTable(network)) { - sqlite3_close(network->m_sqliteDB); - network->m_sqliteDB = nullptr; - network->m_enableSQLite = false; - return; - } - // load existing SQLite metrics counters loadSQLiteCounters(network); @@ -1168,6 +1218,57 @@ void TrafficNetwork::MetricsLogging::logCallErrorEvent(TrafficNetwork* network, } } +/* Logs a call collision event with slot number. */ + +void TrafficNetwork::MetricsLogging::logCallCollisionEvent(TrafficNetwork* network, uint32_t peerId, uint32_t streamId, uint32_t srcId, + uint32_t dstId, uint8_t slotNo, uint32_t rxPeerId, uint32_t rxStreamId, uint32_t rxSrcId, uint32_t rxDstId, uint8_t rxSlot) +{ + if (network == nullptr || !network->m_enableMetrics) + return; + + uint64_t ts = nowNs(); + + if (network->m_enableInfluxDB) { + influxdb::QueryBuilder() + .meas("call_collision_event") + .tag("peerId", std::to_string(peerId)) + .tag("streamId", std::to_string(streamId)) + .tag("srcId", std::to_string(srcId)) + .tag("dstId", std::to_string(dstId)) + .tag("rxPeerId", std::to_string(rxPeerId)) + .tag("rxStreamId", std::to_string(rxStreamId)) + .tag("rxSrcId", std::to_string(rxSrcId)) + .tag("rxDstId", std::to_string(rxDstId)) + .field("slot", slotNo) + .field("rxSlot", rxSlot) + .timestamp(ts) + .requestAsync(network->m_influxServer); + } + + if (network->m_enableSQLite && network->m_sqliteDB != nullptr) { + MetricEvent e; + e.type = MetricEventType::CALL_COLLISION_EVENT; + e.tsNs = ts; + e.peerId = peerId; + e.streamId = streamId; + e.srcId = srcId; + e.dstId = dstId; + e.rxPeerId = rxPeerId; + e.rxStreamId = rxStreamId; + e.rxSrcId = rxSrcId; + e.rxDstId = rxDstId; + if (slotNo != 0U) { + e.hasSlot = true; + e.slotNo = slotNo; + } + if (rxSlot != 0U) { + e.hasRxSlot = true; + e.rxSlot = rxSlot; + } + enqueueSQLiteMetric(network, std::move(e)); + } +} + /* Logs a P25 TSBK raw event. */ void TrafficNetwork::MetricsLogging::logTSBKEvent(TrafficNetwork* network, uint32_t peerId, const std::string& lco, const std::string& tsbk, @@ -1272,108 +1373,34 @@ void TrafficNetwork::MetricsLogging::initializeSQLite(TrafficNetwork* network) return; if (!network->m_enableSQLite) return; + if (network->m_sqliteDB == nullptr) + return; - std::string sql = R"( -PRAGMA journal_mode = WAL; -PRAGMA synchronous = NORMAL; -PRAGMA foreign_keys = ON; - -CREATE TABLE activity ( - id INTEGER PRIMARY KEY, - ts_ns INTEGER NOT NULL, - ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, - peer_id INTEGER NOT NULL, - identity TEXT NOT NULL, - msg TEXT NOT NULL -); - -CREATE INDEX idx_activity_time ON activity(ts_ns); -CREATE INDEX idx_activity_peer_time ON activity(peer_id, ts_ns); - -CREATE TABLE diag ( - id INTEGER PRIMARY KEY, - ts_ns INTEGER NOT NULL, - ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, - peer_id INTEGER NOT NULL, - identity TEXT NOT NULL, - msg TEXT NOT NULL -); - -CREATE INDEX idx_diag_time ON diag(ts_ns); -CREATE INDEX idx_diag_peer_time ON diag(peer_id, ts_ns); - -CREATE TABLE call_event ( - id INTEGER PRIMARY KEY, - ts_ns INTEGER NOT NULL, - ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, - peer_id INTEGER NOT NULL, - mode TEXT NOT NULL CHECK (mode IN ('Analog','DMR','NXDN','P25')), - stream_id INTEGER NOT NULL, - src_id INTEGER NOT NULL, - dst_id INTEGER NOT NULL, - duration_ms INTEGER NOT NULL, - slot INTEGER NULL -); - -CREATE INDEX idx_call_event_time ON call_event(ts_ns); -CREATE INDEX idx_call_event_mode_time ON call_event(mode, ts_ns); -CREATE INDEX idx_call_event_peer_time ON call_event(peer_id, ts_ns); -CREATE INDEX idx_call_event_dst_time ON call_event(dst_id, ts_ns); -CREATE INDEX idx_call_event_stream ON call_event(stream_id); - -CREATE TABLE call_error_event ( - id INTEGER PRIMARY KEY, - ts_ns INTEGER NOT NULL, - ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, - peer_id INTEGER NOT NULL, - stream_id INTEGER NOT NULL, - src_id INTEGER NOT NULL, - dst_id INTEGER NOT NULL, - message TEXT NOT NULL, - slot INTEGER NULL -); - -CREATE INDEX idx_call_error_time ON call_error_event(ts_ns); -CREATE INDEX idx_call_error_peer_time ON call_error_event(peer_id, ts_ns); -CREATE INDEX idx_call_error_message_time ON call_error_event(message, ts_ns); -CREATE INDEX idx_call_error_stream ON call_error_event(stream_id); - -CREATE TABLE tsbk_event ( - id INTEGER PRIMARY KEY, - ts_ns INTEGER NOT NULL, - ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, - peer_id INTEGER NOT NULL, - lco TEXT NOT NULL, - tsbk TEXT NOT NULL, - raw TEXT NOT NULL -); - -CREATE INDEX idx_tsbk_time ON tsbk_event(ts_ns); -CREATE INDEX idx_tsbk_peer_time ON tsbk_event(peer_id, ts_ns); -CREATE INDEX idx_tsbk_lco_time ON tsbk_event(lco, ts_ns); - -CREATE TABLE csbk_event ( - id INTEGER PRIMARY KEY, - ts_ns INTEGER NOT NULL, - ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, - peer_id INTEGER NOT NULL, - lco TEXT NOT NULL, - csbk TEXT NOT NULL, - raw TEXT NOT NULL -); - -CREATE INDEX idx_csbk_time ON csbk_event(ts_ns); -CREATE INDEX idx_csbk_peer_time ON csbk_event(peer_id, ts_ns); -CREATE INDEX idx_csbk_lco_time ON csbk_event(lco, ts_ns); - -CREATE TABLE IF NOT EXISTS metrics_counters ( - key TEXT PRIMARY KEY, - value INTEGER NOT NULL -); -)"; + if (sqlite3_exec(network->m_sqliteDB, "PRAGMA journal_mode = WAL;", nullptr, nullptr, nullptr) != SQLITE_OK) { + LogError(LOG_MASTER, "Error setting SQLite journal_mode, error: %s", sqlite3_errmsg(network->m_sqliteDB)); + sqlite3_close(network->m_sqliteDB); + network->m_sqliteDB = nullptr; + network->m_enableSQLite = false; + return; + } - if (sqlite3_exec(network->m_sqliteDB, sql.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK) { - LogError(LOG_MASTER, "Error creating SQLite tables, error: %s", sqlite3_errmsg(network->m_sqliteDB)); + if (sqlite3_exec(network->m_sqliteDB, "PRAGMA synchronous = NORMAL;", nullptr, nullptr, nullptr) != SQLITE_OK) { + LogError(LOG_MASTER, "Error setting SQLite synchronous mode, error: %s", sqlite3_errmsg(network->m_sqliteDB)); + sqlite3_close(network->m_sqliteDB); + network->m_sqliteDB = nullptr; + network->m_enableSQLite = false; + return; + } + + if (sqlite3_exec(network->m_sqliteDB, "PRAGMA foreign_keys = ON;", nullptr, nullptr, nullptr) != SQLITE_OK) { + LogError(LOG_MASTER, "Error enabling SQLite foreign_keys, error: %s", sqlite3_errmsg(network->m_sqliteDB)); + sqlite3_close(network->m_sqliteDB); + network->m_sqliteDB = nullptr; + network->m_enableSQLite = false; + return; + } + + if (!ensureSQLiteMetricTables(network)) { sqlite3_close(network->m_sqliteDB); network->m_sqliteDB = nullptr; network->m_enableSQLite = false; @@ -1398,6 +1425,138 @@ bool TrafficNetwork::MetricsLogging::ensureSQLiteCounterTable(TrafficNetwork* ne return true; } +/* Ensures all SQLite metric tables and indexes exist. */ + +bool TrafficNetwork::MetricsLogging::ensureSQLiteMetricTables(TrafficNetwork* network) +{ + if (network == nullptr || network->m_sqliteDB == nullptr) { + return false; + } + + // SQLite schema statements for creating metric tables and indexes + const char* schemaStatements[] = { + // Activity table and indexes +R"(CREATE TABLE IF NOT EXISTS activity ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + identity TEXT NOT NULL, + msg TEXT NOT NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_activity_time ON activity(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_activity_peer_time ON activity(peer_id, ts_ns);", + + // Diagnostic table and indexes +R"(CREATE TABLE IF NOT EXISTS diag ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + identity TEXT NOT NULL, + msg TEXT NOT NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_diag_time ON diag(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_diag_peer_time ON diag(peer_id, ts_ns);", + + // Call event table and indexes +R"(CREATE TABLE IF NOT EXISTS call_event ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + mode TEXT NOT NULL CHECK (mode IN ('Analog','DMR','NXDN','P25')), + stream_id INTEGER NOT NULL, + src_id INTEGER NOT NULL, + dst_id INTEGER NOT NULL, + duration_ms INTEGER NOT NULL, + slot INTEGER NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_call_event_time ON call_event(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_event_mode_time ON call_event(mode, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_event_peer_time ON call_event(peer_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_event_dst_time ON call_event(dst_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_event_stream ON call_event(stream_id);", + + // Call error event table and indexes +R"(CREATE TABLE IF NOT EXISTS call_error_event ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + stream_id INTEGER NOT NULL, + src_id INTEGER NOT NULL, + dst_id INTEGER NOT NULL, + message TEXT NOT NULL, + slot INTEGER NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_call_error_time ON call_error_event(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_error_peer_time ON call_error_event(peer_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_error_message_time ON call_error_event(message, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_error_stream ON call_error_event(stream_id);", + + // Call collision event table and indexes +R"(CREATE TABLE IF NOT EXISTS call_collision_event ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + stream_id INTEGER NOT NULL, + src_id INTEGER NOT NULL, + dst_id INTEGER NOT NULL, + slot INTEGER NULL, + rx_peer_id INTEGER NOT NULL, + rx_stream_id INTEGER NOT NULL, + rx_src_id INTEGER NOT NULL, + rx_dst_id INTEGER NOT NULL, + rx_slot INTEGER NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_call_collision_time ON call_collision_event(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_collision_peer_time ON call_collision_event(peer_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_collision_stream ON call_collision_event(stream_id);", + "CREATE INDEX IF NOT EXISTS idx_call_collision_rx_peer_time ON call_collision_event(rx_peer_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_call_collision_rx_stream ON call_collision_event(rx_stream_id);", + + // TSBK event table and indexes +R"(CREATE TABLE IF NOT EXISTS tsbk_event ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + lco TEXT NOT NULL, + tsbk TEXT NOT NULL, + raw TEXT NOT NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_tsbk_time ON tsbk_event(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_tsbk_peer_time ON tsbk_event(peer_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_tsbk_lco_time ON tsbk_event(lco, ts_ns);", + + // CSBK event table and indexes +R"(CREATE TABLE IF NOT EXISTS csbk_event ( + id INTEGER PRIMARY KEY, + ts_ns INTEGER NOT NULL, + ts_s REAL GENERATED ALWAYS AS (ts_ns / 1000000000.0) STORED, + peer_id INTEGER NOT NULL, + lco TEXT NOT NULL, + csbk TEXT NOT NULL, + raw TEXT NOT NULL +);)", + "CREATE INDEX IF NOT EXISTS idx_csbk_time ON csbk_event(ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_csbk_peer_time ON csbk_event(peer_id, ts_ns);", + "CREATE INDEX IF NOT EXISTS idx_csbk_lco_time ON csbk_event(lco, ts_ns);" + }; + + // execute each schema statement to ensure the SQLite database has the necessary tables and indexes + for (const char* statement : schemaStatements) { + if (sqlite3_exec(network->m_sqliteDB, statement, nullptr, nullptr, nullptr) != SQLITE_OK) { + LogError(LOG_MASTER, "Error ensuring SQLite metrics schema, error: %s", sqlite3_errmsg(network->m_sqliteDB)); + return false; + } + } + + return ensureSQLiteCounterTable(network); +} + /* Loads persisted metrics counters from SQLite. */ void TrafficNetwork::MetricsLogging::loadSQLiteCounters(TrafficNetwork* network) diff --git a/src/fne/network/TrafficNetwork.h b/src/fne/network/TrafficNetwork.h index 29944d6f..5aa7d1cf 100644 --- a/src/fne/network/TrafficNetwork.h +++ b/src/fne/network/TrafficNetwork.h @@ -1131,6 +1131,22 @@ namespace network * @param slotNo Slot number. */ static void logCallErrorEvent(TrafficNetwork* network, uint32_t peerId, uint32_t streamId, uint32_t srcId, uint32_t dstId, const std::string& message, uint8_t slotNo); + /** + * @brief Logs a call collision event with slot number. + * @param network Pointer to the TrafficNetwork instance. + * @param peerId Peer ID. + * @param streamId Stream ID. + * @param srcId Source ID. + * @param dstId Destination ID. + * @param slotNo Slot number. + * @param rxPeerId Received peer ID. + * @param rxStreamId Received stream ID. + * @param rxSrcId Received source ID. + * @param rxDstId Received destination ID. + * @param rxSlot Received slot number. + */ + static void logCallCollisionEvent(TrafficNetwork* network, uint32_t peerId, uint32_t streamId, uint32_t srcId, uint32_t dstId, uint8_t slotNo, + uint32_t rxPeerId, uint32_t rxStreamId, uint32_t rxSrcId, uint32_t rxDstId, uint8_t rxSlot); /** * @brief Logs a P25 TSBK raw event. * @param network Pointer to the TrafficNetwork instance. @@ -1172,6 +1188,12 @@ namespace network * @return True if the table exists (or was created), false on error. */ static bool ensureSQLiteCounterTable(TrafficNetwork* network); + /** + * @brief Ensures all SQLite metrics tables and indexes exist. + * @param network Pointer to the TrafficNetwork instance. + * @return True if all schema objects exist (or were created), false on error. + */ + static bool ensureSQLiteMetricTables(TrafficNetwork* network); /** * @brief Loads persisted metrics counters from SQLite. * @param network Pointer to the TrafficNetwork instance. diff --git a/src/fne/network/callhandler/TagAnalogData.cpp b/src/fne/network/callhandler/TagAnalogData.cpp index f30e7559..7894602e 100644 --- a/src/fne/network/callhandler/TagAnalogData.cpp +++ b/src/fne/network/callhandler/TagAnalogData.cpp @@ -269,6 +269,7 @@ bool TagAnalogData::processFrame(const uint8_t* data, uint32_t len, uint32_t pee m_rejectedCallStreams.unlock(); TrafficNetwork::MetricsLogging::incrementCallCollisions(m_network); + TrafficNetwork::MetricsLogging::logCallCollisionEvent(m_network, peerId, streamId, srcId, dstId, 0U, status.peerId, status.streamId, status.srcId, status.dstId, 0U); return false; } diff --git a/src/fne/network/callhandler/TagDMRData.cpp b/src/fne/network/callhandler/TagDMRData.cpp index b515a5e8..62310996 100644 --- a/src/fne/network/callhandler/TagDMRData.cpp +++ b/src/fne/network/callhandler/TagDMRData.cpp @@ -397,6 +397,7 @@ bool TagDMRData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId m_rejectedCallStreams.unlock(); TrafficNetwork::MetricsLogging::incrementCallCollisions(m_network); + TrafficNetwork::MetricsLogging::logCallCollisionEvent(m_network, peerId, streamId, srcId, dstId, slotNo, status.peerId, status.streamId, status.srcId, status.dstId, status.slotNo); return false; } diff --git a/src/fne/network/callhandler/TagNXDNData.cpp b/src/fne/network/callhandler/TagNXDNData.cpp index 2b8382fa..f3f0522a 100644 --- a/src/fne/network/callhandler/TagNXDNData.cpp +++ b/src/fne/network/callhandler/TagNXDNData.cpp @@ -424,6 +424,7 @@ bool TagNXDNData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerI m_rejectedCallStreams.unlock(); TrafficNetwork::MetricsLogging::incrementCallCollisions(m_network); + TrafficNetwork::MetricsLogging::logCallCollisionEvent(m_network, peerId, streamId, srcId, dstId, 0U, status.peerId, status.streamId, status.srcId, status.dstId, 0U); return false; } diff --git a/src/fne/network/callhandler/TagP25Data.cpp b/src/fne/network/callhandler/TagP25Data.cpp index 949bce95..b2dfeb00 100644 --- a/src/fne/network/callhandler/TagP25Data.cpp +++ b/src/fne/network/callhandler/TagP25Data.cpp @@ -504,6 +504,7 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId m_rejectedCallStreams.unlock(); TrafficNetwork::MetricsLogging::incrementCallCollisions(m_network); + TrafficNetwork::MetricsLogging::logCallCollisionEvent(m_network, peerId, streamId, srcId, dstId, 0U, status.peerId, status.streamId, status.srcId, status.dstId, 0U); return false; }