diff --git a/README.md b/README.md index 4e3c9c1..495276c 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ https://github.com/github-copilot-resources/copilot-metrics-viewer/assets/332930 ## Key Metrics Here are the key metrics visualized in these charts: -1. **Acceptance Rate:** This metric represents the ratio of accepted lines to the total lines suggested by GitHub Copilot. This rate is an indicator of the relevance and usefulness of Copilot's suggestions. +1. **Acceptance Rate:** This metric represents the ratio of accepted numbers to the total numbers suggested by GitHub Copilot. This rate is an indicator of the relevance and usefulness of Copilot's suggestions.

- image + image

2. **Total Suggestions** This chart illustrates the total number of code suggestions made by GitHub Copilot. It offers a view of the tool's activity and its engagement with users over time. @@ -26,7 +26,7 @@ Here are the key metrics visualized in these charts: 3. **Total Acceptances:** This visualization focuses on the total number of suggestions accepted by users.

- image + image

4. **Total Lines Suggested:** Showcases the total number of lines of code suggested by GitHub Copilot. This gives an idea of the volume of code generation and assistance provided. @@ -34,26 +34,26 @@ Here are the key metrics visualized in these charts: 5. **Total Lines Accepted:** As the name says, the total lines of code accepted by users (full acceptances) offering insights into how much of the suggested code is actually being utilized incorporated to the codebase.

- image + image

6. **Total Active Users:** Represents the number of active users engaging with GitHub Copilot. This helps in understanding the user base growth and adoption rate.

- image + image

## Languages Breakdown Analysis -Pie charts with the top 5 languages by accepted prompts and acceptance rate are displayed at the top. +Pie charts with the top 5 languages by accepted prompts and acceptance rate (by count/by lines) are displayed at the top.

- image + image

The language breakdown analysis tab also displays a table showing the Accepted Prompts, Accepted Lines of Code, and Acceptance Rate (%) for each language over the past 28 days. The entries are sorted by the number of _accepted lines of code descending_.

- image + image

## Copilot Chat Metrics diff --git a/images/Acceptance_rate_by_lines.png b/images/Acceptance_rate_by_lines.png new file mode 100644 index 0000000..5e85dba Binary files /dev/null and b/images/Acceptance_rate_by_lines.png differ diff --git a/images/Acceptance_rate_bycount.png b/images/Acceptance_rate_bycount.png new file mode 100644 index 0000000..0451879 Binary files /dev/null and b/images/Acceptance_rate_bycount.png differ diff --git a/images/Language_breakdown.png b/images/Language_breakdown.png new file mode 100644 index 0000000..3181ea1 Binary files /dev/null and b/images/Language_breakdown.png differ diff --git a/images/Language_breakdown_list.png b/images/Language_breakdown_list.png new file mode 100644 index 0000000..06baeca Binary files /dev/null and b/images/Language_breakdown_list.png differ diff --git a/images/MainMetrics.png b/images/MainMetrics.png new file mode 100644 index 0000000..cb673b9 Binary files /dev/null and b/images/MainMetrics.png differ diff --git a/images/Total Lines.png b/images/Total Lines.png new file mode 100644 index 0000000..83f2d30 Binary files /dev/null and b/images/Total Lines.png differ diff --git a/images/Total_Active_users.png b/images/Total_Active_users.png new file mode 100644 index 0000000..491f4d7 Binary files /dev/null and b/images/Total_Active_users.png differ diff --git a/images/Total_suggestions_count.png b/images/Total_suggestions_count.png new file mode 100644 index 0000000..f09fac3 Binary files /dev/null and b/images/Total_suggestions_count.png differ diff --git a/src/components/BreakdownComponent.vue b/src/components/BreakdownComponent.vue index eb9da17..e724234 100644 --- a/src/components/BreakdownComponent.vue +++ b/src/components/BreakdownComponent.vue @@ -19,11 +19,11 @@ - +
-
Top 5 {{ breakdownDisplayNamePlural }} by accepted prompts
+
Top 5 {{ breakdownDisplayNamePlural }} by accepted suggestions(prompts)
@@ -31,13 +31,25 @@
- +
-
Top 5 {{ breakdownDisplayNamePlural }} by acceptance rate
+
Acceptance Rate (by count) for Top 5 {{ breakdownDisplayNamePlural }}
- + +
+
+
+
+ + + + +
+
Acceptance Rate (by code lines) for Top 5 {{ breakdownDisplayNamePlural }}
+
+
@@ -53,8 +65,11 @@ {{ item.name }} {{ item.acceptedPrompts }} + {{ item.suggestedPrompts }} {{ item.acceptedLinesOfCode }} - {{ item.acceptanceRate.toFixed(2) }}% + {{ item.suggestedLinesOfCode }} + {{ item.acceptanceRateByCount.toFixed(2) }}% + {{ item.acceptanceRateByLines.toFixed(2) }}% @@ -74,9 +89,9 @@ import { ArcElement, CategoryScale, LinearScale, + BarElement, PointElement, LineElement, - BarElement, Title, Tooltip, Legend @@ -120,8 +135,11 @@ export default defineComponent({ return [ { title: `${this.breakdownDisplayName} Name`, key: 'name' }, { title: 'Accepted Prompts', key: 'acceptedPrompts' }, + { title: 'Suggested Prompts', key: 'suggestedPrompts' }, { title: 'Accepted Lines of Code', key: 'acceptedLinesOfCode' }, - { title: 'Acceptance Rate (%)', key: 'acceptanceRate' }, + { title: 'Suggested Lines of Code', key: 'suggestedLinesOfCode' }, + { title: 'Acceptance Rate by Count (%)', key: 'acceptanceRateByCount' }, + { title: 'Acceptance Rate by Lines (%)', key: 'acceptanceRateByLines' }, ]; }, }, @@ -139,8 +157,11 @@ export default defineComponent({ //Top 5 by accepted prompts let breakdownsChartDataTop5AcceptedPrompts = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); - //Top 5 by acceptance rate - let breakdownsChartDataTop5AcceptanceRate = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); + //Acceptance Rate by lines for top 5 by accepted prompts + let breakdownsChartDataTop5AcceptedPromptsByLines = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); + + //Acceptance Rate by counts for top 5 by accepted prompts + let breakdownsChartDataTop5AcceptedPromptsByCounts = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); const chartOptions = { responsive: true, @@ -157,6 +178,7 @@ export default defineComponent({ // Process the breakdown separately data.forEach((m: Metrics) => m.breakdown.forEach(breakdownData => { + //console.log('Processing breakdown data:', breakdownData); const breakdownName = breakdownData[props.breakdownKey as keyof typeof breakdownData] as string; let breakdown = breakdownList.value.find(b => b.name === breakdownName); @@ -165,6 +187,7 @@ export default defineComponent({ breakdown = new Breakdown({ name: breakdownName, acceptedPrompts: breakdownData.acceptances_count, + suggestedPrompts: breakdownData.suggestions_count, suggestedLinesOfCode: breakdownData.lines_suggested, acceptedLinesOfCode: breakdownData.lines_accepted, }); @@ -172,40 +195,52 @@ export default defineComponent({ } else { // Update the existing breakdown object breakdown.acceptedPrompts += breakdownData.acceptances_count; + breakdown.suggestedPrompts += breakdownData.suggestions_count; breakdown.suggestedLinesOfCode += breakdownData.lines_suggested; breakdown.acceptedLinesOfCode += breakdownData.lines_accepted; } - // Recalculate the acceptance rate - breakdown.acceptanceRate = breakdown.suggestedLinesOfCode !== 0 ? (breakdown.acceptedLinesOfCode / breakdown.suggestedLinesOfCode) * 100 : 0; - })); + // Recalculate the acceptance rates + breakdown.acceptanceRateByCount = breakdown.suggestedPrompts !== 0 ? (breakdown.acceptedPrompts / breakdown.suggestedPrompts) * 100 : 0; + breakdown.acceptanceRateByLines = breakdown.suggestedLinesOfCode !== 0 ? (breakdown.acceptedLinesOfCode / breakdown.suggestedLinesOfCode) * 100 : 0; - //Sort breakdowns map by acceptance rate - breakdownList.value.sort((a, b) => b.acceptanceRate - a.acceptanceRate); + // Log each breakdown for debugging + // console.log('Breakdown:', breakdown); + })); - // Get the top 5 breakdowns by acceptance rate - const top5BreakdownsAcceptanceRate = breakdownList.value.slice(0, 5); + // for test, it seems there is an issue in data, so need to get the data in console + console.log('Breakdown List:', JSON.stringify(breakdownList.value, null, 2)); + + //Sort breakdowns map by accepted prompts + breakdownList.value.sort((a, b) => b.acceptedPrompts - a.acceptedPrompts); - breakdownsChartDataTop5AcceptanceRate.value = { - labels: top5BreakdownsAcceptanceRate.map(breakdown => breakdown.name), + // Get the top 5 breakdowns by accepted prompts + const top5BreakdownsAcceptedPrompts = breakdownList.value.slice(0, 5); + + breakdownsChartDataTop5AcceptedPrompts.value = { + labels: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.name), datasets: [ { - data: top5BreakdownsAcceptanceRate.map(breakdown => breakdown.acceptanceRate.toFixed(2)), + data: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.acceptedPrompts), backgroundColor: pieChartColors.value, }, ], }; - //Sort breakdowns map by accepted prompts - breakdownList.value.sort((a, b) => b.acceptedPrompts - a.acceptedPrompts); + breakdownsChartDataTop5AcceptedPromptsByLines.value = { + labels: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.name), + datasets: [ + { + data: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.acceptanceRateByLines.toFixed(2)), + backgroundColor: pieChartColors.value, + }, + ], + }; - // Get the top 5 breakdowns by accepted prompts - const top5BreakdownsAcceptedPrompts = breakdownList.value.slice(0, 5); - - breakdownsChartDataTop5AcceptedPrompts.value = { + breakdownsChartDataTop5AcceptedPromptsByCounts.value = { labels: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.name), datasets: [ { - data: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.acceptedPrompts), + data: top5BreakdownsAcceptedPrompts.map(breakdown => breakdown.acceptanceRateByCount.toFixed(2)), backgroundColor: pieChartColors.value, }, ], @@ -214,7 +249,7 @@ export default defineComponent({ numberOfBreakdowns.value = breakdownList.value.length; return { chartOptions, breakdownList, numberOfBreakdowns, - breakdownsChartData, breakdownsChartDataTop5AcceptedPrompts, breakdownsChartDataTop5AcceptanceRate }; + breakdownsChartData, breakdownsChartDataTop5AcceptedPrompts, breakdownsChartDataTop5AcceptedPromptsByLines, breakdownsChartDataTop5AcceptedPromptsByCounts }; }, diff --git a/src/components/MainComponent.vue b/src/components/MainComponent.vue index d142002..1d29971 100644 --- a/src/components/MainComponent.vue +++ b/src/components/MainComponent.vue @@ -128,7 +128,11 @@ export default defineComponent({ const apiError = ref(undefined); const signInRequired = ref(false); - function processError(error: any) { + /** + * Handles API errors by setting appropriate error messages. + * @param {any} error - The error object returned from the API call. + */ + function processError(error: any) { console.log(error); // Check the status code of the error response if (error.response && error.response.status) { @@ -153,20 +157,23 @@ export default defineComponent({ if(config.github.team && config.github.team.trim() !== '') { getTeamMetricsApi().then(data => { metrics.value = data; + //console.log("Metrics data in getTeamMetricsApi: ", metrics.value); // Set metricsReady to true after the call completes. metricsReady.value = true; }).catch(processError); } - - if (metricsReady.value === false) { - getMetricsApi().then(data => { - metrics.value = data; - - // Set metricsReady to true after the call completes. - metricsReady.value = true; - - }).catch(processError); + else { + if (metricsReady.value === false) { + getMetricsApi().then(data => { + metrics.value = data; + //console.log("Metrics data in getMetricsApi: ", metrics.value); + + // Set metricsReady to true after the call completes. + metricsReady.value = true; + + }).catch(processError); + } } getSeatsApi().then(data => { @@ -179,7 +186,8 @@ export default defineComponent({ return { metricsReady, metrics, seatsReady, seats, apiError, signInRequired }; } -}) + } +) \ No newline at end of file + diff --git a/src/components/MetricsViewer.vue b/src/components/MetricsViewer.vue index 3dffa27..9e41181 100644 --- a/src/components/MetricsViewer.vue +++ b/src/components/MetricsViewer.vue @@ -2,15 +2,16 @@
+ - + +
-
-
Acceptance Rate Average
-
- Over the last 28 days -
-

{{ acceptanceRateAverage.toFixed(2) }}%

+
Acceptance Rate (by count)
+
+ Over the last 28 days +
+

{{ acceptanceRateAverageByCount.toFixed(2) }}%

@@ -19,7 +20,7 @@
-
Cumulative Number of Suggestions
+
Total counts of Suggestions(Prompts)
Over the last 28 days
@@ -29,14 +30,14 @@ - -
-
-
Cumulative Number of Accepted Prompts
-
- Over the last 28 days -
-

{{ cumulativeNumberAcceptances }}

+ +
+
+
Acceptance Rate (by lines)
+
+ Over the last 28 days +
+

{{ acceptanceRateAverageByLines.toFixed(2) }}%

@@ -45,11 +46,11 @@
-
Cumulative Number of Lines of Code Accepted
+
Total Lines of code Suggested
Over the last 28 days
-

{{ cumulativeNumberLOCAccepted }}

+

{{ totalLinesSuggested }}

@@ -57,13 +58,16 @@ - -

Acceptance rate (%)

- +

Acceptance rate by count (%)

+

Total Suggestions Count | Total Acceptances Count

+ +

Acceptance rate by lines (%)

+ +

Total Lines Suggested | Total Lines Accepted

@@ -140,13 +144,18 @@ export default defineComponent({ setup(props) { //Tiles - let acceptanceRateAverage = ref(0); + let acceptanceRateAverageByLines = ref(0); + let acceptanceRateAverageByCount = ref(0); let cumulativeNumberSuggestions = ref(0); let cumulativeNumberAcceptances = ref(0); let cumulativeNumberLOCAccepted = ref(0); + let totalLinesSuggested = ref(0); + + //Acceptance Rate by lines + const acceptanceRateByLinesChartData = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); - //Acceptance Rate - const acceptanceRateChartData = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); + //Acceptance Rate by count + const acceptanceRateByCountChartData = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); //Total Suggestions Count | Total Acceptance Counts const totalSuggestionsAndAcceptanceChartData = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] }); @@ -253,19 +262,37 @@ export default defineComponent({ ] }; - const acceptanceRates = data.map((m: Metrics) => { + const acceptanceRatesByLines = data.map((m: Metrics) => { const rate = m.total_lines_suggested !== 0 ? (m.total_lines_accepted / m.total_lines_suggested) * 100 : 0; return rate; }); - - acceptanceRateChartData.value = { + const acceptanceRatesByCount = data.map((m: Metrics) => { + const rate = m.total_suggestions_count !== 0 ? (m.total_acceptances_count / m.total_suggestions_count) * 100 : 0; + return rate; + }); + + acceptanceRateByLinesChartData.value = { + labels: data.map((m: Metrics) => m.day), + datasets: [ + { + type: 'line', // This makes the dataset a line in the chart + label: 'Acceptance Rate by Lines', + data: acceptanceRatesByLines, + backgroundColor: 'rgba(173, 216, 230, 0.2)', // light blue + borderColor: 'rgba(173, 216, 230, 1)', // darker blue + fill: false // This makes the area under the line not filled + } + ] + }; + + acceptanceRateByCountChartData.value = { labels: data.map((m: Metrics) => m.day), datasets: [ { type: 'line', // This makes the dataset a line in the chart - label: 'Acceptance Rate', - data: acceptanceRates, + label: 'Acceptance Rate by Count', + data: acceptanceRatesByCount, backgroundColor: 'rgba(173, 216, 230, 0.2)', // light blue borderColor: 'rgba(173, 216, 230, 1)', // darker blue fill: false // This makes the area under the line not filled @@ -273,10 +300,19 @@ export default defineComponent({ ] }; - if(cumulativeNumberSuggestions.value === 0){ - acceptanceRateAverage.value = 0; + totalLinesSuggested.value = data.reduce((sum: number, m: Metrics) => sum + m.total_lines_suggested, 0); + + if(totalLinesSuggested.value === 0){ + acceptanceRateAverageByLines.value = 0; + } else { + acceptanceRateAverageByLines.value = cumulativeNumberLOCAccepted.value / totalLinesSuggested.value * 100; + } + + // Calculate acceptanceRateAverageByCount + if (cumulativeNumberSuggestions.value === 0) { + acceptanceRateAverageByCount.value = 0; } else { - acceptanceRateAverage.value = cumulativeNumberAcceptances.value / cumulativeNumberSuggestions.value * 100; + acceptanceRateAverageByCount.value = cumulativeNumberAcceptances.value / cumulativeNumberSuggestions.value * 100; } totalActiveUsersChartData.value = { @@ -293,8 +329,8 @@ export default defineComponent({ return { totalSuggestionsAndAcceptanceChartData, chartData, chartOptions, totalActiveUsersChartData, - totalActiveUsersChartOptions, acceptanceRateChartData, acceptanceRateAverage, cumulativeNumberSuggestions, - cumulativeNumberAcceptances, cumulativeNumberLOCAccepted }; + totalActiveUsersChartOptions, acceptanceRateByLinesChartData, acceptanceRateByCountChartData, acceptanceRateAverageByLines, acceptanceRateAverageByCount, cumulativeNumberSuggestions, + cumulativeNumberAcceptances, cumulativeNumberLOCAccepted, totalLinesSuggested }; }, }); diff --git a/src/components/SeatsAnalysisViewer.vue b/src/components/SeatsAnalysisViewer.vue index f2406c8..58b6756 100644 --- a/src/components/SeatsAnalysisViewer.vue +++ b/src/components/SeatsAnalysisViewer.vue @@ -64,7 +64,7 @@