소개
Copilot 메트릭에 대한 REST API 엔드포인트을(를) 사용하여 사용자가 GitHub Copilot을 채택하는 방식의 추세를 확인할 수 있습니다. GitHub Copilot을 롤아웃하는 동안 이러한 추세를 확인하여 사용자가 할당된 라이선스를 사용하고 있는지 확인하고, 사용자가 사용 중인 기능을 확인하고, 개발자에게 회사의 사용 계획이 미치는 영향을 이해하는 것이 유용합니다.
API에는 다음이 포함됩니다.
- 지난 28일 동안의 데이터
- 활성 사용자와 참여 사용자 수
- 언어와 IDE별 분석
- 엔터프라이즈, 조직, 팀의 메트릭을 보는 옵션
현재 GitHub Copilot 사용 메트릭에 대한 REST API 엔드포인트을(를) 사용하는 경우 가능한 한 빨리 Copilot 메트릭에 대한 REST API 엔드포인트로 마이그레이션하는 것이 좋습니다.
이 가이드에서는 API를 쿼리하고 데이터를 저장하고 주별 사용자 수 변경에 대한 추세를 분석하는 방법을 보여 줍니다. 이 가이드의 예제에서는 조직의 엔드포인트를 사용하지만, 필요에 맞게 예제를 조정할 수 있습니다.
엔드포인트 가용성 정보
엔드포인트는 엔터프라이즈, 조직, 조직 팀, 엔터프라이즈 팀의 데이터를 가져오는 데 사용할 수 있습니다.
- 일반 조직이나 엔터프라이즈의 일부로 GitHub Copilot Business 또는 GitHub Copilot Enterprise 구독이 있는 경우 엔터프라이즈, 조직, 조직 팀의 엔드포인트를 사용할 수 있습니다. 미리 보기에 등록하지 않으면 엔터프라이즈 팀에 액세스할 수 없습니다.
- 조직을 만들 수 없는 엔터프라이즈 계정인 GitHub Copilot Business에 전용 엔터프라이즈를 사용하는 경우 엔터프라이즈 또는 엔터프라이즈 팀의 엔드포인트를 사용할 수 있습니다.
필수 조건
- 엔터프라이즈나 조직에서 Copilot 메트릭 API 액세스 정책을 사용하도록 설정해야 합니다. 조직에서 Copilot에 대한 정책 관리 또는 엔터프라이즈에서 Copilot Business에 대한 정책과 기능 관리하기을(를) 참조하세요.
- 쿼리하는 조직, 엔터프라이즈, 팀에는 충분한 활성 Copilot 사용자가 있어야 합니다. API는 해당 날짜에 대한 활성 Copilot 라이선스가 있는 멤버가 5명 이상 있는 경우에만 지정된 날짜에 대한 결과를 반환합니다.
- 이 예제에서는 데이터를 쿼리하고 분석하기 위한 JavaScript 스크립트를 만듭니다. 이 스크립트를 로컬로 실행하려면 Node.js를 설치한 다음, Octokit.js SDK를
npm install -g octokit
과 함께 설치해야 합니다.
1. personal access token
만들기
이 예제에서는 조직에 대한 메트릭을 가져오기 위해 manage_billing:copilot
범위를 사용하여 personal access token (classic)을 만듭니다. 개인용 액세스 토큰 관리을(를) 참조하세요.
다른 엔드포인트를 사용하는 경우 다른 범위가 필요할 수 있습니다. Copilot 메트릭에 대한 REST API 엔드포인트을(를) 참조하세요.
2. API에 연결
스크립트에서 API를 호출하고 응답을 변수로 저장합니다. 그런 다음, 데이터를 외부에 저장하고 데이터의 추세를 분석할 수 있습니다.
다음 예제에서는 JavaScript용 Octokit 클라이언트를 사용합니다. cURL 또는 GitHub CLI와 같은 다른 메서드를 사용하여 API를 호출할 수 있습니다.
예시
이 예에서는 다음이 적용됩니다.
- YOUR_TOKEN을 personal access token으로 대체합니다.
- YOUR_ORG를 조직 이름(예:
octo-org
)으로 대체합니다.
// Import Octokit import { Octokit } from "octokit"; // Set your token and organization const octokit = new Octokit({ auth: 'YOUR_TOKEN' }); const org = 'YOUR_ORG'; // Set other variables if required for the endpoint you're using /* const team = 'YOUR_TEAM'; const enterprise = 'YOUR_ENTERPRISE'; const entTeam = 'YOUR_ENTERPRISE_TEAM'; */ // Call the API async function orgMetrics() { const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, { org: 'ORG', headers: { 'X-GitHub-Api-Version': '2022-11-28' } }); const copilotUsage = resp.data; console.log(copilotUsage); } // Call the function orgMetrics();
import { Octokit } from "octokit";
Import Octokit
const octokit = new Octokit({
auth: 'YOUR_TOKEN'
});
const org = 'YOUR_ORG';
Set your token and organization
/*
const team = 'YOUR_TEAM';
const enterprise = 'YOUR_ENTERPRISE';
const entTeam = 'YOUR_ENTERPRISE_TEAM';
*/
Set other variables if required for the endpoint you're using
async function orgMetrics() {
const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, {
org: 'ORG',
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const copilotUsage = resp.data;
console.log(copilotUsage);
}
Call the API
orgMetrics();
Call the function
// Import Octokit
import { Octokit } from "octokit";
// Set your token and organization
const octokit = new Octokit({
auth: 'YOUR_TOKEN'
});
const org = 'YOUR_ORG';
// Set other variables if required for the endpoint you're using
/*
const team = 'YOUR_TEAM';
const enterprise = 'YOUR_ENTERPRISE';
const entTeam = 'YOUR_ENTERPRISE_TEAM';
*/
// Call the API
async function orgMetrics() {
const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, {
org: 'ORG',
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const copilotUsage = resp.data;
console.log(copilotUsage);
}
// Call the function
orgMetrics();
로컬로 스크립트 실행
스크립트를 로컬로 테스트하려면 파일을 copilot.mjs
로 저장한 다음, node copilot.mjs
를 실행합니다.
Important
.mjs 파일 형식이 중요합니다. import { Octokit }
문이 일반 .js
파일에서 작동하지 않을 수 있습니다.
터미널에 다음과 같은 JSON 배열이 있는 출력이 표시됩니다.
[
{
date: '2024-11-07',
copilot_ide_chat: { editors: [Array], total_engaged_users: 14 },
total_active_users: 28,
copilot_dotcom_chat: { models: [Array], total_engaged_users: 4 },
total_engaged_users: 28,
copilot_dotcom_pull_requests: { total_engaged_users: 0 },
copilot_ide_code_completions: { editors: [Array], total_engaged_users: 22 }
},
...
3. 데이터 저장
28일 이상 추세를 분석하려면 다음을 수행해야 합니다.
- cron 작업이나 예약된 GitHub Actions 워크플로를 사용하여 매일 API를 호출합니다.
- 데이터를 로컬로 저장하거나 MySQL과 같은 데이터베이스 서비스를 사용하여 저장합니다.
- 데이터를 쿼리하여 시간별 추세를 식별합니다.
예시
이 예제에서는 데이터를 로컬 .json
파일에 저장합니다. 이렇게 하려면 파일 작업을 위한 일부 모듈을 가져오고 응답 데이터를 저장하도록 orgMetrics
함수를 업데이트합니다.
이 함수는 파일에 이전 데이터를 덮어쓰지 않고 매일 반환되는 새 데이터를 저장합니다.
새 단계에 굵게 주석이 추가되었습니다.
// Import Octokit import { Octokit } from "octokit"; // **Import modules for working with files** import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; // **Declare variables for working with files** const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Set your token and organization const octokit = new Octokit({ auth: 'YOUR_TOKEN' }); const org = 'YOUR_ORG'; // Call the API async function orgMetrics() { const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, { org: 'ORG', headers: { 'X-GitHub-Api-Version': '2022-11-28' } }); const copilotUsage = resp.data; // **Define the path to the local file where data will be stored** const dataFilePath = path.join(__dirname, 'copilotMetricsData.json'); // **Read existing data from the file, if it exists** let existingData = []; if (fs.existsSync(dataFilePath)) { const fileContent = fs.readFileSync(dataFilePath, 'utf8'); existingData = JSON.parse(fileContent); } // **Filter out the new data that is not already in the existing data** const newData = copilotUsage.filter(entry => !existingData.some(existingEntry => existingEntry.date === entry.date)); // **Append new data to the existing data** if (newData.length > 0) { existingData = existingData.concat(newData); // **Save the updated data back to the file** fs.writeFileSync(dataFilePath, JSON.stringify(existingData, null, 2)); console.log(`Saved ${newData.length} new entries.`); } else { console.log('No new data to save.'); } } // Call the function orgMetrics();
import { Octokit } from "octokit";
Import Octokit
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
Import modules for working with files
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Declare variables for working with files
const octokit = new Octokit({
auth: 'YOUR_TOKEN'
});
const org = 'YOUR_ORG';
Set your token and organization
async function orgMetrics() {
const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, {
org: 'ORG',
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const copilotUsage = resp.data;
Call the API
const dataFilePath = path.join(__dirname, 'copilotMetricsData.json');
Define the path to the local file where data will be stored
let existingData = [];
if (fs.existsSync(dataFilePath)) {
const fileContent = fs.readFileSync(dataFilePath, 'utf8');
existingData = JSON.parse(fileContent);
}
Read existing data from the file, if it exists
const newData = copilotUsage.filter(entry => !existingData.some(existingEntry => existingEntry.date === entry.date));
Filter out the new data that is not already in the existing data
if (newData.length > 0) {
existingData = existingData.concat(newData);
Append new data to the existing data
fs.writeFileSync(dataFilePath, JSON.stringify(existingData, null, 2));
console.log(`Saved ${newData.length} new entries.`);
} else {
console.log('No new data to save.');
}
}
Save the updated data back to the file
orgMetrics();
Call the function
// Import Octokit
import { Octokit } from "octokit";
// **Import modules for working with files**
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// **Declare variables for working with files**
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Set your token and organization
const octokit = new Octokit({
auth: 'YOUR_TOKEN'
});
const org = 'YOUR_ORG';
// Call the API
async function orgMetrics() {
const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, {
org: 'ORG',
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const copilotUsage = resp.data;
// **Define the path to the local file where data will be stored**
const dataFilePath = path.join(__dirname, 'copilotMetricsData.json');
// **Read existing data from the file, if it exists**
let existingData = [];
if (fs.existsSync(dataFilePath)) {
const fileContent = fs.readFileSync(dataFilePath, 'utf8');
existingData = JSON.parse(fileContent);
}
// **Filter out the new data that is not already in the existing data**
const newData = copilotUsage.filter(entry => !existingData.some(existingEntry => existingEntry.date === entry.date));
// **Append new data to the existing data**
if (newData.length > 0) {
existingData = existingData.concat(newData);
// **Save the updated data back to the file**
fs.writeFileSync(dataFilePath, JSON.stringify(existingData, null, 2));
console.log(`Saved ${newData.length} new entries.`);
} else {
console.log('No new data to save.');
}
}
// Call the function
orgMetrics();
로컬로 스크립트 실행
node copilot.mjs
로 스크립트를 실행한 후 디렉터리에 copilotMetricsData.json
이라는 새 파일이 호출되어야 합니다. 파일에는 API 응답의 데이터가 포함되어야 합니다.
내일 스크립트를 다시 실행하는 경우 파일에 새로운 하루 동안의 데이터만 저장해야 합니다.
4. 추세 분석
API의 데이터를 사용하여 지난 28일 동안 추세를 식별하거나 이전 API 호출의 데이터를 더 긴 기간 동안 저장한 경우 확인할 수 있습니다.
예시
다음 예제에서는 orgMetrics
함수를 업데이트하여 주별 총 활성 사용자와 참여 사용자 수와 평균 수를 추출합니다. 그런 다음, 해당 데이터를 사용하여 시간별 변경 내용을 추적할 수 있습니다. 이 예제에서는 API에서 직접 반환된 데이터를 사용하며 저장된 데이터가 필요하지 않습니다.
새 단계에 굵게 주석이 추가되었습니다.
// Call the API async function orgMetrics() { const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, { org: 'ORG', headers: { 'X-GitHub-Api-Version': '2022-11-28' } }); const copilotUsage = resp.data; // **Create an object to store data for each week** let userTrends ={ week1: { days:0, activeUsers:0, engagedUsers:0, }, week2: { days:0, activeUsers:0, engagedUsers:0, }, week3: { days:0, activeUsers:0, engagedUsers:0, }, week4: { days:0, activeUsers:0, engagedUsers:0, }, }; // **Iterate over the data** for (let i =0; i<copilotUsage.length; i++) { // **Determine the week number (1-4) based on the index** const week = Math.ceil((i+1)/7); // **Increment userTrends for the current week** userTrends[`week${week}`].days += 1; userTrends[`week${week}`].activeUsers += copilotUsage[i].total_active_users; userTrends[`week${week}`].engagedUsers += copilotUsage[i].total_engaged_users; } // **Calculate the average number of active and engaged users per day for each week, rounded to two decimal places** for (const week in userTrends) { userTrends[week].avgActiveUsers = (userTrends[week].activeUsers / userTrends[week].days).toFixed(2); userTrends[week].avgEngagedUsers = (userTrends[week].engagedUsers / userTrends[week].days).toFixed(2); } // Output to the console console.log(userTrends); }
async function orgMetrics() {
const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, {
org: 'ORG',
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const copilotUsage = resp.data;
Call the API
let userTrends ={
week1: {
days:0,
activeUsers:0,
engagedUsers:0,
},
week2: {
days:0,
activeUsers:0,
engagedUsers:0,
},
week3: {
days:0,
activeUsers:0,
engagedUsers:0,
},
week4: {
days:0,
activeUsers:0,
engagedUsers:0,
},
};
Create an object to store data for each week
for (let i =0; i<copilotUsage.length; i++) {
Iterate over the data
const week = Math.ceil((i+1)/7);
Determine the week number (1-4) based on the index
userTrends[`week${week}`].days += 1;
userTrends[`week${week}`].activeUsers += copilotUsage[i].total_active_users;
userTrends[`week${week}`].engagedUsers += copilotUsage[i].total_engaged_users;
}
Increment userTrends for the current week
for (const week in userTrends) {
userTrends[week].avgActiveUsers = (userTrends[week].activeUsers / userTrends[week].days).toFixed(2);
userTrends[week].avgEngagedUsers = (userTrends[week].engagedUsers / userTrends[week].days).toFixed(2);
}
Calculate the average number of active and engaged users per day for each week, rounded to two decimal places
console.log(userTrends);
}
Output to the console
// Call the API
async function orgMetrics() {
const resp = await octokit.request(`GET /orgs/${org}/copilot/metrics`, {
org: 'ORG',
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
const copilotUsage = resp.data;
// **Create an object to store data for each week**
let userTrends ={
week1: {
days:0,
activeUsers:0,
engagedUsers:0,
},
week2: {
days:0,
activeUsers:0,
engagedUsers:0,
},
week3: {
days:0,
activeUsers:0,
engagedUsers:0,
},
week4: {
days:0,
activeUsers:0,
engagedUsers:0,
},
};
// **Iterate over the data**
for (let i =0; i<copilotUsage.length; i++) {
// **Determine the week number (1-4) based on the index**
const week = Math.ceil((i+1)/7);
// **Increment userTrends for the current week**
userTrends[`week${week}`].days += 1;
userTrends[`week${week}`].activeUsers += copilotUsage[i].total_active_users;
userTrends[`week${week}`].engagedUsers += copilotUsage[i].total_engaged_users;
}
// **Calculate the average number of active and engaged users per day for each week, rounded to two decimal places**
for (const week in userTrends) {
userTrends[week].avgActiveUsers = (userTrends[week].activeUsers / userTrends[week].days).toFixed(2);
userTrends[week].avgEngagedUsers = (userTrends[week].engagedUsers / userTrends[week].days).toFixed(2);
}
// Output to the console
console.log(userTrends);
}
로컬로 스크립트 실행
node copilot.mjs
로 스크립트를 실행한 후에는 다음과 같은 출력이 터미널에 표시됩니다.
{
week1: {
days: 7,
activeUsers: 174,
engagedUsers: 174,
avgActiveUsers: '24.86',
avgEngagedUsers: '24.86'
},
week2: {
days: 7,
activeUsers: 160,
engagedUsers: 151,
avgActiveUsers: '22.86',
avgEngagedUsers: '21.57'
},
week3: {
days: 7,
activeUsers: 134,
engagedUsers: 123,
avgActiveUsers: '19.14',
avgEngagedUsers: '17.57'
},
week4: {
days: 6,
activeUsers: 143,
engagedUsers: 132,
avgActiveUsers: '23.83',
avgEngagedUsers: '22.00'
}
}