From b83b5694052d2a5a30aecd7da2efbf44f39742b6 Mon Sep 17 00:00:00 2001
From: Stanislav Lashmanov <slashmanov@gitlab.com>
Date: Fri, 7 Mar 2025 17:43:34 +0400
Subject: [PATCH] Instrument Rapid Diffs list loading

---
 .../rapid_diffs/stores/diffs_list.js            | 11 +++++++++++
 .../rapid_diffs/app_component.html.haml         | 10 ++++++++++
 .../rapid_diffs/stores/diffs_list_spec.js       | 17 +++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/app/assets/javascripts/rapid_diffs/stores/diffs_list.js b/app/assets/javascripts/rapid_diffs/stores/diffs_list.js
index d8f4adb01bffa..84edbcf5ec9cd 100644
--- a/app/assets/javascripts/rapid_diffs/stores/diffs_list.js
+++ b/app/assets/javascripts/rapid_diffs/stores/diffs_list.js
@@ -4,6 +4,7 @@ import { renderHtmlStreams } from '~/streaming/render_html_streams';
 import { toPolyfillReadable } from '~/streaming/polyfills';
 import { DiffFile } from '~/rapid_diffs/diff_file';
 import { DIFF_FILE_MOUNTED } from '~/rapid_diffs/dom_events';
+import { performanceMarkAndMeasure } from '~/performance/utils';
 
 export const statuses = {
   idle: 'idle',
@@ -66,6 +67,16 @@ export const useDiffsList = defineStore('diffsList', {
           document.querySelector('#js-stream-container'),
           signal,
         );
+        performanceMarkAndMeasure({
+          mark: 'rapid-diffs-list-loaded',
+          measures: [
+            {
+              name: 'rapid-diffs-list-loading',
+              start: 'rapid-diffs-first-diff-file-shown',
+              end: 'rapid-diffs-list-loaded',
+            },
+          ],
+        });
       });
     },
     reloadDiffs(url) {
diff --git a/app/components/rapid_diffs/app_component.html.haml b/app/components/rapid_diffs/app_component.html.haml
index 62c78497877f8..9be3beefaf399 100644
--- a/app/components/rapid_diffs/app_component.html.haml
+++ b/app/components/rapid_diffs/app_component.html.haml
@@ -9,9 +9,19 @@
     .rd-app-content{ data: { sidebar_visible: true } }
       .code{ class: helpers.user_color_scheme }
         %div{ data: { diffs_list: true } }
+          = javascript_tag nonce: content_security_policy_nonce do
+            :plain
+              requestAnimationFrame(() => { window.performance.mark('rapid-diffs-first-diff-file-shown') })
           - if diffs_list?
             = diffs_list
           - else
             = render RapidDiffs::DiffFileComponent.with_collection(@diffs_slice, parallel_view: @diff_view == :parallel)
           - if @stream_url
             #js-stream-container{ data: { diffs_stream_url: @stream_url } }
+          - else
+            = javascript_tag nonce: content_security_policy_nonce do
+              :plain
+                requestAnimationFrame(() => {
+                  window.performance.mark('rapid-diffs-list-loaded');
+                  window.performance.measure('rapid-diffs-list-loading', 'rapid-diffs-first-diff-file-shown', 'rapid-diffs-list-loaded');
+                })
diff --git a/spec/frontend/rapid_diffs/stores/diffs_list_spec.js b/spec/frontend/rapid_diffs/stores/diffs_list_spec.js
index 476b3e901c24c..69982a6b41099 100644
--- a/spec/frontend/rapid_diffs/stores/diffs_list_spec.js
+++ b/spec/frontend/rapid_diffs/stores/diffs_list_spec.js
@@ -7,9 +7,11 @@ import waitForPromises from 'helpers/wait_for_promises';
 import { toPolyfillReadable } from '~/streaming/polyfills';
 import { DiffFile } from '~/rapid_diffs/diff_file';
 import { DIFF_FILE_MOUNTED } from '~/rapid_diffs/dom_events';
+import { performanceMarkAndMeasure } from '~/performance/utils';
 
 jest.mock('~/streaming/polyfills');
 jest.mock('~/streaming/render_html_streams');
+jest.mock('~/performance/utils');
 
 describe('Diffs list store', () => {
   let store;
@@ -103,6 +105,21 @@ describe('Diffs list store', () => {
       });
     });
 
+    it('measures performance', async () => {
+      await store.streamRemainingDiffs('/stream');
+      await waitForPromises();
+      expect(performanceMarkAndMeasure).toHaveBeenCalledWith({
+        mark: 'rapid-diffs-list-loaded',
+        measures: [
+          {
+            name: 'rapid-diffs-list-loading',
+            start: 'rapid-diffs-first-diff-file-shown',
+            end: 'rapid-diffs-list-loaded',
+          },
+        ],
+      });
+    });
+
     itCancelsRunningRequest(() => store.streamRemainingDiffs('/stream'));
     itSetsStatuses(() => store.streamRemainingDiffs('/stream'));
     itAddsLoadingFilesWhileStreaming(() => store.streamRemainingDiffs('/stream'));
-- 
GitLab