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.

JitsiMeetLogStorage.ts 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* eslint-disable lines-around-comment */
  2. // @ts-ignore
  3. import RTCStats from '../../rtcstats/RTCStats';
  4. // @ts-ignore
  5. import { canSendRtcstatsData } from '../../rtcstats/functions';
  6. // @ts-ignore
  7. import { getCurrentConference } from '../conference';
  8. /**
  9. * Implements log storage interface from the @jitsi/logger lib. Captured
  10. * logs are sent to CallStats.
  11. */
  12. export default class JitsiMeetLogStorage {
  13. counter: number;
  14. getState: Function;
  15. /**
  16. * Creates new <tt>JitsiMeetLogStorage</tt>.
  17. *
  18. * @param {Function} getState - The Redux store's {@code getState} method.
  19. */
  20. constructor(getState: Function) {
  21. /**
  22. * Counts each log entry, increases on every batch log entry stored.
  23. *
  24. * @type {number}
  25. */
  26. this.counter = 1;
  27. /**
  28. * The Redux store's {@code getState} method.
  29. *
  30. * @type {Function}
  31. */
  32. this.getState = getState;
  33. }
  34. /**
  35. * The JitsiMeetLogStorage is ready when the CallStats are started and
  36. * before refactoring the code it was after the conference has been joined.
  37. * A conference is considered joined when the 'conference' field is defined
  38. * in the base/conference state.
  39. *
  40. * @returns {boolean} <tt>true</tt> when this storage is ready or
  41. * <tt>false</tt> otherwise.
  42. */
  43. isReady() {
  44. const { conference } = this.getState()['features/base/conference'];
  45. return Boolean(conference);
  46. }
  47. /**
  48. * Checks whether rtcstats logs storage is enabled.
  49. *
  50. * @returns {boolean} <tt>true</tt> when this storage can store logs to
  51. * rtcstats, <tt>false</tt> otherwise.
  52. */
  53. canStoreLogsRtcstats() {
  54. const config = this.getState()['features/base/config'];
  55. // Saving the logs in RTCStats is a new feature and so there is no prior behavior that needs to be maintained.
  56. // That said, this is still experimental and needs to be rolled out gradually so we want this to be off by
  57. // default.
  58. return config?.analytics?.rtcstatsStoreLogs && canSendRtcstatsData(this.getState());
  59. }
  60. /**
  61. * Called by the <tt>LogCollector</tt> to store a series of log lines into
  62. * batch.
  63. *
  64. * @param {Array<string|Object>} logEntries - An array containing strings
  65. * representing log lines or aggregated lines objects.
  66. * @returns {void}
  67. */
  68. storeLogs(logEntries: Array<string | any>) {
  69. // XXX the config.callStatsApplicationLogsDisabled controls whether or not the logs will be sent to callstats.
  70. // this is done in LJM
  71. this.storeLogsCallstats(logEntries);
  72. if (this.canStoreLogsRtcstats()) {
  73. RTCStats.sendLogs(logEntries);
  74. }
  75. }
  76. /**
  77. * Store the console logs in callstats (if callstats is enabled).
  78. *
  79. * @param {Array<string|any>} logEntries - The log entries to send to the rtcstats server.
  80. * @returns {void}
  81. */
  82. storeLogsCallstats(logEntries: Array<string | any>) {
  83. const conference = getCurrentConference(this.getState());
  84. if (!conference || !conference.isCallstatsEnabled()) {
  85. // Discard the logs if CallStats is not enabled.
  86. return;
  87. }
  88. let logMessage = `{"log${this.counter}":"\n`;
  89. for (let i = 0, len = logEntries.length; i < len; i++) {
  90. const logEntry = logEntries[i];
  91. if (logEntry.timestamp) {
  92. logMessage += `${logEntry.timestamp} `;
  93. }
  94. if (logEntry.count > 1) {
  95. logMessage += `(${logEntry.count}) `;
  96. }
  97. logMessage += `${logEntry.text}\n`;
  98. }
  99. logMessage += '"}';
  100. this.counter += 1;
  101. // Try catch was used, because there are many variables
  102. // on the way that could be uninitialized if the storeLogs
  103. // attempt would be made very early (which is unlikely)
  104. try {
  105. conference.sendApplicationLog(logMessage);
  106. } catch (error) {
  107. // NOTE console is intentional here
  108. console.error(
  109. `Failed to store the logs, msg length: ${logMessage.length}`
  110. + `error: ${JSON.stringify(error)}`);
  111. }
  112. }
  113. }