From a95b42dca5ea792a476d82812dd2d0dc64b6f8a9 Mon Sep 17 00:00:00 2001 From: Alex Pennells <apennells@gitlab.com> Date: Thu, 1 Aug 2024 20:48:02 -0400 Subject: [PATCH] Add Duo Pro seats panel to AI impact analytics dashboard Adds a new panel to the AI impact analytics dashboard that allows you to see the Duo Pro adoption for the current scope. Changelog: added EE: true --- .../javascripts/analytics/shared/constants.js | 1 + .../data_sources/ai_impact_over_time.js | 8 ++++++++ .../analytics/dashboards/ai_impact/constants.js | 4 ++++ .../graphql/ai_metric_item.fragment.graphql | 2 ++ ee/app/models/product_analytics/visualization.rb | 8 ++++++-- .../analytics/ai_impact_dashboard/dashboard.yaml | 12 ++++++++++-- .../duo_pro_usage_rate_over_time.yaml | 11 +++++++++++ .../data_sources/ai_impact_over_time_spec.js | 16 +++++++++++----- .../analytics/dashboards/ai_impact/mock_data.js | 2 ++ .../product_analytics/visualizations_spec.rb | 7 ++++--- locale/gitlab.pot | 3 +++ 11 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/duo_pro_usage_rate_over_time.yaml diff --git a/app/assets/javascripts/analytics/shared/constants.js b/app/assets/javascripts/analytics/shared/constants.js index 18160ecd7ae9e..1b54725b1f156 100644 --- a/app/assets/javascripts/analytics/shared/constants.js +++ b/app/assets/javascripts/analytics/shared/constants.js @@ -131,6 +131,7 @@ export const CONTRIBUTOR_METRICS = { export const AI_METRICS = { CODE_SUGGESTIONS_USAGE_RATE: 'code_suggestions_usage_rate', CODE_SUGGESTIONS_ACCEPTANCE_RATE: 'code_suggestions_acceptance_rate', + DUO_PRO_USAGE_RATE: 'duo_pro_usage_rate', }; export const METRIC_TOOLTIPS = { diff --git a/ee/app/assets/javascripts/analytics/analytics_dashboards/data_sources/ai_impact_over_time.js b/ee/app/assets/javascripts/analytics/analytics_dashboards/data_sources/ai_impact_over_time.js index 5e1b728f9103e..262ecfbd52ef6 100644 --- a/ee/app/assets/javascripts/analytics/analytics_dashboards/data_sources/ai_impact_over_time.js +++ b/ee/app/assets/javascripts/analytics/analytics_dashboards/data_sources/ai_impact_over_time.js @@ -40,6 +40,14 @@ const extractMetricRateValue = ({ metric, rawQueryResult: result }) => { }); } + case AI_METRICS.DUO_PRO_USAGE_RATE: { + const { duoChatContributorsCount, duoProAssignedUsersCount } = resp; + return calculateRate({ + numerator: duoChatContributorsCount, + denominator: duoProAssignedUsersCount, + }); + } + default: return null; } 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 f93a5f0b123b7..91db089ab8b3f 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/constants.js @@ -31,6 +31,10 @@ export const AI_IMPACT_OVER_TIME_METRICS = { label: s__('AiImpactAnalytics|Code Suggestions acceptance usage'), units: UNITS.PERCENT, }, + [AI_METRICS.DUO_PRO_USAGE_RATE]: { + label: s__('AiImpactAnalytics|Duo Pro seats: Assigned and used'), + units: UNITS.PERCENT, + }, }; export const AI_IMPACT_TABLE_METRICS = { 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 fd837b86a5b3f..fba4349e6f746 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 @@ -5,4 +5,6 @@ fragment AiMetricItem on AiMetrics { codeSuggestionsContributorsCount codeSuggestionsShownCount codeSuggestionsAcceptedCount + duoChatContributorsCount + duoProAssignedUsersCount } diff --git a/ee/app/models/product_analytics/visualization.rb b/ee/app/models/product_analytics/visualization.rb index 427390b348baf..b64b62fa1b6d0 100644 --- a/ee/app/models/product_analytics/visualization.rb +++ b/ee/app/models/product_analytics/visualization.rb @@ -39,8 +39,12 @@ class Visualization ].freeze AI_IMPACT_DASHBOARD_PATH = 'ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations' - AI_IMPACT_DASHBOARD_VISUALIZATIONS = %w[ai_impact_table code_suggestions_usage_rate_over_time - code_suggestions_acceptance_rate_over_time].freeze + AI_IMPACT_DASHBOARD_VISUALIZATIONS = %w[ + ai_impact_table + code_suggestions_usage_rate_over_time + code_suggestions_acceptance_rate_over_time + duo_pro_usage_rate_over_time + ].freeze def self.for(container:, user:) config_project = diff --git a/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml b/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml index e43e6175e8e87..133c16432fa28 100644 --- a/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml +++ b/ee/lib/gitlab/analytics/ai_impact_dashboard/dashboard.yaml @@ -3,11 +3,19 @@ title: AI impact analytics description: Visualize the relation between AI usage and SDLC trends. version: "2" panels: + - title: "Duo Pro seats: Assigned and used" + visualization: duo_pro_usage_rate_over_time + gridAttributes: + yPos: 0 + xPos: 0 + width: 3 + height: 1 + options: {} - title: "Code Suggestions: Unique users" visualization: code_suggestions_usage_rate_over_time gridAttributes: yPos: 0 - xPos: 0 + xPos: 3 width: 3 height: 1 options: {} @@ -15,7 +23,7 @@ panels: visualization: code_suggestions_acceptance_rate_over_time gridAttributes: yPos: 0 - xPos: 3 + xPos: 6 width: 3 height: 1 options: {} diff --git a/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/duo_pro_usage_rate_over_time.yaml b/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/duo_pro_usage_rate_over_time.yaml new file mode 100644 index 0000000000000..5f70140d6f22d --- /dev/null +++ b/ee/lib/gitlab/analytics/ai_impact_dashboard/visualizations/duo_pro_usage_rate_over_time.yaml @@ -0,0 +1,11 @@ +--- +version: 1 +type: SingleStat +data: + type: ai_impact_over_time + query: + metric: duo_pro_usage_rate + dateRange: last_30_days +options: + unit: percent + decimalPlaces: 1 diff --git a/ee/spec/frontend/analytics/analytics_dashboards/components/data_sources/ai_impact_over_time_spec.js b/ee/spec/frontend/analytics/analytics_dashboards/components/data_sources/ai_impact_over_time_spec.js index a040e2e796a38..908e46d55d4bb 100644 --- a/ee/spec/frontend/analytics/analytics_dashboards/components/data_sources/ai_impact_over_time_spec.js +++ b/ee/spec/frontend/analytics/analytics_dashboards/components/data_sources/ai_impact_over_time_spec.js @@ -1,4 +1,5 @@ import { mockAiMetricsResponseData } from 'ee_jest/analytics/dashboards/ai_impact/mock_data'; +import { AI_METRICS } from '~/analytics/shared/constants'; import fetch from 'ee/analytics/analytics_dashboards/data_sources/ai_impact_over_time'; import { defaultClient } from 'ee/analytics/analytics_dashboards/graphql/client'; import { LAST_WEEK, LAST_30_DAYS, LAST_180_DAYS } from 'ee/dora/components/static_data/shared'; @@ -6,7 +7,7 @@ import { LAST_WEEK, LAST_30_DAYS, LAST_180_DAYS } from 'ee/dora/components/stati describe('AI Impact Over Time Data Source', () => { let res; - const query = { metric: 'code_suggestions_usage_rate', dateRange: LAST_30_DAYS }; + const query = { metric: AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE, dateRange: LAST_30_DAYS }; const namespace = 'cool namespace'; const defaultParams = { namespace, @@ -72,7 +73,7 @@ describe('AI Impact Over Time Data Source', () => { dateRange, { namespace: namespaceParam = 'cool namespace', - metric = 'code_suggestions_usage_rate', + metric = AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE, } = {}, ) => { mockResolvedQuery(); @@ -94,8 +95,13 @@ describe('AI Impact Over Time Data Source', () => { }); }); - it('can override the metric queried', async () => { - res = await mockQuery(LAST_WEEK, { metric: 'code_suggestions_acceptance_rate' }); + it.each` + metric | result + ${AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE} | ${'62.5'} + ${AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE} | ${'40.0'} + ${AI_METRICS.DUO_PRO_USAGE_RATE} | ${'50.0'} + `('can override the metric with `$metric`', async ({ metric, result }) => { + res = await mockQuery(LAST_WEEK, { metric }); expectQueryWithVariables({ startDate: new Date('2020-06-30'), @@ -103,7 +109,7 @@ describe('AI Impact Over Time Data Source', () => { fullPath: namespace, }); - expect(res).toBe('40.0'); + expect(res).toBe(result); }); it('can override the namespace', async () => { 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 bb4c3d34b1eaf..657e1ee66cb9c 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/mock_data.js +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/mock_data.js @@ -209,6 +209,8 @@ export const mockAiMetricsResponseData = { codeSuggestionsContributorsCount: 5, codeSuggestionsAcceptedCount: 2, codeSuggestionsShownCount: 5, + duoChatContributorsCount: 5, + duoProAssignedUsersCount: 10, __typename: 'AiMetrics', }, __typename: 'Group', diff --git a/ee/spec/requests/api/graphql/product_analytics/visualizations_spec.rb b/ee/spec/requests/api/graphql/product_analytics/visualizations_spec.rb index ca1f4cdec4977..dc46906a47b22 100644 --- a/ee/spec/requests/api/graphql/product_analytics/visualizations_spec.rb +++ b/ee/spec/requests/api/graphql/product_analytics/visualizations_spec.rb @@ -61,9 +61,10 @@ end where(:node_idx, :panel_type, :panel_title) do - 0 | 'SingleStat' | 'Code Suggestions: Unique users' - 1 | 'SingleStat' | 'Code Suggestions: Acceptance rate' - 2 | 'AiImpactTable' | 'Metric trends for %{namespaceType}: %{namespaceName}' + 0 | 'SingleStat' | 'Duo Pro seats: Assigned and used' + 1 | 'SingleStat' | 'Code Suggestions: Unique users' + 2 | 'SingleStat' | 'Code Suggestions: Acceptance rate' + 3 | 'AiImpactTable' | 'Metric trends for %{namespaceType}: %{namespaceName}' end with_them do diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6090931faac75..19148380406f9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4954,6 +4954,9 @@ msgstr "" msgid "AiImpactAnalytics|Code Suggestions usage" msgstr "" +msgid "AiImpactAnalytics|Duo Pro seats: Assigned and used" +msgstr "" + msgid "AiImpactAnalytics|Monthly user engagement with AI Code Suggestions. Percentage ratio calculated as monthly unique Code Suggestions users / total monthly unique code contributors." msgstr "" -- GitLab