mirror of
https://dev.azure.com/effectory/Survey%20Software/_git/Cloud%20Engineering
synced 2026-02-27 18:52:18 +01:00
- Add copilot usage check script #124960
- Add VSCode Plugin Scan poc script #124961
This commit is contained in:
529
Powershell/Tools/Get-CopilotUsage.ps1
Normal file
529
Powershell/Tools/Get-CopilotUsage.ps1
Normal file
@@ -0,0 +1,529 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves GitHub Copilot usage metrics per user for an organization.
|
||||
|
||||
.DESCRIPTION
|
||||
This script calls the GitHub REST API to get Copilot metrics for an organization,
|
||||
showing usage per user to help identify who is actively using their premium seats.
|
||||
|
||||
.PARAMETER Organization
|
||||
The GitHub organization name.
|
||||
|
||||
.PARAMETER Token
|
||||
GitHub Personal Access Token with 'copilot', 'manage_billing:copilot', or 'read:org' scope.
|
||||
If not provided, will attempt to use GITHUB_TOKEN environment variable.
|
||||
|
||||
.PARAMETER Days
|
||||
Number of days to look back (default: 28, max: 28).
|
||||
|
||||
.PARAMETER ExportToExcel
|
||||
Optional path to export results to Excel file (e.g., "copilot-usage.xlsx").
|
||||
|
||||
.PARAMETER IncludeUserSeats
|
||||
Include individual user seat information (who has access and when they last used it).
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-CopilotUsage.ps1 -Organization "myorg" -Token "ghp_xxxxx"
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-CopilotUsage.ps1 -Organization "myorg" -Days 7 -ExportToExcel "copilot-usage.xlsx"
|
||||
|
||||
.EXAMPLE
|
||||
.\Get-CopilotUsage.ps1 -Organization "myorg" -IncludeUserSeats -ExportToExcel "copilot-usage.xlsx"
|
||||
|
||||
.NOTES
|
||||
API Documentation: https://docs.github.com/en/rest/copilot/copilot-metrics
|
||||
Required Token Scopes: 'copilot', 'manage_billing:copilot', or 'read:org'
|
||||
This script requires the ImportExcel module. Install it with: Install-Module -Name ImportExcel
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Organization,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$Token,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateRange(1, 28)]
|
||||
[int]$Days = 28,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ExportToExcel,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$IncludeUserSeats
|
||||
)
|
||||
|
||||
# Check if ImportExcel module is available when export is requested
|
||||
if (-not [string]::IsNullOrEmpty($ExportToExcel)) {
|
||||
if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
|
||||
Write-Warning "ImportExcel module is not installed. Installing it now..."
|
||||
try {
|
||||
Install-Module -Name ImportExcel -Scope CurrentUser -Force -AllowClobber
|
||||
Write-Host "ImportExcel module installed successfully." -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Error "Failed to install ImportExcel module. Please install it manually: Install-Module -Name ImportExcel"
|
||||
Write-Host "Continuing without Excel export..." -ForegroundColor Yellow
|
||||
$ExportToExcel = ""
|
||||
}
|
||||
}
|
||||
if (-not [string]::IsNullOrEmpty($ExportToExcel)) {
|
||||
Import-Module ImportExcel
|
||||
}
|
||||
}
|
||||
|
||||
# Use environment variable if token not provided
|
||||
if ([string]::IsNullOrEmpty($Token)) {
|
||||
$Token = $env:GITHUB_TOKEN
|
||||
if ([string]::IsNullOrEmpty($Token)) {
|
||||
Write-Error "GitHub token not provided. Use -Token parameter or set GITHUB_TOKEN environment variable."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# API endpoint
|
||||
$apiUrl = "https://api.github.com/orgs/$Organization/copilot/metrics"
|
||||
|
||||
# Headers for authentication
|
||||
$headers = @{
|
||||
"Accept" = "application/vnd.github+json"
|
||||
"Authorization" = "Bearer $Token"
|
||||
"X-GitHub-Api-Version" = "2022-11-28"
|
||||
}
|
||||
|
||||
Write-Host "Fetching Copilot usage metrics for organization: $Organization" -ForegroundColor Cyan
|
||||
Write-Host "Time period: Last $Days days" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Variables to store data
|
||||
$dailySummary = @()
|
||||
$languageSummary = @()
|
||||
$editorSummary = @()
|
||||
$overallSummary = $null
|
||||
$userSeats = @()
|
||||
|
||||
try {
|
||||
# Calculate date range
|
||||
$since = (Get-Date).AddDays(-$Days).ToString("yyyy-MM-dd")
|
||||
$until = (Get-Date).ToString("yyyy-MM-dd")
|
||||
|
||||
# Add query parameters
|
||||
$uri = "$apiUrl`?since=$since&until=$until"
|
||||
|
||||
# Make API request
|
||||
$response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
|
||||
|
||||
if ($null -eq $response -or $response.Count -eq 0) {
|
||||
Write-Warning "No usage data found for the specified period."
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Process and display results
|
||||
$userMetrics = @()
|
||||
|
||||
foreach ($dayMetric in $response) {
|
||||
$date = $dayMetric.date
|
||||
|
||||
if ($null -ne $dayMetric.copilot_ide_code_completions) {
|
||||
foreach ($editor in $dayMetric.copilot_ide_code_completions.editors) {
|
||||
foreach ($model in $editor.models) {
|
||||
foreach ($language in $model.languages) {
|
||||
$userMetrics += [PSCustomObject]@{
|
||||
Date = $date
|
||||
Editor = $editor.name
|
||||
Model = $model.name
|
||||
Language = $language.name
|
||||
TotalEngagedUsers = $language.total_engaged_users
|
||||
SuggestionsCount = $language.total_code_suggestions
|
||||
AcceptancesCount = $language.total_code_acceptances
|
||||
LinesAccepted = $language.total_code_lines_accepted
|
||||
LinesSuggested = $language.total_code_lines_suggested
|
||||
ActiveUsers = $language.total_engaged_users
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Aggregate by user activity
|
||||
Write-Host "=== COPILOT USAGE SUMMARY ===" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
if ($userMetrics.Count -eq 0) {
|
||||
Write-Warning "No detailed metrics available for this period."
|
||||
} else {
|
||||
# Group by date and calculate totals
|
||||
$dailySummary = $userMetrics | Group-Object Date | ForEach-Object {
|
||||
$dayData = $_.Group
|
||||
[PSCustomObject]@{
|
||||
Date = $_.Name
|
||||
TotalEngagedUsers = ($dayData | Measure-Object -Property TotalEngagedUsers -Maximum).Maximum
|
||||
TotalSuggestions = ($dayData | Measure-Object -Property SuggestionsCount -Sum).Sum
|
||||
TotalAcceptances = ($dayData | Measure-Object -Property AcceptancesCount -Sum).Sum
|
||||
TotalLinesAccepted = ($dayData | Measure-Object -Property LinesAccepted -Sum).Sum
|
||||
AcceptanceRate = if (($dayData | Measure-Object -Property SuggestionsCount -Sum).Sum -gt 0) {
|
||||
[math]::Round((($dayData | Measure-Object -Property AcceptancesCount -Sum).Sum /
|
||||
($dayData | Measure-Object -Property SuggestionsCount -Sum).Sum) * 100, 2)
|
||||
} else { 0 }
|
||||
}
|
||||
} | Sort-Object Date -Descending
|
||||
|
||||
# Display daily summary
|
||||
Write-Host "Daily Summary:" -ForegroundColor Yellow
|
||||
$dailySummary | Format-Table -AutoSize
|
||||
|
||||
# Calculate overall statistics
|
||||
$totalUsers = ($dailySummary | Measure-Object -Property TotalEngagedUsers -Maximum).Maximum
|
||||
$totalSuggestions = ($dailySummary | Measure-Object -Property TotalSuggestions -Sum).Sum
|
||||
$totalAcceptances = ($dailySummary | Measure-Object -Property TotalAcceptances -Sum).Sum
|
||||
$overallAcceptanceRate = if ($totalSuggestions -gt 0) {
|
||||
[math]::Round(($totalAcceptances / $totalSuggestions) * 100, 2)
|
||||
} else { 0 }
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== OVERALL STATISTICS ===" -ForegroundColor Green
|
||||
Write-Host "Peak Engaged Users: $totalUsers" -ForegroundColor White
|
||||
Write-Host "Total Suggestions: $totalSuggestions" -ForegroundColor White
|
||||
Write-Host "Total Acceptances: $totalAcceptances" -ForegroundColor White
|
||||
Write-Host "Overall Acceptance Rate: $overallAcceptanceRate%" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
# Language breakdown
|
||||
$languageSummary = $userMetrics | Group-Object Language | ForEach-Object {
|
||||
$langData = $_.Group
|
||||
[PSCustomObject]@{
|
||||
Language = $_.Name
|
||||
TotalSuggestions = ($langData | Measure-Object -Property SuggestionsCount -Sum).Sum
|
||||
TotalAcceptances = ($langData | Measure-Object -Property AcceptancesCount -Sum).Sum
|
||||
AcceptanceRate = if (($langData | Measure-Object -Property SuggestionsCount -Sum).Sum -gt 0) {
|
||||
[math]::Round((($langData | Measure-Object -Property AcceptancesCount -Sum).Sum /
|
||||
($langData | Measure-Object -Property SuggestionsCount -Sum).Sum) * 100, 2)
|
||||
} else { 0 }
|
||||
}
|
||||
} | Sort-Object TotalAcceptances -Descending
|
||||
|
||||
Write-Host "Language Breakdown:" -ForegroundColor Yellow
|
||||
$languageSummary | Format-Table -AutoSize
|
||||
|
||||
# Editor breakdown
|
||||
$editorSummary = $userMetrics | Group-Object Editor | ForEach-Object {
|
||||
$editorData = $_.Group
|
||||
[PSCustomObject]@{
|
||||
Editor = $_.Name
|
||||
TotalSuggestions = ($editorData | Measure-Object -Property SuggestionsCount -Sum).Sum
|
||||
TotalAcceptances = ($editorData | Measure-Object -Property AcceptancesCount -Sum).Sum
|
||||
}
|
||||
} | Sort-Object TotalAcceptances -Descending
|
||||
|
||||
Write-Host "Editor Breakdown:" -ForegroundColor Yellow
|
||||
$editorSummary | Format-Table -AutoSize
|
||||
|
||||
# Create overall summary object for Excel
|
||||
$overallSummary = [PSCustomObject]@{
|
||||
Organization = $Organization
|
||||
DateRange = "$since to $until"
|
||||
PeakEngagedUsers = $totalUsers
|
||||
TotalSuggestions = $totalSuggestions
|
||||
TotalAcceptances = $totalAcceptances
|
||||
OverallAcceptanceRate = "$overallAcceptanceRate%"
|
||||
ReportGeneratedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
|
||||
}
|
||||
}
|
||||
|
||||
# Fetch individual user seat information if requested
|
||||
if ($IncludeUserSeats) {
|
||||
Write-Host ""
|
||||
Write-Host "=== FETCHING USER SEAT INFORMATION ===" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
try {
|
||||
# First, get the seat assignments
|
||||
$seatsUrl = "https://api.github.com/orgs/$Organization/copilot/billing/seats"
|
||||
$page = 1
|
||||
$perPage = 100
|
||||
$allSeats = @()
|
||||
|
||||
do {
|
||||
$seatsUri = "$seatsUrl`?per_page=$perPage&page=$page"
|
||||
$seatsResponse = Invoke-RestMethod -Uri $seatsUri -Headers $headers -Method Get
|
||||
|
||||
if ($null -ne $seatsResponse.seats) {
|
||||
$allSeats += $seatsResponse.seats
|
||||
}
|
||||
|
||||
$page++
|
||||
} while ($seatsResponse.seats.Count -eq $perPage)
|
||||
|
||||
Write-Host "Found $($allSeats.Count) user seats" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "NOTE: GitHub does not provide per-user 'credit usage' via API." -ForegroundColor Yellow
|
||||
Write-Host "Credit calculation is based on billing model: 1 seat = 300 credits/month" -ForegroundColor Yellow
|
||||
Write-Host "'Wasting credits' means: seat assigned but user inactive >30 days" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# Calculate credits consumed per user
|
||||
# GitHub Copilot Business/Enterprise charges per seat regardless of usage
|
||||
# If a user has a seat assigned, they consume the full month's credits
|
||||
# The "last_activity_at" tells us if they're actually using it
|
||||
$creditsPerMonth = 300
|
||||
$daysInMonth = [DateTime]::DaysInMonth((Get-Date).Year, (Get-Date).Month)
|
||||
$currentDay = (Get-Date).Day
|
||||
|
||||
# Calculate how many days have passed in the current month
|
||||
$daysElapsedInMonth = $currentDay
|
||||
|
||||
if ($allSeats.Count -eq 0) {
|
||||
Write-Warning "No user seats found."
|
||||
} else {
|
||||
$userSeats = $allSeats | ForEach-Object {
|
||||
$username = $_.assignee.login
|
||||
|
||||
$lastActivityDate = if ($_.last_activity_at) {
|
||||
try {
|
||||
# Try parsing as DateTime - handles multiple formats
|
||||
if ($_.last_activity_at -is [DateTime]) {
|
||||
$_.last_activity_at
|
||||
} else {
|
||||
[DateTime]::Parse($_.last_activity_at, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::None)
|
||||
}
|
||||
} catch {
|
||||
# Fallback: try different parsing methods
|
||||
try {
|
||||
[DateTime]::ParseExact($_.last_activity_at, "MM/dd/yyyy HH:mm:ss", [System.Globalization.CultureInfo]::InvariantCulture)
|
||||
} catch {
|
||||
try {
|
||||
# ISO 8601 format
|
||||
[DateTime]::Parse($_.last_activity_at)
|
||||
} catch {
|
||||
Write-Verbose "Could not parse date: $($_.last_activity_at) for user $username"
|
||||
$null
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
$daysSinceLastActivity = if ($lastActivityDate) {
|
||||
[math]::Round(((Get-Date) - $lastActivityDate).TotalDays)
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
$isActive = if ($daysSinceLastActivity -ne $null) {
|
||||
$daysSinceLastActivity -le 30
|
||||
} else {
|
||||
$false
|
||||
}
|
||||
|
||||
$assignedDate = if ($_.created_at) {
|
||||
try {
|
||||
if ($_.created_at -is [DateTime]) {
|
||||
$_.created_at
|
||||
} else {
|
||||
$parsedDate = [DateTime]::Parse($_.created_at, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::None)
|
||||
$parsedDate
|
||||
}
|
||||
} catch {
|
||||
try {
|
||||
[DateTime]::ParseExact($_.created_at, "MM/dd/yyyy HH:mm:ss", [System.Globalization.CultureInfo]::InvariantCulture)
|
||||
} catch {
|
||||
$null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$null
|
||||
}
|
||||
|
||||
# Calculate credits consumed
|
||||
# GitHub Copilot billing model: Charges per seat per month
|
||||
# Once a seat is assigned, the FULL monthly cost applies
|
||||
# Credits don't depend on usage - they're consumed just by having the seat
|
||||
|
||||
# Check if the seat is currently assigned (not pending cancellation)
|
||||
$isPendingCancellation = ![string]::IsNullOrEmpty($_.pending_cancellation_date)
|
||||
|
||||
if ($isPendingCancellation) {
|
||||
# Seat is being cancelled - no credits for full month
|
||||
$creditsConsumed = 0
|
||||
} elseif ($assignedDate -and $assignedDate.Year -eq (Get-Date).Year -and $assignedDate.Month -eq (Get-Date).Month) {
|
||||
# Assigned THIS month - pro-rate based on days from assignment to end of month
|
||||
$daysAssignedThisMonth = $currentDay - $assignedDate.Day + 1
|
||||
$creditsConsumed = [math]::Round(($daysAssignedThisMonth / $daysInMonth) * $creditsPerMonth, 2)
|
||||
} else {
|
||||
# Assigned before this month - FULL month charge
|
||||
$creditsConsumed = $creditsPerMonth
|
||||
}
|
||||
|
||||
$creditsRemaining = [math]::Round($creditsPerMonth - $creditsConsumed, 2)
|
||||
$creditsUsagePercent = if ($creditsPerMonth -gt 0) {
|
||||
[math]::Round(($creditsConsumed / $creditsPerMonth) * 100, 2)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
# Determine if credits are being wasted (assigned but not actively using)
|
||||
$isWastingCredits = ($creditsConsumed -gt 0) -and ($daysSinceLastActivity -eq $null -or $daysSinceLastActivity -gt 30)
|
||||
|
||||
[PSCustomObject]@{
|
||||
Username = $username
|
||||
DisplayName = $_.assignee.name
|
||||
Email = $_.assignee.email
|
||||
AssignedAt = $assignedDateFormatted
|
||||
LastActivityAt = if ($lastActivityDate) { $lastActivityDate.ToString("yyyy-MM-dd HH:mm:ss") } else { "Never" }
|
||||
DaysSinceLastActivity = if ($daysSinceLastActivity -ne $null) { $daysSinceLastActivity } else { "N/A" }
|
||||
IsActive30Days = $isActive
|
||||
IsWastingCredits = $isWastingCredits
|
||||
DaysAssignedThisMonth = if ($assignedDate) { $daysAssignedThisMonth } else { $currentDay }
|
||||
CreditsAllocated = $creditsPerMonth
|
||||
CreditsConsumed = $creditsConsumed
|
||||
CreditsRemaining = $creditsRemaining
|
||||
CreditsUsagePercent = $creditsUsagePercent
|
||||
PendingCancellationDate = if ($_.pending_cancellation_date) { $_.pending_cancellation_date } else { "" }
|
||||
Editor = $_.last_activity_editor
|
||||
AssigningTeam = if ($_.assigning_team) { $_.assigning_team.name } else { "" }
|
||||
}
|
||||
} | Sort-Object CreditsConsumed -Descending
|
||||
|
||||
Write-Host "Total Seats Assigned: $($userSeats.Count)" -ForegroundColor Cyan
|
||||
$activeUsers = ($userSeats | Where-Object { $_.IsActive30Days -eq $true }).Count
|
||||
$inactiveUsers = ($userSeats | Where-Object { $_.IsActive30Days -eq $false }).Count
|
||||
$wastingCredits = ($userSeats | Where-Object { $_.IsWastingCredits -eq $true }).Count
|
||||
|
||||
Write-Host "Active Users (last 30 days): $activeUsers" -ForegroundColor Green
|
||||
Write-Host "Inactive Users: $inactiveUsers" -ForegroundColor Yellow
|
||||
Write-Host "Users Wasting Credits: $wastingCredits" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
|
||||
# Show top users by credit consumption
|
||||
Write-Host "All Users by Credit Consumption (Month of $(Get-Date -Format 'MMMM yyyy')):" -ForegroundColor Yellow
|
||||
$userSeats | Select-Object -First 50 |
|
||||
Format-Table Username, DaysAssignedThisMonth, CreditsConsumed, CreditsUsagePercent, LastActivityAt, IsWastingCredits, Editor -AutoSize
|
||||
|
||||
# Show users wasting credits
|
||||
Write-Host ""
|
||||
Write-Host "Users WASTING Credits (assigned but inactive >30 days):" -ForegroundColor Red
|
||||
$userSeats | Where-Object { $_.IsWastingCredits -eq $true } |
|
||||
Select-Object -First 50 |
|
||||
Format-Table Username, CreditsConsumed, DaysSinceLastActivity, LastActivityAt, AssignedAt -AutoSize
|
||||
|
||||
# Credit usage summary
|
||||
$totalCreditsAllocated = $userSeats.Count * $creditsPerMonth
|
||||
$totalCreditsConsumed = ($userSeats | Measure-Object -Property CreditsConsumed -Sum).Sum
|
||||
$totalCreditsWasted = ($userSeats | Where-Object { $_.IsWastingCredits -eq $true } | Measure-Object -Property CreditsConsumed -Sum).Sum
|
||||
$creditEfficiency = if ($totalCreditsAllocated -gt 0) {
|
||||
[math]::Round(($totalCreditsConsumed / $totalCreditsAllocated) * 100, 2)
|
||||
} else { 0 }
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== CREDIT USAGE ANALYSIS (Month of $(Get-Date -Format 'MMMM yyyy')) ===" -ForegroundColor Green
|
||||
Write-Host "Credits per User per Month: $creditsPerMonth" -ForegroundColor White
|
||||
Write-Host "Total Seats: $($userSeats.Count)" -ForegroundColor White
|
||||
Write-Host "Total Credits Allocated (Full Month): $totalCreditsAllocated ($($userSeats.Count) users x $creditsPerMonth)" -ForegroundColor White
|
||||
Write-Host "Total Credits Consumed (Month-to-Date): $([math]::Round($totalCreditsConsumed, 2))" -ForegroundColor Cyan
|
||||
Write-Host "Total Credits on WASTED Seats: $([math]::Round($totalCreditsWasted, 2))" -ForegroundColor Red
|
||||
Write-Host "Potential Monthly Savings (remove inactive): $([math]::Round(($wastingCredits * $creditsPerMonth), 2)) credits" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host "Days Elapsed in Month: $currentDay of $daysInMonth" -ForegroundColor White
|
||||
Write-Host "Credit Utilization: $creditEfficiency% (of full-month allocation)" -ForegroundColor $(if ($creditEfficiency -lt 50) { "Red" } elseif ($creditEfficiency -lt 75) { "Yellow" } else { "Green" })
|
||||
Write-Host ""
|
||||
|
||||
# Recommendations
|
||||
if ($wastingCredits -gt 0) {
|
||||
Write-Host "💡 RECOMMENDATIONS:" -ForegroundColor Cyan
|
||||
Write-Host " → Remove $wastingCredits inactive user(s) to save ~$([math]::Round(($wastingCredits * $creditsPerMonth), 2)) credits/month" -ForegroundColor Yellow
|
||||
Write-Host " → That's approximately `$$([math]::Round(($wastingCredits * 19), 2))/month in wasted costs (at ~`$19/seat)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Warning "Failed to retrieve user seat information: $_"
|
||||
Write-Host "You may need 'manage_billing:copilot' scope to access seat details." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Error "An error occurred: $_"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Export to Excel if requested
|
||||
if (-not [string]::IsNullOrEmpty($ExportToExcel)) {
|
||||
Write-Host ""
|
||||
Write-Host "Exporting to Excel: $ExportToExcel" -ForegroundColor Cyan
|
||||
|
||||
try {
|
||||
# Remove existing file if it exists
|
||||
if (Test-Path $ExportToExcel) {
|
||||
Remove-Item $ExportToExcel -Force
|
||||
}
|
||||
|
||||
# Export to multiple worksheets
|
||||
$excelParams = @{
|
||||
Path = $ExportToExcel
|
||||
AutoSize = $true
|
||||
FreezeTopRow = $true
|
||||
BoldTopRow = $true
|
||||
}
|
||||
|
||||
$sheetCount = 1
|
||||
|
||||
# Sheet 1: Overall Summary
|
||||
if ($null -ne $overallSummary) {
|
||||
$overallSummary | Export-Excel @excelParams -WorksheetName "Overall Summary" -TableName "OverallSummary"
|
||||
$sheetCount++
|
||||
}
|
||||
|
||||
# Sheet 2: Daily Summary
|
||||
if ($dailySummary.Count -gt 0) {
|
||||
$dailySummary | Export-Excel @excelParams -WorksheetName "Daily Summary" -TableName "DailySummary"
|
||||
$sheetCount++
|
||||
}
|
||||
|
||||
# Sheet 3: Language Breakdown
|
||||
if ($languageSummary.Count -gt 0) {
|
||||
$languageSummary | Export-Excel @excelParams -WorksheetName "Language Breakdown" -TableName "LanguageBreakdown"
|
||||
$sheetCount++
|
||||
}
|
||||
|
||||
# Sheet 4: Editor Breakdown
|
||||
if ($editorSummary.Count -gt 0) {
|
||||
$editorSummary | Export-Excel @excelParams -WorksheetName "Editor Breakdown" -TableName "EditorBreakdown"
|
||||
$sheetCount++
|
||||
}
|
||||
|
||||
# Sheet 5: Detailed Metrics
|
||||
if ($userMetrics.Count -gt 0) {
|
||||
$userMetrics | Sort-Object Date -Descending |
|
||||
Export-Excel @excelParams -WorksheetName "Detailed Metrics" -TableName "DetailedMetrics"
|
||||
$sheetCount++
|
||||
}
|
||||
|
||||
# Sheet 6: User Seats (if included)
|
||||
if ($userSeats.Count -gt 0) {
|
||||
$userSeats | Export-Excel @excelParams -WorksheetName "User Seats" -TableName "UserSeats"
|
||||
$sheetCount++
|
||||
}
|
||||
|
||||
Write-Host "Results exported to: $ExportToExcel" -ForegroundColor Green
|
||||
Write-Host "Excel file contains multiple worksheets:" -ForegroundColor Green
|
||||
Write-Host " - Overall Summary" -ForegroundColor White
|
||||
Write-Host " - Daily Summary" -ForegroundColor White
|
||||
Write-Host " - Language Breakdown" -ForegroundColor White
|
||||
Write-Host " - Editor Breakdown" -ForegroundColor White
|
||||
Write-Host " - Detailed Metrics" -ForegroundColor White
|
||||
if ($userSeats.Count -gt 0) {
|
||||
Write-Host " - User Seats (per-user credit information)" -ForegroundColor White
|
||||
}
|
||||
} catch {
|
||||
Write-Error "Failed to export to Excel: $_"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Note: For individual user seat management in browser, visit:" -ForegroundColor Cyan
|
||||
Write-Host "https://github.com/organizations/$Organization/settings/copilot/seat_management" -ForegroundColor Cyan
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Script completed." -ForegroundColor Green
|
||||
Reference in New Issue
Block a user