@backstage-community/plugin-copilot-backend 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/client/GithubClient.cjs.js +92 -10
- package/dist/client/GithubClient.cjs.js.map +1 -1
- package/dist/task/EnterpriseTeamTask.cjs.js +4 -1
- package/dist/task/EnterpriseTeamTask.cjs.js.map +1 -1
- package/dist/task/OrganizationTeamTask.cjs.js +4 -1
- package/dist/task/OrganizationTeamTask.cjs.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage-community/plugin-copilot-backend
|
|
2
2
|
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 181ea72: Various performance improvements for larger organizations
|
|
8
|
+
|
|
9
|
+
- Only gather metrics from teams that have 5 or more members, teams
|
|
10
|
+
with less members will not have any metrics provided by the api as
|
|
11
|
+
documented here https://docs.github.com/en/rest/copilot/copilot-metrics?apiVersion=2022-11-28
|
|
12
|
+
- To improve performance and reduce the API calls made on large orgs,
|
|
13
|
+
we only need to retrieve the org and enterprise seats once per task.
|
|
14
|
+
|
|
3
15
|
## 0.12.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -64,12 +64,59 @@ class GithubClient {
|
|
|
64
64
|
}
|
|
65
65
|
async fetchEnterpriseTeams() {
|
|
66
66
|
const octokit = await this.getEnterpriseOctokit();
|
|
67
|
-
const path = `/enterprises/${this.copilotConfig.enterprise}/teams`;
|
|
68
67
|
try {
|
|
69
|
-
const teams =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
const teams = [];
|
|
69
|
+
let cursor = null;
|
|
70
|
+
let hasNextPage = true;
|
|
71
|
+
while (hasNextPage) {
|
|
72
|
+
const query = `
|
|
73
|
+
query($enterprise: String!, $cursor: String) {
|
|
74
|
+
enterprise(slug: $enterprise) {
|
|
75
|
+
organizations(first: 100) {
|
|
76
|
+
nodes {
|
|
77
|
+
teams(first: 100, after: $cursor) {
|
|
78
|
+
pageInfo {
|
|
79
|
+
hasNextPage
|
|
80
|
+
endCursor
|
|
81
|
+
}
|
|
82
|
+
nodes {
|
|
83
|
+
id
|
|
84
|
+
databaseId
|
|
85
|
+
slug
|
|
86
|
+
name
|
|
87
|
+
members {
|
|
88
|
+
totalCount
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
const variables = {
|
|
98
|
+
enterprise: this.copilotConfig.enterprise,
|
|
99
|
+
cursor
|
|
100
|
+
};
|
|
101
|
+
const response = await octokit.graphql(query, variables);
|
|
102
|
+
const allTeams = response.enterprise.organizations.nodes.flatMap(
|
|
103
|
+
(org) => org.teams.nodes
|
|
104
|
+
);
|
|
105
|
+
const filteredTeams = allTeams.filter((team) => team.members.totalCount >= 5).map((team) => ({
|
|
106
|
+
id: team.databaseId,
|
|
107
|
+
slug: team.slug,
|
|
108
|
+
name: team.name
|
|
109
|
+
}));
|
|
110
|
+
teams.push(...filteredTeams);
|
|
111
|
+
hasNextPage = response.enterprise.organizations.nodes.some(
|
|
112
|
+
(org) => org.teams.pageInfo.hasNextPage
|
|
113
|
+
);
|
|
114
|
+
if (hasNextPage) {
|
|
115
|
+
cursor = response.enterprise.organizations.nodes.find(
|
|
116
|
+
(org) => org.teams.pageInfo.hasNextPage
|
|
117
|
+
)?.teams.pageInfo.endCursor;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
73
120
|
return teams;
|
|
74
121
|
} catch (error) {
|
|
75
122
|
throw errors.ResponseError.fromResponse(error.response || error);
|
|
@@ -110,12 +157,47 @@ class GithubClient {
|
|
|
110
157
|
}
|
|
111
158
|
async fetchOrganizationTeams() {
|
|
112
159
|
const octokit = await this.getOrganizationOctokit();
|
|
113
|
-
const path = `/orgs/${this.copilotConfig.organization}/teams`;
|
|
114
160
|
try {
|
|
115
|
-
const teams =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
161
|
+
const teams = [];
|
|
162
|
+
let cursor = null;
|
|
163
|
+
let hasNextPage = true;
|
|
164
|
+
while (hasNextPage) {
|
|
165
|
+
const query = `
|
|
166
|
+
query($org: String!, $cursor: String) {
|
|
167
|
+
organization(login: $org) {
|
|
168
|
+
teams(first: 100, after: $cursor) {
|
|
169
|
+
pageInfo {
|
|
170
|
+
hasNextPage
|
|
171
|
+
endCursor
|
|
172
|
+
}
|
|
173
|
+
nodes {
|
|
174
|
+
id
|
|
175
|
+
databaseId
|
|
176
|
+
slug
|
|
177
|
+
name
|
|
178
|
+
members {
|
|
179
|
+
totalCount
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
`;
|
|
186
|
+
const variables = {
|
|
187
|
+
org: this.copilotConfig.organization,
|
|
188
|
+
cursor
|
|
189
|
+
};
|
|
190
|
+
const response = await octokit.graphql(query, variables);
|
|
191
|
+
const teamsData = response.organization.teams;
|
|
192
|
+
const filteredTeams = teamsData.nodes.filter((team) => team.members.totalCount >= 5).map((team) => ({
|
|
193
|
+
id: team.databaseId,
|
|
194
|
+
slug: team.slug,
|
|
195
|
+
name: team.name
|
|
196
|
+
}));
|
|
197
|
+
teams.push(...filteredTeams);
|
|
198
|
+
hasNextPage = teamsData.pageInfo.hasNextPage;
|
|
199
|
+
cursor = teamsData.pageInfo.endCursor;
|
|
200
|
+
}
|
|
119
201
|
return teams;
|
|
120
202
|
} catch (error) {
|
|
121
203
|
throw errors.ResponseError.fromResponse(error.response || error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GithubClient.cjs.js","sources":["../../src/client/GithubClient.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ResponseError } from '@backstage/errors';\nimport { Config } from '@backstage/config';\nimport {\n CopilotMetrics,\n CopilotSeats,\n TeamInfo,\n} from '@backstage-community/plugin-copilot-common';\nimport { Octokit } from '@octokit/rest';\nimport {\n CopilotConfig,\n CopilotCredentials,\n getCopilotConfig,\n getGithubCredentials,\n} from '../utils/GithubUtils';\n\ninterface GithubApi {\n fetchEnterpriseCopilotMetrics: () => Promise<CopilotMetrics[]>;\n fetchEnterpriseTeamCopilotMetrics: (\n teamId: string,\n ) => Promise<CopilotMetrics[]>;\n fetchOrganizationCopilotMetrics: () => Promise<CopilotMetrics[]>;\n fetchOrganizationTeamCopilotMetrics: (\n teamId: string,\n ) => Promise<CopilotMetrics[]>;\n\n fetchEnterpriseTeams: () => Promise<TeamInfo[]>;\n fetchOrganizationTeams: () => Promise<TeamInfo[]>;\n}\n\nexport class GithubClient implements GithubApi {\n private enterpriseOctokit?: Octokit;\n private organizationOctokit?: Octokit;\n\n constructor(\n private readonly copilotConfig: CopilotConfig,\n private readonly config: Config,\n ) {}\n\n static async fromConfig(config: Config) {\n const info = getCopilotConfig(config);\n return new GithubClient(info, config);\n }\n\n private async getCredentials(): Promise<CopilotCredentials> {\n return await getGithubCredentials(this.config, this.copilotConfig);\n }\n\n private async getOctokit(\n type: 'enterprise' | 'organization',\n ): Promise<Octokit> {\n const credentials = await this.getCredentials();\n const headers = credentials[type]?.headers || {};\n\n return new Octokit({\n baseUrl: this.copilotConfig.apiBaseUrl,\n auth: headers.Authorization?.replace('Bearer ', '') || '',\n headers: {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n },\n });\n }\n\n private async getEnterpriseOctokit(): Promise<Octokit> {\n if (!this.enterpriseOctokit) {\n this.enterpriseOctokit = await this.getOctokit('enterprise');\n }\n return this.enterpriseOctokit;\n }\n\n private async getOrganizationOctokit(): Promise<Octokit> {\n if (!this.organizationOctokit) {\n this.organizationOctokit = await this.getOctokit('organization');\n }\n return this.organizationOctokit;\n }\n\n async fetchEnterpriseCopilotMetrics(): Promise<CopilotMetrics[]> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchEnterpriseTeamCopilotMetrics(\n teamId: string,\n ): Promise<CopilotMetrics[]> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/team/${teamId}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchEnterpriseTeams(): Promise<TeamInfo[]> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/teams`;\n\n try {\n const teams = await octokit.paginate(`GET ${path}`, {\n per_page: 100, // Maximum allowed per page\n });\n return teams as TeamInfo[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchEnterpriseSeats(): Promise<any> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/copilot/billing/seats`;\n\n try {\n const seats = await octokit.paginate(`GET ${path}`, {\n per_page: 100, // Maximum allowed per page\n });\n\n return this.mergePaginationResult(seats as CopilotSeats[]);\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationCopilotMetrics(): Promise<CopilotMetrics[]> {\n const octokit = await this.getOrganizationOctokit();\n const path = `/orgs/${this.copilotConfig.organization}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationTeamCopilotMetrics(\n teamId: string,\n ): Promise<CopilotMetrics[]> {\n const octokit = await this.getOrganizationOctokit();\n const path = `/orgs/${this.copilotConfig.organization}/team/${teamId}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationTeams(): Promise<TeamInfo[]> {\n const octokit = await this.getOrganizationOctokit();\n const path = `/orgs/${this.copilotConfig.organization}/teams`;\n\n try {\n const teams = await octokit.paginate(`GET ${path}`, {\n per_page: 100, // Maximum allowed per page\n });\n return teams as TeamInfo[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationSeats(): Promise<CopilotSeats> {\n const octokit = await this.getOrganizationOctokit();\n\n try {\n const seats = await octokit.paginate(octokit.copilot.listCopilotSeats, {\n org: this.copilotConfig.organization!,\n per_page: 100, // Maximum allowed per page\n });\n\n return this.mergePaginationResult(seats as CopilotSeats[]);\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n /**\n * This function is used to merge paginated results from the GitHub API\n * that does not work as one would expect. If the api returns a object which\n * contains paginated results, we get an array of the objects instead of merged data.\n * So this function merges this data into one object where the property \"seats\" are\n * merged into a single array.\n * @param data\n * @returns paginated result as one would expect\n */\n mergePaginationResult(data: CopilotSeats[]): CopilotSeats {\n if (data.length === 0) {\n return {\n total_seats: 0,\n seats: [],\n };\n }\n\n // total_seats is the same for all pages, so we can just take it from the first page\n // and merge the seats from all pages into one array\n const totalSeats = data[0].total_seats;\n const seats = data.map(seat => seat.seats).flat();\n\n return {\n total_seats: totalSeats,\n seats: seats,\n };\n }\n}\n"],"names":["getCopilotConfig","getGithubCredentials","Octokit","ResponseError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GithubClient.cjs.js","sources":["../../src/client/GithubClient.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ResponseError } from '@backstage/errors';\nimport { Config } from '@backstage/config';\nimport {\n CopilotMetrics,\n CopilotSeats,\n TeamInfo,\n} from '@backstage-community/plugin-copilot-common';\nimport { Octokit } from '@octokit/rest';\nimport {\n CopilotConfig,\n CopilotCredentials,\n getCopilotConfig,\n getGithubCredentials,\n} from '../utils/GithubUtils';\n\ninterface GithubApi {\n fetchEnterpriseCopilotMetrics: () => Promise<CopilotMetrics[]>;\n fetchEnterpriseTeamCopilotMetrics: (\n teamId: string,\n ) => Promise<CopilotMetrics[]>;\n fetchOrganizationCopilotMetrics: () => Promise<CopilotMetrics[]>;\n fetchOrganizationTeamCopilotMetrics: (\n teamId: string,\n ) => Promise<CopilotMetrics[]>;\n\n fetchEnterpriseTeams: () => Promise<TeamInfo[]>;\n fetchOrganizationTeams: () => Promise<TeamInfo[]>;\n}\n\nexport class GithubClient implements GithubApi {\n private enterpriseOctokit?: Octokit;\n private organizationOctokit?: Octokit;\n\n constructor(\n private readonly copilotConfig: CopilotConfig,\n private readonly config: Config,\n ) {}\n\n static async fromConfig(config: Config) {\n const info = getCopilotConfig(config);\n return new GithubClient(info, config);\n }\n\n private async getCredentials(): Promise<CopilotCredentials> {\n return await getGithubCredentials(this.config, this.copilotConfig);\n }\n\n private async getOctokit(\n type: 'enterprise' | 'organization',\n ): Promise<Octokit> {\n const credentials = await this.getCredentials();\n const headers = credentials[type]?.headers || {};\n\n return new Octokit({\n baseUrl: this.copilotConfig.apiBaseUrl,\n auth: headers.Authorization?.replace('Bearer ', '') || '',\n headers: {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n },\n });\n }\n\n private async getEnterpriseOctokit(): Promise<Octokit> {\n if (!this.enterpriseOctokit) {\n this.enterpriseOctokit = await this.getOctokit('enterprise');\n }\n return this.enterpriseOctokit;\n }\n\n private async getOrganizationOctokit(): Promise<Octokit> {\n if (!this.organizationOctokit) {\n this.organizationOctokit = await this.getOctokit('organization');\n }\n return this.organizationOctokit;\n }\n\n async fetchEnterpriseCopilotMetrics(): Promise<CopilotMetrics[]> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchEnterpriseTeamCopilotMetrics(\n teamId: string,\n ): Promise<CopilotMetrics[]> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/team/${teamId}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchEnterpriseTeams(): Promise<TeamInfo[]> {\n const octokit = await this.getEnterpriseOctokit();\n\n try {\n const teams: TeamInfo[] = [];\n let cursor: string | null = null;\n let hasNextPage = true;\n\n while (hasNextPage) {\n const query = `\n query($enterprise: String!, $cursor: String) {\n enterprise(slug: $enterprise) {\n organizations(first: 100) {\n nodes {\n teams(first: 100, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n databaseId\n slug\n name\n members {\n totalCount\n }\n }\n }\n }\n }\n }\n }\n `;\n\n const variables = {\n enterprise: this.copilotConfig.enterprise,\n cursor,\n };\n\n const response: any = await octokit.graphql(query, variables);\n\n // Flatten teams from all organizations in the enterprise\n const allTeams = response.enterprise.organizations.nodes.flatMap(\n (org: any) => org.teams.nodes,\n );\n\n // Filter teams with 5 or more members\n const filteredTeams = allTeams\n .filter((team: any) => team.members.totalCount >= 5)\n .map((team: any) => ({\n id: team.databaseId,\n slug: team.slug,\n name: team.name,\n }));\n\n teams.push(...filteredTeams);\n\n // Check if any organization has more teams to fetch\n hasNextPage = response.enterprise.organizations.nodes.some(\n (org: any) => org.teams.pageInfo.hasNextPage,\n );\n\n if (hasNextPage) {\n cursor = response.enterprise.organizations.nodes.find(\n (org: any) => org.teams.pageInfo.hasNextPage,\n )?.teams.pageInfo.endCursor;\n }\n }\n\n return teams;\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchEnterpriseSeats(): Promise<any> {\n const octokit = await this.getEnterpriseOctokit();\n const path = `/enterprises/${this.copilotConfig.enterprise}/copilot/billing/seats`;\n\n try {\n const seats = await octokit.paginate(`GET ${path}`, {\n per_page: 100, // Maximum allowed per page\n });\n\n return this.mergePaginationResult(seats as CopilotSeats[]);\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationCopilotMetrics(): Promise<CopilotMetrics[]> {\n const octokit = await this.getOrganizationOctokit();\n const path = `/orgs/${this.copilotConfig.organization}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationTeamCopilotMetrics(\n teamId: string,\n ): Promise<CopilotMetrics[]> {\n const octokit = await this.getOrganizationOctokit();\n const path = `/orgs/${this.copilotConfig.organization}/team/${teamId}/copilot/metrics`;\n\n try {\n const response = await octokit.request(`GET ${path}`);\n return response.data as CopilotMetrics[];\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationTeams(): Promise<TeamInfo[]> {\n const octokit = await this.getOrganizationOctokit();\n\n try {\n const teams: TeamInfo[] = [];\n let cursor: string | null = null;\n let hasNextPage = true;\n\n while (hasNextPage) {\n const query = `\n query($org: String!, $cursor: String) {\n organization(login: $org) {\n teams(first: 100, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n databaseId\n slug\n name\n members {\n totalCount\n }\n }\n }\n }\n }\n `;\n\n const variables = {\n org: this.copilotConfig.organization,\n cursor,\n };\n\n const response: any = await octokit.graphql(query, variables);\n const teamsData = response.organization.teams;\n\n // Filter teams with 5 or more members\n const filteredTeams = teamsData.nodes\n .filter((team: any) => team.members.totalCount >= 5)\n .map((team: any) => ({\n id: team.databaseId,\n slug: team.slug,\n name: team.name,\n }));\n\n teams.push(...filteredTeams);\n\n hasNextPage = teamsData.pageInfo.hasNextPage;\n cursor = teamsData.pageInfo.endCursor;\n }\n\n return teams;\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n async fetchOrganizationSeats(): Promise<CopilotSeats> {\n const octokit = await this.getOrganizationOctokit();\n\n try {\n const seats = await octokit.paginate(octokit.copilot.listCopilotSeats, {\n org: this.copilotConfig.organization!,\n per_page: 100, // Maximum allowed per page\n });\n\n return this.mergePaginationResult(seats as CopilotSeats[]);\n } catch (error) {\n throw ResponseError.fromResponse(error.response || error);\n }\n }\n\n /**\n * This function is used to merge paginated results from the GitHub API\n * that does not work as one would expect. If the api returns a object which\n * contains paginated results, we get an array of the objects instead of merged data.\n * So this function merges this data into one object where the property \"seats\" are\n * merged into a single array.\n * @param data\n * @returns paginated result as one would expect\n */\n mergePaginationResult(data: CopilotSeats[]): CopilotSeats {\n if (data.length === 0) {\n return {\n total_seats: 0,\n seats: [],\n };\n }\n\n // total_seats is the same for all pages, so we can just take it from the first page\n // and merge the seats from all pages into one array\n const totalSeats = data[0].total_seats;\n const seats = data.map(seat => seat.seats).flat();\n\n return {\n total_seats: totalSeats,\n seats: seats,\n };\n }\n}\n"],"names":["getCopilotConfig","getGithubCredentials","Octokit","ResponseError"],"mappings":"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"}
|
|
@@ -21,6 +21,10 @@ async function discoverEnterpriseTeamMetrics({
|
|
|
21
21
|
logger.info(
|
|
22
22
|
`[discoverEnterpriseTeamMetrics] Fetched ${teams.length} teams`
|
|
23
23
|
);
|
|
24
|
+
const seats = await api.fetchEnterpriseSeats();
|
|
25
|
+
logger.info(
|
|
26
|
+
`[discoverEnterpriseTeamMetrics] Fetched ${seats.length} seats from enterprise`
|
|
27
|
+
);
|
|
24
28
|
for (const team of teams) {
|
|
25
29
|
try {
|
|
26
30
|
logger.info(
|
|
@@ -109,7 +113,6 @@ async function discoverEnterpriseTeamMetrics({
|
|
|
109
113
|
await batchInsert.batchInsertInChunks(ideChatEditorModels, 30, async (chunk) => {
|
|
110
114
|
await db.batchInsertIdeChatEditorModels(chunk);
|
|
111
115
|
});
|
|
112
|
-
const seats = await api.fetchEnterpriseSeats();
|
|
113
116
|
const seatsToInsert = metricHelpers.convertToTeamSeatAnalysis(
|
|
114
117
|
seats,
|
|
115
118
|
type,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnterpriseTeamTask.cjs.js","sources":["../../src/task/EnterpriseTeamTask.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n CopilotMetrics,\n MetricsType,\n} from '@backstage-community/plugin-copilot-common';\nimport { batchInsertInChunks } from '../utils/batchInsert';\nimport {\n convertToTeamSeatAnalysis,\n filterBaseMetrics,\n filterIdeChatEditorModelMetrics,\n filterIdeChatMetrics,\n filterIdeCompletionEditorMetrics,\n filterIdeCompletionEditorModelLanguageMetrics,\n filterIdeCompletionEditorModelMetrics,\n filterIdeCompletionLanguageMetrics,\n filterIdeCompletionMetrics,\n filterIdeEditorMetrics,\n filterNewMetricsV2,\n} from '../utils/metricHelpers';\nimport { TaskOptions } from './TaskManagement';\n\nexport async function discoverEnterpriseTeamMetrics({\n api,\n logger,\n db,\n config,\n}: TaskOptions): Promise<void> {\n if (!config.getOptionalString('copilot.enterprise')) {\n logger.info(\n '[discoverEnterpriseTeamMetrics] Skipping: Enterprise configuration not found.',\n );\n return;\n }\n\n const type: MetricsType = 'enterprise';\n\n try {\n const teams = await api.fetchEnterpriseTeams();\n logger.info(\n `[discoverEnterpriseTeamMetrics] Fetched ${teams.length} teams`,\n );\n\n for (const team of teams) {\n try {\n logger.info(\n `[discoverEnterpriseTeamMetrics] Fetching metrics for team: ${team.slug}`,\n );\n\n const copilotMetrics = await api.fetchEnterpriseTeamCopilotMetrics(\n team.slug,\n );\n\n const lastDay = await db.getMostRecentDayFromMetricsV2(type, team.slug);\n logger.info(\n `[discoverEnterpriseTeamMetrics] Found last day: ${lastDay}`,\n );\n\n const newMetrics: CopilotMetrics[] = filterNewMetricsV2(\n copilotMetrics,\n lastDay,\n );\n logger.info(\n `[discoverEnterpriseTeamMetrics] Found ${newMetrics.length} new metrics to insert for team: ${team.slug}`,\n );\n\n if (newMetrics.length > 0) {\n const coPilotMetrics = filterBaseMetrics(newMetrics, type, team.slug);\n const ideCompletionsToInsert = filterIdeCompletionMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideCompletionsLanguagesToInsert =\n filterIdeCompletionLanguageMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorsToInsert =\n filterIdeCompletionEditorMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelsToInsert =\n filterIdeCompletionEditorModelMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelLanguagesToInsert =\n filterIdeCompletionEditorModelLanguageMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChats = filterIdeChatMetrics(newMetrics, type, team.slug);\n const ideChatEditors = filterIdeEditorMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChatEditorModels = filterIdeChatEditorModelMetrics(\n newMetrics,\n type,\n team.slug,\n );\n\n await batchInsertInChunks(coPilotMetrics, 30, async chunk => {\n await db.batchInsertMetrics(chunk);\n });\n\n await batchInsertInChunks(ideCompletionsToInsert, 30, async chunk => {\n await db.batchInsertIdeCompletions(chunk);\n });\n\n await batchInsertInChunks(\n ideCompletionsLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditors(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModels(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModelLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(ideChats, 30, async chunk => {\n await db.batchInsertIdeChats(chunk);\n });\n\n await batchInsertInChunks(ideChatEditors, 30, async chunk => {\n await db.batchInsertIdeChatEditors(chunk);\n });\n\n await batchInsertInChunks(ideChatEditorModels, 30, async chunk => {\n await db.batchInsertIdeChatEditorModels(chunk);\n });\n\n // Fetch seat analysis\n const seats = await api.fetchEnterpriseSeats();\n const seatsToInsert = convertToTeamSeatAnalysis(\n seats,\n type,\n team.slug,\n );\n await db.insertSeatAnalysys(seatsToInsert);\n\n logger.info(\n `[discoverEnterpriseTeamMetrics] Inserted new metrics into the database for team: ${team.slug}`,\n );\n } else {\n logger.info(\n `[discoverEnterpriseTeamMetrics] No new metrics found to insert for team: ${team.slug}`,\n );\n }\n } catch (error) {\n logger.error(\n `[discoverEnterpriseTeamMetrics] Error processing metrics for team ${team.slug}`,\n error,\n );\n }\n }\n } catch (error) {\n logger.error('[discoverEnterpriseTeamMetrics] Error fetching teams', error);\n throw error;\n }\n}\n"],"names":["filterNewMetricsV2","filterBaseMetrics","filterIdeCompletionMetrics","filterIdeCompletionLanguageMetrics","filterIdeCompletionEditorMetrics","filterIdeCompletionEditorModelMetrics","filterIdeCompletionEditorModelLanguageMetrics","filterIdeChatMetrics","filterIdeEditorMetrics","filterIdeChatEditorModelMetrics","batchInsertInChunks","convertToTeamSeatAnalysis"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EnterpriseTeamTask.cjs.js","sources":["../../src/task/EnterpriseTeamTask.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n CopilotMetrics,\n MetricsType,\n} from '@backstage-community/plugin-copilot-common';\nimport { batchInsertInChunks } from '../utils/batchInsert';\nimport {\n convertToTeamSeatAnalysis,\n filterBaseMetrics,\n filterIdeChatEditorModelMetrics,\n filterIdeChatMetrics,\n filterIdeCompletionEditorMetrics,\n filterIdeCompletionEditorModelLanguageMetrics,\n filterIdeCompletionEditorModelMetrics,\n filterIdeCompletionLanguageMetrics,\n filterIdeCompletionMetrics,\n filterIdeEditorMetrics,\n filterNewMetricsV2,\n} from '../utils/metricHelpers';\nimport { TaskOptions } from './TaskManagement';\n\nexport async function discoverEnterpriseTeamMetrics({\n api,\n logger,\n db,\n config,\n}: TaskOptions): Promise<void> {\n if (!config.getOptionalString('copilot.enterprise')) {\n logger.info(\n '[discoverEnterpriseTeamMetrics] Skipping: Enterprise configuration not found.',\n );\n return;\n }\n\n const type: MetricsType = 'enterprise';\n\n try {\n const teams = await api.fetchEnterpriseTeams();\n logger.info(\n `[discoverEnterpriseTeamMetrics] Fetched ${teams.length} teams`,\n );\n\n // Fetch seat analysis\n const seats = await api.fetchEnterpriseSeats();\n logger.info(\n `[discoverEnterpriseTeamMetrics] Fetched ${seats.length} seats from enterprise`,\n );\n\n for (const team of teams) {\n try {\n logger.info(\n `[discoverEnterpriseTeamMetrics] Fetching metrics for team: ${team.slug}`,\n );\n\n const copilotMetrics = await api.fetchEnterpriseTeamCopilotMetrics(\n team.slug,\n );\n\n const lastDay = await db.getMostRecentDayFromMetricsV2(type, team.slug);\n logger.info(\n `[discoverEnterpriseTeamMetrics] Found last day: ${lastDay}`,\n );\n\n const newMetrics: CopilotMetrics[] = filterNewMetricsV2(\n copilotMetrics,\n lastDay,\n );\n logger.info(\n `[discoverEnterpriseTeamMetrics] Found ${newMetrics.length} new metrics to insert for team: ${team.slug}`,\n );\n\n if (newMetrics.length > 0) {\n const coPilotMetrics = filterBaseMetrics(newMetrics, type, team.slug);\n const ideCompletionsToInsert = filterIdeCompletionMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideCompletionsLanguagesToInsert =\n filterIdeCompletionLanguageMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorsToInsert =\n filterIdeCompletionEditorMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelsToInsert =\n filterIdeCompletionEditorModelMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelLanguagesToInsert =\n filterIdeCompletionEditorModelLanguageMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChats = filterIdeChatMetrics(newMetrics, type, team.slug);\n const ideChatEditors = filterIdeEditorMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChatEditorModels = filterIdeChatEditorModelMetrics(\n newMetrics,\n type,\n team.slug,\n );\n\n await batchInsertInChunks(coPilotMetrics, 30, async chunk => {\n await db.batchInsertMetrics(chunk);\n });\n\n await batchInsertInChunks(ideCompletionsToInsert, 30, async chunk => {\n await db.batchInsertIdeCompletions(chunk);\n });\n\n await batchInsertInChunks(\n ideCompletionsLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditors(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModels(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModelLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(ideChats, 30, async chunk => {\n await db.batchInsertIdeChats(chunk);\n });\n\n await batchInsertInChunks(ideChatEditors, 30, async chunk => {\n await db.batchInsertIdeChatEditors(chunk);\n });\n\n await batchInsertInChunks(ideChatEditorModels, 30, async chunk => {\n await db.batchInsertIdeChatEditorModels(chunk);\n });\n\n const seatsToInsert = convertToTeamSeatAnalysis(\n seats,\n type,\n team.slug,\n );\n await db.insertSeatAnalysys(seatsToInsert);\n\n logger.info(\n `[discoverEnterpriseTeamMetrics] Inserted new metrics into the database for team: ${team.slug}`,\n );\n } else {\n logger.info(\n `[discoverEnterpriseTeamMetrics] No new metrics found to insert for team: ${team.slug}`,\n );\n }\n } catch (error) {\n logger.error(\n `[discoverEnterpriseTeamMetrics] Error processing metrics for team ${team.slug}`,\n error,\n );\n }\n }\n } catch (error) {\n logger.error('[discoverEnterpriseTeamMetrics] Error fetching teams', error);\n throw error;\n }\n}\n"],"names":["filterNewMetricsV2","filterBaseMetrics","filterIdeCompletionMetrics","filterIdeCompletionLanguageMetrics","filterIdeCompletionEditorMetrics","filterIdeCompletionEditorModelMetrics","filterIdeCompletionEditorModelLanguageMetrics","filterIdeChatMetrics","filterIdeEditorMetrics","filterIdeChatEditorModelMetrics","batchInsertInChunks","convertToTeamSeatAnalysis"],"mappings":"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"}
|
|
@@ -21,6 +21,10 @@ async function discoverOrganizationTeamMetrics({
|
|
|
21
21
|
logger.info(
|
|
22
22
|
`[discoverOrganizationTeamMetrics] Fetched ${teams.length} teams`
|
|
23
23
|
);
|
|
24
|
+
const seats = await api.fetchOrganizationSeats();
|
|
25
|
+
logger.info(
|
|
26
|
+
`[discoverOrganizationTeamMetrics] Fetched ${seats.seats.length} seats from organization`
|
|
27
|
+
);
|
|
24
28
|
for (const team of teams) {
|
|
25
29
|
try {
|
|
26
30
|
logger.info(
|
|
@@ -109,7 +113,6 @@ async function discoverOrganizationTeamMetrics({
|
|
|
109
113
|
await batchInsert.batchInsertInChunks(ideChatEditorModels, 30, async (chunk) => {
|
|
110
114
|
await db.batchInsertIdeChatEditorModels(chunk);
|
|
111
115
|
});
|
|
112
|
-
const seats = await api.fetchOrganizationSeats();
|
|
113
116
|
const seatsToInsert = metricHelpers.convertToTeamSeatAnalysis(
|
|
114
117
|
seats,
|
|
115
118
|
type,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrganizationTeamTask.cjs.js","sources":["../../src/task/OrganizationTeamTask.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CopilotMetrics,\n MetricsType,\n} from '@backstage-community/plugin-copilot-common';\nimport { batchInsertInChunks } from '../utils/batchInsert';\nimport {\n convertToTeamSeatAnalysis,\n filterBaseMetrics,\n filterIdeChatEditorModelMetrics,\n filterIdeChatMetrics,\n filterIdeCompletionEditorMetrics,\n filterIdeCompletionEditorModelLanguageMetrics,\n filterIdeCompletionEditorModelMetrics,\n filterIdeCompletionLanguageMetrics,\n filterIdeCompletionMetrics,\n filterIdeEditorMetrics,\n filterNewMetricsV2,\n} from '../utils/metricHelpers';\nimport { TaskOptions } from './TaskManagement';\n\nexport async function discoverOrganizationTeamMetrics({\n api,\n logger,\n db,\n config,\n}: TaskOptions): Promise<void> {\n if (!config.getOptionalString('copilot.organization')) {\n logger.info(\n '[discoverOrganizationTeamMetrics] Skipping: Organization configuration not found.',\n );\n return;\n }\n\n const type: MetricsType = 'organization';\n\n try {\n const teams = await api.fetchOrganizationTeams();\n logger.info(\n `[discoverOrganizationTeamMetrics] Fetched ${teams.length} teams`,\n );\n\n for (const team of teams) {\n try {\n logger.info(\n `[discoverOrganizationTeamMetrics] Fetching metrics for team: ${team.slug}`,\n );\n\n const copilotMetrics = await api.fetchOrganizationTeamCopilotMetrics(\n team.slug,\n );\n\n const lastDay = await db.getMostRecentDayFromMetricsV2(type, team.slug);\n logger.info(\n `[discoverOrganizationTeamMetrics] Found last day: ${lastDay}`,\n );\n\n const newMetrics: CopilotMetrics[] = filterNewMetricsV2(\n copilotMetrics,\n lastDay,\n );\n logger.info(\n `[discoverOrganizationTeamMetrics] Found ${newMetrics.length} new metrics to insert for team: ${team.slug}`,\n );\n\n if (newMetrics.length > 0) {\n const coPilotMetrics = filterBaseMetrics(newMetrics, type, team.slug);\n const ideCompletionsToInsert = filterIdeCompletionMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideCompletionsLanguagesToInsert =\n filterIdeCompletionLanguageMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorsToInsert =\n filterIdeCompletionEditorMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelsToInsert =\n filterIdeCompletionEditorModelMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelLanguagesToInsert =\n filterIdeCompletionEditorModelLanguageMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChats = filterIdeChatMetrics(newMetrics, type, team.slug);\n const ideChatEditors = filterIdeEditorMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChatEditorModels = filterIdeChatEditorModelMetrics(\n newMetrics,\n type,\n team.slug,\n );\n\n await batchInsertInChunks(coPilotMetrics, 30, async chunk => {\n await db.batchInsertMetrics(chunk);\n });\n\n await batchInsertInChunks(ideCompletionsToInsert, 30, async chunk => {\n await db.batchInsertIdeCompletions(chunk);\n });\n\n await batchInsertInChunks(\n ideCompletionsLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditors(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModels(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModelLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(ideChats, 30, async chunk => {\n await db.batchInsertIdeChats(chunk);\n });\n\n await batchInsertInChunks(ideChatEditors, 30, async chunk => {\n await db.batchInsertIdeChatEditors(chunk);\n });\n\n await batchInsertInChunks(ideChatEditorModels, 30, async chunk => {\n await db.batchInsertIdeChatEditorModels(chunk);\n });\n\n // Fetch seat analysis\n const seats = await api.fetchOrganizationSeats();\n const seatsToInsert = convertToTeamSeatAnalysis(\n seats,\n type,\n team.slug,\n );\n await db.insertSeatAnalysys(seatsToInsert);\n\n logger.info(\n `[discoverOrganizationTeamMetrics] Inserted new metrics into the database for team: ${team.slug}`,\n );\n } else {\n logger.info(\n `[discoverOrganizationTeamMetrics] No new metrics found to insert for team: ${team.slug}`,\n );\n }\n } catch (error) {\n logger.error(\n `[discoverOrganizationTeamMetrics] Error processing metrics for team ${team.slug}`,\n error,\n );\n }\n }\n } catch (error) {\n logger.error(\n '[discoverOrganizationTeamMetrics] Error fetching teams',\n error,\n );\n throw error;\n }\n}\n"],"names":["filterNewMetricsV2","filterBaseMetrics","filterIdeCompletionMetrics","filterIdeCompletionLanguageMetrics","filterIdeCompletionEditorMetrics","filterIdeCompletionEditorModelMetrics","filterIdeCompletionEditorModelLanguageMetrics","filterIdeChatMetrics","filterIdeEditorMetrics","filterIdeChatEditorModelMetrics","batchInsertInChunks","convertToTeamSeatAnalysis"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrganizationTeamTask.cjs.js","sources":["../../src/task/OrganizationTeamTask.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CopilotMetrics,\n MetricsType,\n} from '@backstage-community/plugin-copilot-common';\nimport { batchInsertInChunks } from '../utils/batchInsert';\nimport {\n convertToTeamSeatAnalysis,\n filterBaseMetrics,\n filterIdeChatEditorModelMetrics,\n filterIdeChatMetrics,\n filterIdeCompletionEditorMetrics,\n filterIdeCompletionEditorModelLanguageMetrics,\n filterIdeCompletionEditorModelMetrics,\n filterIdeCompletionLanguageMetrics,\n filterIdeCompletionMetrics,\n filterIdeEditorMetrics,\n filterNewMetricsV2,\n} from '../utils/metricHelpers';\nimport { TaskOptions } from './TaskManagement';\n\nexport async function discoverOrganizationTeamMetrics({\n api,\n logger,\n db,\n config,\n}: TaskOptions): Promise<void> {\n if (!config.getOptionalString('copilot.organization')) {\n logger.info(\n '[discoverOrganizationTeamMetrics] Skipping: Organization configuration not found.',\n );\n return;\n }\n\n const type: MetricsType = 'organization';\n\n try {\n const teams = await api.fetchOrganizationTeams();\n logger.info(\n `[discoverOrganizationTeamMetrics] Fetched ${teams.length} teams`,\n );\n\n // Fetch seat analysis\n const seats = await api.fetchOrganizationSeats();\n logger.info(\n `[discoverOrganizationTeamMetrics] Fetched ${seats.seats.length} seats from organization`,\n );\n\n for (const team of teams) {\n try {\n logger.info(\n `[discoverOrganizationTeamMetrics] Fetching metrics for team: ${team.slug}`,\n );\n\n const copilotMetrics = await api.fetchOrganizationTeamCopilotMetrics(\n team.slug,\n );\n\n const lastDay = await db.getMostRecentDayFromMetricsV2(type, team.slug);\n logger.info(\n `[discoverOrganizationTeamMetrics] Found last day: ${lastDay}`,\n );\n\n const newMetrics: CopilotMetrics[] = filterNewMetricsV2(\n copilotMetrics,\n lastDay,\n );\n logger.info(\n `[discoverOrganizationTeamMetrics] Found ${newMetrics.length} new metrics to insert for team: ${team.slug}`,\n );\n\n if (newMetrics.length > 0) {\n const coPilotMetrics = filterBaseMetrics(newMetrics, type, team.slug);\n const ideCompletionsToInsert = filterIdeCompletionMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideCompletionsLanguagesToInsert =\n filterIdeCompletionLanguageMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorsToInsert =\n filterIdeCompletionEditorMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelsToInsert =\n filterIdeCompletionEditorModelMetrics(newMetrics, type, team.slug);\n const ideCompletionsEditorModelLanguagesToInsert =\n filterIdeCompletionEditorModelLanguageMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChats = filterIdeChatMetrics(newMetrics, type, team.slug);\n const ideChatEditors = filterIdeEditorMetrics(\n newMetrics,\n type,\n team.slug,\n );\n const ideChatEditorModels = filterIdeChatEditorModelMetrics(\n newMetrics,\n type,\n team.slug,\n );\n\n await batchInsertInChunks(coPilotMetrics, 30, async chunk => {\n await db.batchInsertMetrics(chunk);\n });\n\n await batchInsertInChunks(ideCompletionsToInsert, 30, async chunk => {\n await db.batchInsertIdeCompletions(chunk);\n });\n\n await batchInsertInChunks(\n ideCompletionsLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditors(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelsToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModels(chunk);\n },\n );\n\n await batchInsertInChunks(\n ideCompletionsEditorModelLanguagesToInsert,\n 30,\n async chunk => {\n await db.batchInsertIdeCompletionsEditorModelLanguages(chunk);\n },\n );\n\n await batchInsertInChunks(ideChats, 30, async chunk => {\n await db.batchInsertIdeChats(chunk);\n });\n\n await batchInsertInChunks(ideChatEditors, 30, async chunk => {\n await db.batchInsertIdeChatEditors(chunk);\n });\n\n await batchInsertInChunks(ideChatEditorModels, 30, async chunk => {\n await db.batchInsertIdeChatEditorModels(chunk);\n });\n\n const seatsToInsert = convertToTeamSeatAnalysis(\n seats,\n type,\n team.slug,\n );\n await db.insertSeatAnalysys(seatsToInsert);\n\n logger.info(\n `[discoverOrganizationTeamMetrics] Inserted new metrics into the database for team: ${team.slug}`,\n );\n } else {\n logger.info(\n `[discoverOrganizationTeamMetrics] No new metrics found to insert for team: ${team.slug}`,\n );\n }\n } catch (error) {\n logger.error(\n `[discoverOrganizationTeamMetrics] Error processing metrics for team ${team.slug}`,\n error,\n );\n }\n }\n } catch (error) {\n logger.error(\n '[discoverOrganizationTeamMetrics] Error fetching teams',\n error,\n );\n throw error;\n }\n}\n"],"names":["filterNewMetricsV2","filterBaseMetrics","filterIdeCompletionMetrics","filterIdeCompletionLanguageMetrics","filterIdeCompletionEditorMetrics","filterIdeCompletionEditorModelMetrics","filterIdeCompletionEditorModelLanguageMetrics","filterIdeChatMetrics","filterIdeEditorMetrics","filterIdeChatEditorModelMetrics","batchInsertInChunks","convertToTeamSeatAnalysis"],"mappings":"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"}
|