From 1faafbf023e9045e4e159fee94643ce693585344 Mon Sep 17 00:00:00 2001 From: Alex Pennells Date: Wed, 19 Nov 2025 09:36:46 -0500 Subject: [PATCH 1/3] Add Duo Code Review metrics to the Duo analytics dashboard Adds `Duo Code Review requests` and `Duo Code Review comments` to the `Duo usage metrics` table of the `GitLab Duo and SDLC trends` analytics dashboard. EE: true Changelog: added --- .../javascripts/analytics/shared/constants.js | 14 ++ doc/user/analytics/duo_and_sdlc_trends.md | 6 + .../analytics/dashboards/ai_impact/api.js | 20 +++ .../dashboards/ai_impact/constants.js | 12 ++ .../graphql/ai_metric_item.fragment.graphql | 5 + .../ai_impact_ai_metrics_table.yaml | 2 + .../ai_impact/__snapshots__/api_spec.js.snap | 142 ++++++++++++++---- .../__snapshots__/utils_spec.js.snap | 14 ++ .../dashboards/ai_impact/api_spec.js | 82 +++++++--- .../__snapshots__/metric_table_spec.js.snap | 80 ++++++++++ .../ai_impact/components/metric_table_spec.js | 4 + .../analytics/dashboards/ai_impact/helpers.js | 8 + .../dashboards/ai_impact/mock_data.js | 45 ++++++ locale/gitlab.pot | 12 ++ 14 files changed, 394 insertions(+), 52 deletions(-) diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js index d699f54db1486d..286f85b622f16e 100644 --- a/app/assets/javascripts/analytics/shared/constants.js +++ b/app/assets/javascripts/analytics/shared/constants.js @@ -201,6 +201,8 @@ export const AI_METRICS = { DUO_USAGE_RATE: 'duo_usage_rate', DUO_RCA_USAGE_RATE: 'duo_rca_usage_rate', DUO_USED_COUNT: 'duo_used_count', + DUO_REVIEW_COUNT: 'duo_review_count', + DUO_REVIEW_COMMENT_COUNT: 'duo_review_comment_count', }; export const VALUE_STREAM_METRIC_DISPLAY_UNITS = { @@ -416,6 +418,18 @@ export const VALUE_STREAM_METRIC_METADATA = { projectLink: '', docsLink: helpPagePath('user/gitlab_duo/feature_summary'), }, + [AI_METRICS.DUO_REVIEW_COUNT]: { + description: s__('AiImpactAnalytics|Number of Duo Code Review requests.'), + groupLink: '', + projectLink: '', + docsLink: helpPagePath('user/gitlab_duo/feature_summary'), + }, + [AI_METRICS.DUO_REVIEW_COMMENT_COUNT]: { + description: s__('AiImpactAnalytics|Number of Duo Code Review comments.'), + groupLink: '', + projectLink: '', + docsLink: helpPagePath('user/gitlab_duo/feature_summary'), + }, ...PIPELINE_ANALYTICS_METRIC_METADATA, }; diff --git a/doc/user/analytics/duo_and_sdlc_trends.md b/doc/user/analytics/duo_and_sdlc_trends.md index d72927e84a4289..beef9929e1d2e6 100644 --- a/doc/user/analytics/duo_and_sdlc_trends.md +++ b/doc/user/analytics/duo_and_sdlc_trends.md @@ -74,6 +74,7 @@ The **Metric trends** table displays metrics for the last six months, with month - Duo RCA usage [enabled on GitLab.com, GitLab Self-Managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/543987) in GitLab 18.3. - Duo RCA usage [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/556726) in GitLab 18.4. Feature flag `duo_rca_usage_rate` removed. - Duo features usage [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/207562) in GitLab 18.6. +- Duo Code Review requests and Duo Code Review comments [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/573979) in GitLab 18.7. {{< /history >}} @@ -105,6 +106,11 @@ The **Metric trends** table displays metrics for the last six months, with month - **Duo features usage**: Number of contributors who used any GitLab Duo feature. +- **Duo Code Review requests**: Number of Duo Code Review requests made on merge requests. + This includes requests initiated by both merge request authors and non-authors. + +- **Duo Code Review comments**: Number of comments posted by Duo Code Review on merge request diffs. + ### Development metrics - [**Lead time**](../group/value_stream_analytics/_index.md#lifecycle-metrics) diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js index 9ad53ac340b21d..57d454bb3c3427 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js @@ -45,6 +45,11 @@ export const extractGraphqlAiData = ({ rootCauseAnalysisUsersCount = null, duoAssignedUsersCount = null, duoUsedCount = null, + codeReview: { + requestReviewDuoCodeReviewOnMrByAuthorEventCount = null, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount = null, + postCommentDuoCodeReviewOnDiffEventCount = null, + } = {}, } = {}) => { const codeSuggestionsUsageRate = calculateRate({ numerator: codeSuggestionsContributorsCount, @@ -66,6 +71,13 @@ export const extractGraphqlAiData = ({ denominator: duoAssignedUsersCount, }); + const duoReviewCount = + requestReviewDuoCodeReviewOnMrByAuthorEventCount === null && + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount === null + ? '-' + : (requestReviewDuoCodeReviewOnMrByAuthorEventCount ?? 0) + + (requestReviewDuoCodeReviewOnMrByNonAuthorEventCount ?? 0); + return { [AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE]: { identifier: AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE, @@ -103,5 +115,13 @@ export const extractGraphqlAiData = ({ identifier: AI_METRICS.DUO_USED_COUNT, value: duoUsedCount ?? '-', }, + [AI_METRICS.DUO_REVIEW_COUNT]: { + identifier: AI_METRICS.DUO_REVIEW_COUNT, + value: duoReviewCount ?? '-', + }, + [AI_METRICS.DUO_REVIEW_COMMENT_COUNT]: { + identifier: AI_METRICS.DUO_REVIEW_COMMENT_COUNT, + value: postCommentDuoCodeReviewOnDiffEventCount ?? '-', + }, }; }; diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js index 2896b89bde85c9..7273ce424319b5 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js @@ -11,6 +11,8 @@ export const SUPPORTED_AI_METRICS = [ AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE, AI_METRICS.DUO_CHAT_USAGE_RATE, AI_METRICS.DUO_RCA_USAGE_RATE, + AI_METRICS.DUO_REVIEW_COUNT, + AI_METRICS.DUO_REVIEW_COMMENT_COUNT, ]; export const HIDE_METRIC_DRILL_DOWN = [ AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE, @@ -18,6 +20,8 @@ export const HIDE_METRIC_DRILL_DOWN = [ AI_METRICS.DUO_CHAT_USAGE_RATE, AI_METRICS.DUO_RCA_USAGE_RATE, AI_METRICS.DUO_USED_COUNT, + AI_METRICS.DUO_REVIEW_COUNT, + AI_METRICS.DUO_REVIEW_COMMENT_COUNT, ]; // The AI impact metrics supported for over time tiles @@ -46,6 +50,14 @@ export const AI_IMPACT_USAGE_METRICS = { label: s__('AiImpactAnalytics|Duo RCA usage'), units: UNITS.PERCENT, }, + [AI_METRICS.DUO_REVIEW_COUNT]: { + label: s__('AiImpactAnalytics|Duo Code Review requests'), + units: UNITS.COUNT, + }, + [AI_METRICS.DUO_REVIEW_COMMENT_COUNT]: { + label: s__('AiImpactAnalytics|Duo Code Review comments'), + units: UNITS.COUNT, + }, [AI_METRICS.DUO_USED_COUNT]: { label: s__('AiImpactAnalytics|Duo features usage'), units: UNITS.COUNT, diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/graphql/ai_metric_item.fragment.graphql b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/graphql/ai_metric_item.fragment.graphql index a95c993eb263fb..ebd483d0d595a5 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/graphql/ai_metric_item.fragment.graphql +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/graphql/ai_metric_item.fragment.graphql @@ -6,6 +6,11 @@ fragment AiMetricItem on AiMetrics { duoAssignedUsersCount duoUsedCount rootCauseAnalysisUsersCount + codeReview { + requestReviewDuoCodeReviewOnMrByAuthorEventCount + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount + postCommentDuoCodeReviewOnDiffEventCount + } codeSuggestions(languages: $languages) { contributorsCount shownCount diff --git a/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml b/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml index 6ba36b62cccc6d..ca6c5fb0999f6c 100644 --- a/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml +++ b/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml @@ -11,4 +11,6 @@ data: - code_suggestions_acceptance_rate - duo_chat_usage_rate - duo_rca_usage_rate + - duo_review_count + - duo_review_comment_count options: {} diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap index c7cff7ec909d4c..0625b7aa4cbe5f 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given {"codeSuggestions": [Object]} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given { codeSuggestions: { acceptedCount: 0, shownCount: 20 } } 1`] = ` { "identifier": "code_suggestions_acceptance_rate", - "tooltip": "No data", - "value": "-", + "tooltip": "0/20", + "value": 0, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given {"codeSuggestions": [Object]} 2`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given { codeSuggestions: { acceptedCount: 3 } } 1`] = ` { "identifier": "code_suggestions_acceptance_rate", "tooltip": "No data", @@ -16,7 +16,7 @@ exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_a } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given {"codeSuggestions": [Object]} 3`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given { codeSuggestions: { acceptedCount: 3, shownCount: 4 } } 1`] = ` { "identifier": "code_suggestions_acceptance_rate", "tooltip": "3/4", @@ -24,23 +24,29 @@ exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_a } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given {"codeSuggestions": [Object]} 4`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_acceptance_rate given { codeSuggestions: { shownCount: 4 } } 1`] = ` { "identifier": "code_suggestions_acceptance_rate", - "tooltip": "0/20", - "value": 0, + "tooltip": "No data", + "value": "-", } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given {"codeContributorsCount": 5} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given { + codeSuggestions: { contributorsCount: 0 }, + codeContributorsCount: 10 +} 1`] = ` { "identifier": "code_suggestions_usage_rate", - "tooltip": "No data", - "value": "-", + "tooltip": "0/10", + "value": 0, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given {"codeContributorsCount": 10, "codeSuggestions": [Object]} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given { + codeSuggestions: { contributorsCount: 5 }, + codeContributorsCount: 10 +} 1`] = ` { "identifier": "code_suggestions_usage_rate", "tooltip": "5/10", @@ -48,15 +54,15 @@ exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_u } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given {"codeContributorsCount": 10, "codeSuggestions": [Object]} 2`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given { codeContributorsCount: 5 } 1`] = ` { "identifier": "code_suggestions_usage_rate", - "tooltip": "0/10", - "value": 0, + "tooltip": "No data", + "value": "-", } `; -exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given {"codeSuggestions": [Object]} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_usage_rate given { codeSuggestions: { contributorsCount: 2 } } 1`] = ` { "identifier": "code_suggestions_usage_rate", "tooltip": "No data", @@ -64,7 +70,7 @@ exports[`AI impact dashboard api extractGraphqlAiData returns code_suggestions_u } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given {"duoAssignedUsersCount": 3} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given { duoAssignedUsersCount: 3 } 1`] = ` { "identifier": "duo_chat_usage_rate", "tooltip": "No data", @@ -72,31 +78,31 @@ exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rat } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given {"duoAssignedUsersCount": 8, "duoChatContributorsCount": 7} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given { duoChatContributorsCount: 0, duoAssignedUsersCount: 50 } 1`] = ` { "identifier": "duo_chat_usage_rate", - "tooltip": "7/8", - "value": 87.5, + "tooltip": "0/50", + "value": 0, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given {"duoAssignedUsersCount": 50, "duoChatContributorsCount": 0} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given { duoChatContributorsCount: 4 } 1`] = ` { "identifier": "duo_chat_usage_rate", - "tooltip": "0/50", - "value": 0, + "tooltip": "No data", + "value": "-", } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given {"duoChatContributorsCount": 4} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_chat_usage_rate given { duoChatContributorsCount: 7, duoAssignedUsersCount: 8 } 1`] = ` { "identifier": "duo_chat_usage_rate", - "tooltip": "No data", - "value": "-", + "tooltip": "7/8", + "value": 87.5, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given {"duoAssignedUsersCount": 3} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given { duoAssignedUsersCount: 3 } 1`] = ` { "identifier": "duo_rca_usage_rate", "tooltip": "No data", @@ -104,7 +110,15 @@ exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given {"duoAssignedUsersCount": 8, "rootCauseAnalysisUsersCount": 5} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given { rootCauseAnalysisUsersCount: 0, duoAssignedUsersCount: 50 } 1`] = ` +{ + "identifier": "duo_rca_usage_rate", + "tooltip": "0/50", + "value": 0, +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given { rootCauseAnalysisUsersCount: 5, duoAssignedUsersCount: 8 } 1`] = ` { "identifier": "duo_rca_usage_rate", "tooltip": "5/8", @@ -112,18 +126,80 @@ exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given {"duoAssignedUsersCount": 50, "rootCauseAnalysisUsersCount": 0} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given { rootCauseAnalysisUsersCount: 10 } 1`] = ` { "identifier": "duo_rca_usage_rate", - "tooltip": "0/50", + "tooltip": "No data", + "value": "-", +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_comment_count given { codeReview: { postCommentDuoCodeReviewOnDiffEventCount: 0 } } 1`] = ` +{ + "identifier": "duo_review_comment_count", "value": 0, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_rca_usage_rate given {"rootCauseAnalysisUsersCount": 10} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_comment_count given { codeReview: { postCommentDuoCodeReviewOnDiffEventCount: 25 } } 1`] = ` { - "identifier": "duo_rca_usage_rate", - "tooltip": "No data", + "identifier": "duo_review_comment_count", + "value": 25, +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_comment_count given {} 1`] = ` +{ + "identifier": "duo_review_comment_count", + "value": "-", +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { + codeReview: { + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 0, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 0 + } +} 1`] = ` +{ + "identifier": "duo_review_count", + "value": 0, +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { + codeReview: { + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 5, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 10 + } +} 1`] = ` +{ + "identifier": "duo_review_count", + "value": 15, +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { + codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 10 } +} 1`] = ` +{ + "identifier": "duo_review_count", + "value": 10, +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { + codeReview: { requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 5 } +} 1`] = ` +{ + "identifier": "duo_review_count", + "value": 5, +} +`; + +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given {} 1`] = ` +{ + "identifier": "duo_review_count", "value": "-", } `; diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap index f2200f981d888d..58e72bf41a2099 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap @@ -304,6 +304,20 @@ exports[`AI impact Dashboard utils generateSkeletonTableData returns the skeleto }, "trendStyle": "ASC", }, + { + "metric": { + "identifier": "duo_review_count", + "value": "Duo Code Review requests", + }, + "trendStyle": "ASC", + }, + { + "metric": { + "identifier": "duo_review_comment_count", + "value": "Duo Code Review comments", + }, + "trendStyle": "ASC", + }, ] `; diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js b/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js index cc5b2d7a0a408a..184593c578ef6a 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js @@ -2,25 +2,69 @@ import { extractGraphqlAiData } from 'ee/analytics/dashboards/ai_impact/api'; describe('AI impact dashboard api', () => { describe('extractGraphqlAiData', () => { - it.each` - identifier | data - ${'code_suggestions_acceptance_rate'} | ${{ codeSuggestions: { shownCount: 4 } }} - ${'code_suggestions_acceptance_rate'} | ${{ codeSuggestions: { acceptedCount: 3 } }} - ${'code_suggestions_acceptance_rate'} | ${{ codeSuggestions: { acceptedCount: 3, shownCount: 4 } }} - ${'code_suggestions_acceptance_rate'} | ${{ codeSuggestions: { acceptedCount: 0, shownCount: 20 } }} - ${'code_suggestions_usage_rate'} | ${{ codeContributorsCount: 5 }} - ${'code_suggestions_usage_rate'} | ${{ codeSuggestions: { contributorsCount: 2 } }} - ${'code_suggestions_usage_rate'} | ${{ codeSuggestions: { contributorsCount: 5 }, codeContributorsCount: 10 }} - ${'code_suggestions_usage_rate'} | ${{ codeSuggestions: { contributorsCount: 0 }, codeContributorsCount: 10 }} - ${'duo_chat_usage_rate'} | ${{ duoAssignedUsersCount: 3 }} - ${'duo_chat_usage_rate'} | ${{ duoChatContributorsCount: 4 }} - ${'duo_chat_usage_rate'} | ${{ duoChatContributorsCount: 7, duoAssignedUsersCount: 8 }} - ${'duo_chat_usage_rate'} | ${{ duoChatContributorsCount: 0, duoAssignedUsersCount: 50 }} - ${'duo_rca_usage_rate'} | ${{ duoAssignedUsersCount: 3 }} - ${'duo_rca_usage_rate'} | ${{ rootCauseAnalysisUsersCount: 10 }} - ${'duo_rca_usage_rate'} | ${{ rootCauseAnalysisUsersCount: 5, duoAssignedUsersCount: 8 }} - ${'duo_rca_usage_rate'} | ${{ rootCauseAnalysisUsersCount: 0, duoAssignedUsersCount: 50 }} - `('returns $identifier given $data', ({ identifier, data }) => { + it.each([ + ['code_suggestions_acceptance_rate', { codeSuggestions: { shownCount: 4 } }], + ['code_suggestions_acceptance_rate', { codeSuggestions: { acceptedCount: 3 } }], + [ + 'code_suggestions_acceptance_rate', + { codeSuggestions: { acceptedCount: 3, shownCount: 4 } }, + ], + [ + 'code_suggestions_acceptance_rate', + { codeSuggestions: { acceptedCount: 0, shownCount: 20 } }, + ], + ['code_suggestions_usage_rate', { codeContributorsCount: 5 }], + ['code_suggestions_usage_rate', { codeSuggestions: { contributorsCount: 2 } }], + [ + 'code_suggestions_usage_rate', + { codeSuggestions: { contributorsCount: 5 }, codeContributorsCount: 10 }, + ], + [ + 'code_suggestions_usage_rate', + { codeSuggestions: { contributorsCount: 0 }, codeContributorsCount: 10 }, + ], + ['duo_chat_usage_rate', { duoAssignedUsersCount: 3 }], + ['duo_chat_usage_rate', { duoChatContributorsCount: 4 }], + ['duo_chat_usage_rate', { duoChatContributorsCount: 7, duoAssignedUsersCount: 8 }], + ['duo_chat_usage_rate', { duoChatContributorsCount: 0, duoAssignedUsersCount: 50 }], + ['duo_rca_usage_rate', { duoAssignedUsersCount: 3 }], + ['duo_rca_usage_rate', { rootCauseAnalysisUsersCount: 10 }], + ['duo_rca_usage_rate', { rootCauseAnalysisUsersCount: 5, duoAssignedUsersCount: 8 }], + ['duo_rca_usage_rate', { rootCauseAnalysisUsersCount: 0, duoAssignedUsersCount: 50 }], + ['duo_review_count', {}], + [ + 'duo_review_count', + { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 10 } }, + ], + [ + 'duo_review_count', + { codeReview: { requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 5 } }, + ], + [ + 'duo_review_count', + { + codeReview: { + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 0, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 0, + }, + }, + ], + [ + 'duo_review_count', + { + codeReview: { + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 5, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 10, + }, + }, + ], + ['duo_review_comment_count', {}], + [ + 'duo_review_comment_count', + { codeReview: { postCommentDuoCodeReviewOnDiffEventCount: 25 } }, + ], + ['duo_review_comment_count', { codeReview: { postCommentDuoCodeReviewOnDiffEventCount: 0 } }], + ])('returns %s given %o', (identifier, data) => { expect(extractGraphqlAiData(data)[identifier]).toMatchSnapshot(); }); }); diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap index 357b4f6b2ce725..fd29ff03573b12 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap @@ -382,6 +382,86 @@ exports[`Metric table for the duo_rca_usage_rate table row when the data is load } `; +exports[`Metric table for the duo_review_comment_count table row when the data is loaded renders the metric values 1`] = ` +[ + "45", + "22", + "67", + "34", + "28", + "53", +] +`; + +exports[`Metric table for the duo_review_comment_count table row when the data is loaded renders the sparkline chart with expected props 1`] = ` +{ + "data": [ + [ + "Jul 1 – 31", + 45, + ], + [ + "Aug 1 – 31", + 22, + ], + [ + "Sep 1 – 30", + 67, + ], + [ + "Oct 1 – 31", + 34, + ], + [ + "Nov 1 – 30", + 28, + ], + ], + "tooltipLabel": "", + "trendStyle": "ASC", +} +`; + +exports[`Metric table for the duo_review_count table row when the data is loaded renders the metric values 1`] = ` +[ + "20", + "8", + "32", + "15", + "11", + "26", +] +`; + +exports[`Metric table for the duo_review_count table row when the data is loaded renders the sparkline chart with expected props 1`] = ` +{ + "data": [ + [ + "Jul 1 – 31", + 20, + ], + [ + "Aug 1 – 31", + 8, + ], + [ + "Sep 1 – 30", + 32, + ], + [ + "Oct 1 – 31", + 15, + ], + [ + "Nov 1 – 30", + 11, + ], + ], + "tooltipLabel": "", + "trendStyle": "ASC", +} +`; + exports[`Metric table for the issues table row when the data is loaded renders the metric values 1`] = ` [ "1", diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js b/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js index a7229d78231da2..04f885652a508e 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js @@ -221,6 +221,8 @@ describe('Metric table', () => { ${AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE} | ${''} | ${''} ${AI_METRICS.DUO_CHAT_USAGE_RATE} | ${''} | ${''} ${AI_METRICS.DUO_RCA_USAGE_RATE} | ${''} | ${''} + ${AI_METRICS.DUO_REVIEW_COUNT} | ${''} | ${''} + ${AI_METRICS.DUO_REVIEW_COMMENT_COUNT} | ${''} | ${''} ${PIPELINE_ANALYTICS_METRICS.COUNT} | ${namespace} | ${AI_IMPACT_TABLE_TRACKING_PROPERTY} ${PIPELINE_ANALYTICS_METRICS.MEDIAN} | ${namespace} | ${AI_IMPACT_TABLE_TRACKING_PROPERTY} ${PIPELINE_ANALYTICS_METRICS.SUCCESS_RATE} | ${namespace} | ${AI_IMPACT_TABLE_TRACKING_PROPERTY} @@ -257,6 +259,8 @@ describe('Metric table', () => { ${AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE} | ${'Code Suggestions acceptance rate'} ${AI_METRICS.DUO_CHAT_USAGE_RATE} | ${'Duo Chat usage'} ${AI_METRICS.DUO_RCA_USAGE_RATE} | ${'Duo RCA usage'} + ${AI_METRICS.DUO_REVIEW_COUNT} | ${'Duo Code Review requests'} + ${AI_METRICS.DUO_REVIEW_COMMENT_COUNT} | ${'Duo Code Review comments'} ${PIPELINE_ANALYTICS_METRICS.COUNT} | ${'Total pipeline runs'} ${PIPELINE_ANALYTICS_METRICS.MEDIAN} | ${'Median duration'} ${PIPELINE_ANALYTICS_METRICS.SUCCESS_RATE} | ${'Success rate'} diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/helpers.js b/ee/spec/frontend/analytics/dashboards/ai_impact/helpers.js index 830c3e50c8c898..e0556a3bfb5b24 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/helpers.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/helpers.js @@ -156,6 +156,9 @@ export const mockAiMetricsResponse = (values = []) => rootCauseAnalysisUsersCount, duoAssignedUsersCount, duoUsedCount, + requestReviewDuoCodeReviewOnMrByAuthorEventCount, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount, + postCommentDuoCodeReviewOnDiffEventCount, languages, acceptedLinesOfCode, shownLinesOfCode, @@ -180,6 +183,11 @@ export const mockAiMetricsResponse = (values = []) => rootCauseAnalysisUsersCount, duoAssignedUsersCount, duoUsedCount, + codeReview: { + requestReviewDuoCodeReviewOnMrByAuthorEventCount, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount, + postCommentDuoCodeReviewOnDiffEventCount, + }, __typename: 'AiMetrics', }, }, diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/mock_data.js b/ee/spec/frontend/analytics/dashboards/ai_impact/mock_data.js index 3ae9d6beb915e1..0731fa0dfd58da 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/mock_data.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/mock_data.js @@ -150,6 +150,9 @@ export const mockTableValues = [ rootCauseAnalysisUsersCount: 5, duoAssignedUsersCount: 15, duoUsedCount: 100, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 12, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 8, + postCommentDuoCodeReviewOnDiffEventCount: 45, pipelineCount: 387, pipelineSuccessCount: 149, pipelineFailedCount: 175, @@ -179,6 +182,9 @@ export const mockTableValues = [ rootCauseAnalysisUsersCount: 6, duoAssignedUsersCount: 7, duoUsedCount: 100, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 5, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 3, + postCommentDuoCodeReviewOnDiffEventCount: 22, pipelineCount: 37, pipelineSuccessCount: 49, pipelineFailedCount: 15, @@ -208,6 +214,9 @@ export const mockTableValues = [ rootCauseAnalysisUsersCount: 11, duoAssignedUsersCount: 15, duoUsedCount: 100, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 18, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 14, + postCommentDuoCodeReviewOnDiffEventCount: 67, pipelineCount: 27, pipelineSuccessCount: 10, pipelineFailedCount: 5, @@ -237,6 +246,9 @@ export const mockTableValues = [ rootCauseAnalysisUsersCount: 12, duoAssignedUsersCount: 18, duoUsedCount: 100, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 9, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 6, + postCommentDuoCodeReviewOnDiffEventCount: 34, pipelineCount: 95, pipelineSuccessCount: 60, pipelineFailedCount: 10, @@ -266,6 +278,9 @@ export const mockTableValues = [ rootCauseAnalysisUsersCount: 7, duoAssignedUsersCount: 17, duoUsedCount: 100, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 7, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 4, + postCommentDuoCodeReviewOnDiffEventCount: 28, pipelineCount: 75, pipelineSuccessCount: 18, pipelineFailedCount: 15, @@ -295,6 +310,9 @@ export const mockTableValues = [ rootCauseAnalysisUsersCount: 6, duoAssignedUsersCount: 12, duoUsedCount: 100, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 15, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 11, + postCommentDuoCodeReviewOnDiffEventCount: 53, pipelineCount: 100, pipelineSuccessCount: 50, pipelineFailedCount: 25, @@ -326,6 +344,9 @@ export const mockTableLargeValues = [ rootCauseAnalysisUsersCount: 1000, duoAssignedUsersCount: 2000, duoUsedCount: 10000, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 1250, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 850, + postCommentDuoCodeReviewOnDiffEventCount: 4500, pipelineCount: 37000, pipelineSuccessCount: 49000, pipelineFailedCount: 15000, @@ -352,6 +373,9 @@ export const mockTableLargeValues = [ rootCauseAnalysisUsersCount: 1200, duoAssignedUsersCount: 1500, duoUsedCount: 10000, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 980, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 620, + postCommentDuoCodeReviewOnDiffEventCount: 3200, pipelineCount: 27000, pipelineSuccessCount: 29000, pipelineFailedCount: 1500, @@ -378,6 +402,9 @@ export const mockTableLargeValues = [ rootCauseAnalysisUsersCount: 2000, duoAssignedUsersCount: 2400, duoUsedCount: 10000, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 1800, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 1400, + postCommentDuoCodeReviewOnDiffEventCount: 6700, pipelineCount: 45000, pipelineSuccessCount: 1000, pipelineFailedCount: 100, @@ -404,6 +431,9 @@ export const mockTableLargeValues = [ rootCauseAnalysisUsersCount: 4000, duoAssignedUsersCount: 6000, duoUsedCount: 10000, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 2100, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 1650, + postCommentDuoCodeReviewOnDiffEventCount: 8900, pipelineCount: 217000, pipelineSuccessCount: 129000, pipelineFailedCount: 15400, @@ -430,6 +460,9 @@ export const mockTableLargeValues = [ rootCauseAnalysisUsersCount: 7000, duoAssignedUsersCount: 9000, duoUsedCount: 10000, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 3400, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 2800, + postCommentDuoCodeReviewOnDiffEventCount: 12500, pipelineCount: 52000, pipelineSuccessCount: 41000, pipelineFailedCount: 1400, @@ -456,6 +489,9 @@ export const mockTableLargeValues = [ rootCauseAnalysisUsersCount: 8000, duoAssignedUsersCount: 8500, duoUsedCount: 10000, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 4200, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 3300, + postCommentDuoCodeReviewOnDiffEventCount: 15800, pipelineCount: 720, pipelineSuccessCount: 240, pipelineFailedCount: 70, @@ -533,6 +569,9 @@ export const mockAiMetricsResponseData = { duoChatContributorsCount: 5, duoAssignedUsersCount: 10, duoUsedCount: 3, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 100, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 100, + postCommentDuoCodeReviewOnDiffEventCount: 100, __typename: 'AiMetrics', }, __typename: 'Group', @@ -551,6 +590,9 @@ export const mockAiMetricsZeroResponseData = { duoChatContributorsCount: 0, duoAssignedUsersCount: 0, duoUsedCount: 0, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: 0, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 0, + postCommentDuoCodeReviewOnDiffEventCount: 0, __typename: 'AiMetrics', }, __typename: 'Group', @@ -567,6 +609,9 @@ export const mockAiMetricsNullResponseData = { duoChatContributorsCount: null, duoAssignedUsersCount: null, duoUsedCount: null, + requestReviewDuoCodeReviewOnMrByAuthorEventCount: null, + requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: null, + postCommentDuoCodeReviewOnDiffEventCount: null, __typename: 'AiMetrics', }, __typename: 'Group', diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1a85177ef324b1..84bd2cb80ea4ad 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6723,12 +6723,24 @@ msgstr "" msgid "AiImpactAnalytics|Duo Chat usage" msgstr "" +msgid "AiImpactAnalytics|Duo Code Review comments" +msgstr "" + +msgid "AiImpactAnalytics|Duo Code Review requests" +msgstr "" + msgid "AiImpactAnalytics|Duo RCA usage" msgstr "" msgid "AiImpactAnalytics|Duo features usage" msgstr "" +msgid "AiImpactAnalytics|Number of Duo Code Review comments." +msgstr "" + +msgid "AiImpactAnalytics|Number of Duo Code Review requests." +msgstr "" + msgid "AiImpactAnalytics|Number of contributors who used any GitLab Duo feature." msgstr "" -- GitLab From 585e38c011f7e3cb088a16bc8b27bff34e2d4793 Mon Sep 17 00:00:00 2001 From: Alex Pennells Date: Mon, 24 Nov 2025 10:59:28 -0500 Subject: [PATCH 2/3] update metric name --- .../javascripts/analytics/shared/constants.js | 4 ++-- .../analytics/dashboards/ai_impact/api.js | 4 ++-- .../dashboards/ai_impact/constants.js | 6 +++--- .../ai_impact_ai_metrics_table.yaml | 2 +- .../ai_impact/__snapshots__/api_spec.js.snap | 20 +++++++++---------- .../__snapshots__/utils_spec.js.snap | 2 +- .../dashboards/ai_impact/api_spec.js | 10 +++++----- .../__snapshots__/metric_table_spec.js.snap | 4 ++-- .../ai_impact/components/metric_table_spec.js | 4 ++-- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js index 286f85b622f16e..58cc80ea2e9bd9 100644 --- a/app/assets/javascripts/analytics/shared/constants.js +++ b/app/assets/javascripts/analytics/shared/constants.js @@ -201,7 +201,7 @@ export const AI_METRICS = { DUO_USAGE_RATE: 'duo_usage_rate', DUO_RCA_USAGE_RATE: 'duo_rca_usage_rate', DUO_USED_COUNT: 'duo_used_count', - DUO_REVIEW_COUNT: 'duo_review_count', + DUO_REVIEW_REQUESTS_COUNT: 'duo_review_requests_count', DUO_REVIEW_COMMENT_COUNT: 'duo_review_comment_count', }; @@ -418,7 +418,7 @@ export const VALUE_STREAM_METRIC_METADATA = { projectLink: '', docsLink: helpPagePath('user/gitlab_duo/feature_summary'), }, - [AI_METRICS.DUO_REVIEW_COUNT]: { + [AI_METRICS.DUO_REVIEW_REQUESTS_COUNT]: { description: s__('AiImpactAnalytics|Number of Duo Code Review requests.'), groupLink: '', projectLink: '', diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js index 57d454bb3c3427..e1d25c679bfed3 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js @@ -115,8 +115,8 @@ export const extractGraphqlAiData = ({ identifier: AI_METRICS.DUO_USED_COUNT, value: duoUsedCount ?? '-', }, - [AI_METRICS.DUO_REVIEW_COUNT]: { - identifier: AI_METRICS.DUO_REVIEW_COUNT, + [AI_METRICS.DUO_REVIEW_REQUESTS_COUNT]: { + identifier: AI_METRICS.DUO_REVIEW_REQUESTS_COUNT, value: duoReviewCount ?? '-', }, [AI_METRICS.DUO_REVIEW_COMMENT_COUNT]: { diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js index 7273ce424319b5..8c5dd92fa7c9f7 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js @@ -11,7 +11,7 @@ export const SUPPORTED_AI_METRICS = [ AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE, AI_METRICS.DUO_CHAT_USAGE_RATE, AI_METRICS.DUO_RCA_USAGE_RATE, - AI_METRICS.DUO_REVIEW_COUNT, + AI_METRICS.DUO_REVIEW_REQUESTS_COUNT, AI_METRICS.DUO_REVIEW_COMMENT_COUNT, ]; export const HIDE_METRIC_DRILL_DOWN = [ @@ -20,7 +20,7 @@ export const HIDE_METRIC_DRILL_DOWN = [ AI_METRICS.DUO_CHAT_USAGE_RATE, AI_METRICS.DUO_RCA_USAGE_RATE, AI_METRICS.DUO_USED_COUNT, - AI_METRICS.DUO_REVIEW_COUNT, + AI_METRICS.DUO_REVIEW_REQUESTS_COUNT, AI_METRICS.DUO_REVIEW_COMMENT_COUNT, ]; @@ -50,7 +50,7 @@ export const AI_IMPACT_USAGE_METRICS = { label: s__('AiImpactAnalytics|Duo RCA usage'), units: UNITS.PERCENT, }, - [AI_METRICS.DUO_REVIEW_COUNT]: { + [AI_METRICS.DUO_REVIEW_REQUESTS_COUNT]: { label: s__('AiImpactAnalytics|Duo Code Review requests'), units: UNITS.COUNT, }, diff --git a/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml b/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml index ca6c5fb0999f6c..e26e49ec004564 100644 --- a/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml +++ b/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/ai_impact_ai_metrics_table.yaml @@ -11,6 +11,6 @@ data: - code_suggestions_acceptance_rate - duo_chat_usage_rate - duo_rca_usage_rate - - duo_review_count + - duo_review_requests_count - duo_review_comment_count options: {} diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap index 0625b7aa4cbe5f..ea5af9f5b3f584 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/api_spec.js.snap @@ -155,51 +155,51 @@ exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_comment } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_requests_count given { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 0, requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 0 } } 1`] = ` { - "identifier": "duo_review_count", + "identifier": "duo_review_requests_count", "value": 0, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_requests_count given { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 5, requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 10 } } 1`] = ` { - "identifier": "duo_review_count", + "identifier": "duo_review_requests_count", "value": 15, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_requests_count given { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 10 } } 1`] = ` { - "identifier": "duo_review_count", + "identifier": "duo_review_requests_count", "value": 10, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given { +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_requests_count given { codeReview: { requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 5 } } 1`] = ` { - "identifier": "duo_review_count", + "identifier": "duo_review_requests_count", "value": 5, } `; -exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_count given {} 1`] = ` +exports[`AI impact dashboard api extractGraphqlAiData returns duo_review_requests_count given {} 1`] = ` { - "identifier": "duo_review_count", + "identifier": "duo_review_requests_count", "value": "-", } `; diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap index 58e72bf41a2099..7eb6aeb48a2645 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap @@ -306,7 +306,7 @@ exports[`AI impact Dashboard utils generateSkeletonTableData returns the skeleto }, { "metric": { - "identifier": "duo_review_count", + "identifier": "duo_review_requests_count", "value": "Duo Code Review requests", }, "trendStyle": "ASC", diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js b/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js index 184593c578ef6a..634e7a6cdebd65 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js @@ -31,17 +31,17 @@ describe('AI impact dashboard api', () => { ['duo_rca_usage_rate', { rootCauseAnalysisUsersCount: 10 }], ['duo_rca_usage_rate', { rootCauseAnalysisUsersCount: 5, duoAssignedUsersCount: 8 }], ['duo_rca_usage_rate', { rootCauseAnalysisUsersCount: 0, duoAssignedUsersCount: 50 }], - ['duo_review_count', {}], + ['duo_review_requests_count', {}], [ - 'duo_review_count', + 'duo_review_requests_count', { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 10 } }, ], [ - 'duo_review_count', + 'duo_review_requests_count', { codeReview: { requestReviewDuoCodeReviewOnMrByNonAuthorEventCount: 5 } }, ], [ - 'duo_review_count', + 'duo_review_requests_count', { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 0, @@ -50,7 +50,7 @@ describe('AI impact dashboard api', () => { }, ], [ - 'duo_review_count', + 'duo_review_requests_count', { codeReview: { requestReviewDuoCodeReviewOnMrByAuthorEventCount: 5, diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap index fd29ff03573b12..27b8ee9be5acd0 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/components/__snapshots__/metric_table_spec.js.snap @@ -422,7 +422,7 @@ exports[`Metric table for the duo_review_comment_count table row when the data i } `; -exports[`Metric table for the duo_review_count table row when the data is loaded renders the metric values 1`] = ` +exports[`Metric table for the duo_review_requests_count table row when the data is loaded renders the metric values 1`] = ` [ "20", "8", @@ -433,7 +433,7 @@ exports[`Metric table for the duo_review_count table row when the data is loaded ] `; -exports[`Metric table for the duo_review_count table row when the data is loaded renders the sparkline chart with expected props 1`] = ` +exports[`Metric table for the duo_review_requests_count table row when the data is loaded renders the sparkline chart with expected props 1`] = ` { "data": [ [ diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js b/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js index 04f885652a508e..b21c95690246d0 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js @@ -221,7 +221,7 @@ describe('Metric table', () => { ${AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE} | ${''} | ${''} ${AI_METRICS.DUO_CHAT_USAGE_RATE} | ${''} | ${''} ${AI_METRICS.DUO_RCA_USAGE_RATE} | ${''} | ${''} - ${AI_METRICS.DUO_REVIEW_COUNT} | ${''} | ${''} + ${AI_METRICS.DUO_REVIEW_REQUESTS_COUNT} | ${''} | ${''} ${AI_METRICS.DUO_REVIEW_COMMENT_COUNT} | ${''} | ${''} ${PIPELINE_ANALYTICS_METRICS.COUNT} | ${namespace} | ${AI_IMPACT_TABLE_TRACKING_PROPERTY} ${PIPELINE_ANALYTICS_METRICS.MEDIAN} | ${namespace} | ${AI_IMPACT_TABLE_TRACKING_PROPERTY} @@ -259,7 +259,7 @@ describe('Metric table', () => { ${AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE} | ${'Code Suggestions acceptance rate'} ${AI_METRICS.DUO_CHAT_USAGE_RATE} | ${'Duo Chat usage'} ${AI_METRICS.DUO_RCA_USAGE_RATE} | ${'Duo RCA usage'} - ${AI_METRICS.DUO_REVIEW_COUNT} | ${'Duo Code Review requests'} + ${AI_METRICS.DUO_REVIEW_REQUESTS_COUNT} | ${'Duo Code Review requests'} ${AI_METRICS.DUO_REVIEW_COMMENT_COUNT} | ${'Duo Code Review comments'} ${PIPELINE_ANALYTICS_METRICS.COUNT} | ${'Total pipeline runs'} ${PIPELINE_ANALYTICS_METRICS.MEDIAN} | ${'Median duration'} -- GitLab From 6161bd583e1b4b9842534f592eefc49d04469e53 Mon Sep 17 00:00:00 2001 From: Alex Pennells Date: Mon, 24 Nov 2025 11:16:06 -0500 Subject: [PATCH 3/3] fix conflicts --- .../gitlab/analytics/ai_impact_dashboard/dashboard.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml b/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml index 53a7f59a0574a2..70fbdfd45f4165 100644 --- a/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml +++ b/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml @@ -56,12 +56,12 @@ panels: yPos: 5 xPos: 0 width: 12 - height: 3 + height: 4 options: {} - title: 'Development metrics for the %{namespaceName} %{namespaceType}' visualization: ai_impact_lifecycle_metrics_table gridAttributes: - yPos: 8 + yPos: 9 xPos: 0 width: 12 height: 3 @@ -69,7 +69,7 @@ panels: - title: 'Pipeline metrics for the %{namespaceName} %{namespaceType}' visualization: pipeline_metrics_table gridAttributes: - yPos: 11 + yPos: 12 xPos: 0 width: 12 height: 3 @@ -77,7 +77,7 @@ panels: - title: 'Code Suggestions accepted by user' visualization: user_metrics_table gridAttributes: - yPos: 13 + yPos: 14 xPos: 0 width: 12 height: 8 -- GitLab