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.

AbstractHandler.ts 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. export interface IEvent {
  2. action?: string;
  3. actionSubject?: string;
  4. attributes?: {
  5. [key: string]: string | undefined;
  6. };
  7. name?: string;
  8. source?: string;
  9. type?: string;
  10. }
  11. interface IOptions {
  12. amplitudeAPPKey?: string;
  13. amplitudeIncludeUTM?: boolean;
  14. blackListedEvents?: string[];
  15. envType?: string;
  16. googleAnalyticsTrackingId?: string;
  17. group?: string;
  18. host?: string;
  19. matomoEndpoint?: string;
  20. matomoSiteID?: string;
  21. product?: string;
  22. subproduct?: string;
  23. user?: string;
  24. version?: string;
  25. whiteListedEvents?: string[];
  26. }
  27. /**
  28. * Abstract implementation of analytics handler.
  29. */
  30. export default class AbstractHandler {
  31. _enabled: boolean;
  32. _whiteListedEvents: Array<string> | undefined;
  33. _blackListedEvents: Array<string> | undefined;
  34. /**
  35. * Creates new instance.
  36. *
  37. * @param {Object} options - Optional parameters.
  38. */
  39. constructor(options: IOptions = {}) {
  40. this._enabled = false;
  41. this._whiteListedEvents = options.whiteListedEvents;
  42. // FIXME:
  43. // Keeping the list with the very noisy events so that we don't flood with events whoever hasn't configured
  44. // white/black lists yet. We need to solve this issue properly by either making these events not so noisy or
  45. // by removing them completely from the code.
  46. this._blackListedEvents = [
  47. ...(options.blackListedEvents || []), // eslint-disable-line no-extra-parens
  48. 'e2e_rtt', 'rtp.stats', 'rtt.by.region', 'available.device', 'stream.switch.delay', 'ice.state.changed',
  49. 'ice.duration', 'peer.conn.status.duration'
  50. ];
  51. }
  52. /**
  53. * Extracts a name for the event from the event properties.
  54. *
  55. * @param {Object} event - The analytics event.
  56. * @returns {string} - The extracted name.
  57. */
  58. _extractName(event: IEvent) {
  59. // Page events have a single 'name' field.
  60. if (event.type === 'page') {
  61. return event.name;
  62. }
  63. const {
  64. action,
  65. actionSubject,
  66. source
  67. } = event;
  68. // All events have action, actionSubject, and source fields. All
  69. // three fields are required, and often jitsi-meet and
  70. // lib-jitsi-meet use the same value when separate values are not
  71. // necessary (i.e. event.action == event.actionSubject).
  72. // Here we concatenate these three fields, but avoid adding the same
  73. // value twice, because it would only make the event's name harder
  74. // to read.
  75. let name = action;
  76. if (actionSubject && actionSubject !== action) {
  77. name = `${actionSubject}.${action}`;
  78. }
  79. if (source && source !== action) {
  80. name = `${source}.${name}`;
  81. }
  82. return name;
  83. }
  84. /**
  85. * Checks if an event should be ignored or not.
  86. *
  87. * @param {Object} event - The event.
  88. * @returns {boolean}
  89. */
  90. _shouldIgnore(event: IEvent) {
  91. if (!event || !this._enabled) {
  92. return true;
  93. }
  94. const name = this._extractName(event) ?? '';
  95. if (Array.isArray(this._whiteListedEvents)) {
  96. return this._whiteListedEvents.indexOf(name) === -1;
  97. }
  98. if (Array.isArray(this._blackListedEvents)) {
  99. return this._blackListedEvents.indexOf(name) !== -1;
  100. }
  101. return false;
  102. }
  103. }