queryAnalytics.test.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import { CoreApp, DataFrame, DataQueryRequest, DataSourceApi, dateTime, LoadingState, PanelData } from '@grafana/data';
  2. import { MetaAnalyticsEventName, reportMetaAnalytics } from '@grafana/runtime';
  3. import { DashboardModel } from '../../dashboard/state';
  4. import { emitDataRequestEvent } from './queryAnalytics';
  5. beforeEach(() => {
  6. jest.clearAllMocks();
  7. });
  8. const datasource = {
  9. name: 'test',
  10. id: 1,
  11. } as DataSourceApi;
  12. const dashboardModel = new DashboardModel(
  13. { id: 1, title: 'Test Dashboard', uid: 'test' },
  14. { folderTitle: 'Test Folder' }
  15. );
  16. jest.mock('app/features/dashboard/services/DashboardSrv', () => ({
  17. getDashboardSrv: () => {
  18. return {
  19. getCurrent: () => dashboardModel,
  20. };
  21. },
  22. }));
  23. jest.mock('@grafana/runtime', () => ({
  24. ...(jest.requireActual('@grafana/runtime') as any),
  25. reportMetaAnalytics: jest.fn(),
  26. }));
  27. const mockGetUrlSearchParams = jest.fn(() => {
  28. return {};
  29. });
  30. jest.mock('@grafana/data', () => ({
  31. ...(jest.requireActual('@grafana/data') as any),
  32. urlUtil: {
  33. getUrlSearchParams: () => mockGetUrlSearchParams(),
  34. },
  35. }));
  36. const partiallyCachedSeries = [
  37. {
  38. refId: 'A',
  39. meta: {
  40. isCachedResponse: true,
  41. },
  42. fields: [],
  43. length: 0,
  44. },
  45. {
  46. refId: 'B',
  47. fields: [],
  48. length: 0,
  49. },
  50. ];
  51. const multipleDataframesWithSameRefId = [
  52. {
  53. refId: 'A',
  54. meta: {
  55. isCachedResponse: true,
  56. },
  57. fields: [],
  58. length: 0,
  59. },
  60. {
  61. refId: 'A',
  62. fields: [],
  63. length: 0,
  64. },
  65. ];
  66. function getTestData(requestApp: string, series: DataFrame[] = []): PanelData {
  67. const now = dateTime();
  68. return {
  69. request: {
  70. app: requestApp,
  71. dashboardId: 1,
  72. panelId: 2,
  73. startTime: now.unix(),
  74. endTime: now.add(1, 's').unix(),
  75. } as DataQueryRequest,
  76. series,
  77. state: LoadingState.Done,
  78. timeRange: {
  79. from: dateTime(),
  80. to: dateTime(),
  81. raw: { from: '1h', to: 'now' },
  82. },
  83. };
  84. }
  85. describe('emitDataRequestEvent - from a dashboard panel', () => {
  86. it('Should report meta analytics', () => {
  87. const data = getTestData(CoreApp.Dashboard);
  88. emitDataRequestEvent(datasource)(data);
  89. expect(reportMetaAnalytics).toBeCalledTimes(1);
  90. expect(reportMetaAnalytics).toBeCalledWith(
  91. expect.objectContaining({
  92. eventName: MetaAnalyticsEventName.DataRequest,
  93. datasourceName: datasource.name,
  94. datasourceId: datasource.id,
  95. panelId: 2,
  96. dashboardId: 1,
  97. dashboardName: 'Test Dashboard',
  98. dashboardUid: 'test',
  99. folderName: 'Test Folder',
  100. dataSize: 0,
  101. duration: 1,
  102. totalQueries: 0,
  103. cachedQueries: 0,
  104. })
  105. );
  106. });
  107. it('Should report meta analytics with counts for cached and total queries', () => {
  108. const data = getTestData(CoreApp.Dashboard, partiallyCachedSeries);
  109. emitDataRequestEvent(datasource)(data);
  110. expect(reportMetaAnalytics).toBeCalledTimes(1);
  111. expect(reportMetaAnalytics).toBeCalledWith(
  112. expect.objectContaining({
  113. eventName: MetaAnalyticsEventName.DataRequest,
  114. datasourceName: datasource.name,
  115. datasourceId: datasource.id,
  116. panelId: 2,
  117. dashboardId: 1,
  118. dashboardName: 'Test Dashboard',
  119. dashboardUid: 'test',
  120. folderName: 'Test Folder',
  121. dataSize: 2,
  122. duration: 1,
  123. totalQueries: 2,
  124. cachedQueries: 1,
  125. })
  126. );
  127. });
  128. it('Should report meta analytics with counts for cached and total queries when same refId spread across multiple DataFrames', () => {
  129. const data = getTestData(CoreApp.Dashboard, multipleDataframesWithSameRefId);
  130. emitDataRequestEvent(datasource)(data);
  131. expect(reportMetaAnalytics).toBeCalledTimes(1);
  132. expect(reportMetaAnalytics).toBeCalledWith(
  133. expect.objectContaining({
  134. eventName: MetaAnalyticsEventName.DataRequest,
  135. datasourceName: datasource.name,
  136. datasourceId: datasource.id,
  137. panelId: 2,
  138. dashboardId: 1,
  139. dashboardName: 'Test Dashboard',
  140. dashboardUid: 'test',
  141. folderName: 'Test Folder',
  142. dataSize: 2,
  143. duration: 1,
  144. totalQueries: 1,
  145. cachedQueries: 1,
  146. })
  147. );
  148. });
  149. it('Should not report meta analytics twice if the request receives multiple responses', () => {
  150. const data = getTestData(CoreApp.Dashboard);
  151. const fn = emitDataRequestEvent(datasource);
  152. fn(data);
  153. fn(data);
  154. expect(reportMetaAnalytics).toBeCalledTimes(1);
  155. });
  156. it('Should not report meta analytics in edit mode', () => {
  157. mockGetUrlSearchParams.mockImplementationOnce(() => {
  158. return { editPanel: 2 };
  159. });
  160. const data = getTestData(CoreApp.Dashboard);
  161. emitDataRequestEvent(datasource)(data);
  162. expect(reportMetaAnalytics).not.toBeCalled();
  163. });
  164. });
  165. describe('emitDataRequestEvent - from Explore', () => {
  166. const data = getTestData(CoreApp.Explore);
  167. it('Should not report meta analytics', () => {
  168. emitDataRequestEvent(datasource)(data);
  169. expect(reportMetaAnalytics).not.toBeCalled();
  170. });
  171. });