diff --git a/lib/src/config.dart b/lib/src/config.dart index 0f901955..7dc05c9c 100644 --- a/lib/src/config.dart +++ b/lib/src/config.dart @@ -64,6 +64,9 @@ class Settings { /// ICE Gathering Timeout (in millisecond). int ice_gathering_timeout = 500; + /// Call statistics in the log + bool log_call_statistics = false; + bool terminateOnAudioMediaPortZero = false; /// Sip Message Delay (in millisecond) ( default 0 ). @@ -255,6 +258,9 @@ class Checks { }, 'ice_gathering_timeout': (Settings src, Settings? dst) { dst!.ice_gathering_timeout = src.ice_gathering_timeout; + }, + 'log_call_statistics': (Settings src, Settings? dst) { + dst!.log_call_statistics = src.log_call_statistics; } }; } diff --git a/lib/src/rtc_session.dart b/lib/src/rtc_session.dart index ac7c1cae..23f768e6 100644 --- a/lib/src/rtc_session.dart +++ b/lib/src/rtc_session.dart @@ -726,7 +726,7 @@ class RTCSession extends EventManager implements Owner { /** * Terminate the call. */ - void terminate([Map? options]) { + void terminate([Map? options]) async { logger.d('terminate()'); options = options ?? {}; @@ -844,6 +844,9 @@ class RTCSession extends EventManager implements Owner { } }); + //write call statistics to the log + await _logCallStat(); + _ended( Originator.local, null, @@ -863,6 +866,10 @@ class RTCSession extends EventManager implements Owner { {'extraHeaders': extraHeaders, 'body': body}); reason_phrase = reason_phrase ?? 'Terminated by local'; status_code = status_code ?? 200; + + //write call statistics to the log + await _logCallStat(); + _ended( Originator.local, null, @@ -1359,6 +1366,10 @@ class RTCSession extends EventManager implements Owner { case SipMethod.BYE: if (_state == RtcSessionState.confirmed) { request.reply(200); + + //write call statistics to the log + await _logCallStat(); + _ended( Originator.remote, request, @@ -1369,6 +1380,10 @@ class RTCSession extends EventManager implements Owner { } else if (_state == RtcSessionState.inviteReceived) { request.reply(200); _request.reply(487, 'BYE Received'); + + //write call statistics to the log + await _logCallStat(); + _ended( Originator.remote, request, @@ -3441,4 +3456,53 @@ class RTCSession extends EventManager implements Owner { logger.d('emit "unmuted"'); emit(EventCallUnmuted(session: this, audio: audio, video: video)); } + + Future _logCallStat() async { + if (!ua.configuration.log_call_statistics) return; + + try { + List? senders = await connection?.senders; + List? receivers = await connection?.receivers; + + RTCRtpReceiver? receiver = receivers?.firstOrNull; + RTCRtpSender? sender = senders?.firstOrNull; + + List senderStats = []; + List receiverStats = []; + + if (sender != null) { + senderStats = await sender.getStats(); + } + + if (receiver != null) { + receiverStats = await receiver.getStats(); + } + + String senderStat = 'Sender stats: \n'; + + for (StatsReport s in senderStats) { + senderStat += ' ${s.timestamp} ${s.id} ${s.type}:\n'; + s.values.forEach((key, value) { + senderStat += ' $key: $value\n'; + }); + senderStat += '\r'; + } + + logger.d(senderStat); + + String receiverStat = 'Receiver stats: \n'; + + for (StatsReport s in receiverStats) { + receiverStat += ' ${s.timestamp} ${s.id} ${s.type}\n'; + s.values.forEach((key, value) { + receiverStat += ' $key: $value\n'; + }); + receiverStat += '\r'; + } + + logger.d(receiverStat); + } catch (e) { + return; + } + } } diff --git a/lib/src/sip_ua_helper.dart b/lib/src/sip_ua_helper.dart index 288d5e60..4fb2119a 100644 --- a/lib/src/sip_ua_helper.dart +++ b/lib/src/sip_ua_helper.dart @@ -194,6 +194,7 @@ class SIPUAHelper extends EventManager { uaSettings.connectionRecoveryMinInterval; _settings.terminateOnAudioMediaPortZero = uaSettings.terminateOnMediaPortZero; + _settings.log_call_statistics = uaSettings.logCallStatistics; try { _ua = UA(_settings); @@ -899,6 +900,9 @@ class UaSettings { /// Min interval between recovery connection, default 2 sec int connectionRecoveryMinInterval = 2; + /// Allows to write advanced call statistics in the log after the call ends + bool logCallStatistics = false; + bool terminateOnMediaPortZero = false; /// Sip Message Delay (in millisecond) (default 0).