You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RTCStats.ts 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* eslint-disable lines-around-comment */
  2. import {
  3. PC_CON_STATE_CHANGE,
  4. PC_STATE_CONNECTED,
  5. PC_STATE_FAILED
  6. // @ts-expect-error
  7. } from '@jitsi/rtcstats/events';
  8. import JitsiMeetJS, { RTCStatsEvents } from '../base/lib-jitsi-meet';
  9. import logger from './logger';
  10. import {
  11. DominantSpeakerData,
  12. E2ERTTData,
  13. FaceLandmarksData,
  14. VideoTypeData
  15. } from './types';
  16. /**
  17. * Handle lib-jitsi-meet rtcstats events and send jitsi-meet specific statistics.
  18. */
  19. class RTCStats {
  20. private _connStateEvents: Array<any> = [];
  21. private _initialized = false;
  22. /**
  23. * Handles rtcstats events.
  24. *
  25. * @returns {void}
  26. */
  27. init() {
  28. this._connStateEvents = [];
  29. if (!this._initialized) {
  30. JitsiMeetJS.rtcstats.on(
  31. RTCStatsEvents.RTC_STATS_PC_EVENT,
  32. (pcEvent: any) => this.handleRTCStatsEvent(pcEvent));
  33. this._initialized = true;
  34. }
  35. }
  36. /**
  37. * Send console logs to rtcstats server.
  38. *
  39. * @param {Array<string|any>} logEntries - The log entries to send to the rtcstats server.
  40. * @returns {void}
  41. */
  42. sendLogs(logEntries: Array<string | any>) {
  43. JitsiMeetJS.rtcstats.sendStatsEntry('logs', logEntries);
  44. }
  45. /**
  46. * Send dominant speaker data, the data will be processed by rtcstats-server and saved in the dump file.
  47. *
  48. * @param {Object} dominantSpeakerData - Dominant speaker data to be saved in the rtcstats dump.
  49. * @returns {void}
  50. */
  51. sendDominantSpeakerData(dominantSpeakerData: DominantSpeakerData) {
  52. JitsiMeetJS.rtcstats.sendStatsEntry('dominantSpeaker', dominantSpeakerData);
  53. }
  54. /**
  55. * Send e2e rtt data, the data will be processed by rtcstats-server and saved in the dump file.
  56. *
  57. * @param {Object} e2eRttData - The object that holds the e2e data.
  58. * @returns {void}
  59. */
  60. sendE2ERTTData(e2eRttData: E2ERTTData) {
  61. JitsiMeetJS.rtcstats.sendStatsEntry('e2eRtt', e2eRttData);
  62. }
  63. /**
  64. * Send identity data, the data will be processed by rtcstats-server and saved in the dump file.
  65. *
  66. * @param {Object} identityData - The object that holds the identity data.
  67. * @returns {void}
  68. */
  69. sendIdentityData(identityData: Object) {
  70. JitsiMeetJS.rtcstats.sendIdentityEntry(identityData);
  71. }
  72. /**
  73. * Send the timestamp of the start of the conference, the data will be processed by the rtcstats-server
  74. * and saved in the dump file.
  75. *
  76. * @param {Object} timestamp - The object which contains the timestamp.
  77. * @returns {void}
  78. */
  79. sendConferenceTimestamp(timestamp: number) {
  80. JitsiMeetJS.rtcstats.sendStatsEntry('conferenceStartTimestamp', timestamp);
  81. }
  82. /**
  83. * Send videoType data, the data will be processed by rtcstats-server and saved in the dump file.
  84. *
  85. * @param {Object} videoTypeData - The object that holds the videoType data.
  86. * @returns {void}
  87. */
  88. sendVideoTypeData(videoTypeData: VideoTypeData) {
  89. JitsiMeetJS.rtcstats.sendStatsEntry('setVideoType', videoTypeData);
  90. }
  91. /**
  92. * Send face landmarks data, the data will be processed by rtcstats-server and saved in the dump file.
  93. *
  94. * @param {Object} faceLandmarksData - Face landmarks data to be saved in the rtcstats dump.
  95. * @returns {void}
  96. */
  97. sendFaceLandmarksData(faceLandmarksData: FaceLandmarksData) {
  98. JitsiMeetJS.rtcstats.sendStatsEntry('faceLandmarks', faceLandmarksData);
  99. }
  100. /**
  101. * RTCStats client can notify the APP of any PeerConnection related event that occurs.
  102. *
  103. * @param {Object} event - The PeerConnection event.
  104. * @param {string} event.type - The event type.
  105. * @param {Object} event.body - Event body.
  106. * @param {string} event.body.isP2P - PeerConnection type.
  107. * @param {string} event.body.state - PeerConnection state change which triggered the event.
  108. * @returns {void}
  109. */
  110. handleRTCStatsEvent(event: any) {
  111. switch (event.type) {
  112. case PC_CON_STATE_CHANGE: {
  113. const { body: { isP2P = null, state = null } } = event;
  114. this._connStateEvents.push(event.body);
  115. // We only report PC related connection issues. If the rtcstats websocket is not connected at this point
  116. // it usually means that none of our services can be reached i.e. there's problem with the internet
  117. // connection and not necessarily with reaching the JVB (due to a firewall or other reasons).
  118. if (state === PC_STATE_FAILED) {
  119. const connectionType = isP2P ? 'P2P' : 'JVB';
  120. const wasConnected = this._connStateEvents.some((connectionEvent: { isP2P: any; state: string; }) =>
  121. (connectionEvent.isP2P === isP2P) && (connectionEvent.state === PC_STATE_CONNECTED));
  122. logger.info(`${connectionType} PeerConnection failed, previously connected: ${wasConnected}`);
  123. if (typeof APP !== 'undefined') {
  124. APP.API.notifyPeerConnectionFailure(isP2P, wasConnected);
  125. }
  126. }
  127. break;
  128. }
  129. }
  130. }
  131. }
  132. export default new RTCStats();