@nitin15j/plugin-dora-backend
Version:
This plugin backend was templated using the Backstage CLI. You should replace this text with a description of your plugin backend.
244 lines (241 loc) • 9.18 kB
JavaScript
;
class MetricsService {
constructor(client, logger) {
this.client = client;
this.logger = logger;
}
parseDateRange(rangeStr) {
const match = rangeStr.match(/last(\d+)days/i);
if (!match) {
throw new Error("Invalid date range format. Expected format: lastXdays (e.g., last7days)");
}
return parseInt(match[1], 10);
}
calculateDateRanges(dateRange) {
const days = this.parseDateRange(dateRange);
const now = /* @__PURE__ */ new Date();
const currentEnd = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1, 0, 0, 0, 0));
const currentStart = new Date(currentEnd);
currentStart.setUTCDate(currentStart.getUTCDate() - days);
const previousEnd = new Date(currentStart);
const previousStart = new Date(previousEnd);
previousStart.setUTCDate(previousStart.getUTCDate() - days);
return {
currentRangeStart: currentStart.toISOString(),
currentRangeEnd: currentEnd.toISOString(),
previousRangeStart: previousStart.toISOString(),
previousRangeEnd: previousEnd.toISOString()
};
}
async getProjectMetrics(projectSlug, environment, deploymentId, timeRange) {
try {
const dateRanges = this.calculateDateRanges(timeRange);
this.logger.info("Fetching metrics", {
projectSlug,
timeRange
});
const response = await this.client.projectMetrics({
projectSlug,
environment,
deploymentSlug: deploymentId,
metricTypes: ["metrics"],
currentRangeStart: dateRanges.currentRangeStart,
currentRangeEnd: dateRanges.currentRangeEnd,
previousRangeStart: dateRanges.previousRangeStart,
previousRangeEnd: dateRanges.previousRangeEnd
});
if (!response.project?.currentRange || !response.project?.previousRange) {
throw new Error("No metrics data available");
}
this.logger.info("Retrieved metrics", {
projectSlug,
currentRange: {
avgLeadTimeInSec: response.project.currentRange.avgLeadTimeInSec,
numOfDeploys: response.project.currentRange.numOfDeploys,
numOfDeploysPerDay: response.project.currentRange.numOfDeploysPerDay,
failureRatePercent: response.project.currentRange.failureRatePercent,
avgMttrDurationInSec: response.project.currentRange.avgMttrDurationInSec
},
previousRange: {
avgLeadTimeInSec: response.project.previousRange.avgLeadTimeInSec,
numOfDeploys: response.project.previousRange.numOfDeploys,
numOfDeploysPerDay: response.project.previousRange.numOfDeploysPerDay,
failureRatePercent: response.project.previousRange.failureRatePercent,
avgMttrDurationInSec: response.project.previousRange.avgMttrDurationInSec
}
});
return response;
} catch (error) {
this.logger.error("Failed to fetch metrics", {
error: error instanceof Error ? error.message : String(error),
projectSlug
});
throw error;
}
}
async getProjectMetricsInsights(projectSlug, environment, deploymentId, timeRange) {
try {
const dateRanges = this.calculateDateRanges(timeRange);
this.logger.info("Fetching metrics Insights", {
projectSlug,
timeRange
});
const response = await this.client.projectMetricsInsights({
projectSlug,
environment,
deploymentSlug: deploymentId,
metricTypes: ["metrics"],
currentRangeStart: dateRanges.currentRangeStart,
currentRangeEnd: dateRanges.currentRangeEnd,
previousRangeStart: dateRanges.previousRangeStart,
previousRangeEnd: dateRanges.previousRangeEnd
});
if (!response) {
throw new Error("No metrics Insights data available");
}
this.logger.info("Retrieved metrics Insights");
return response;
} catch (error) {
this.logger.error("Failed to fetch metrics insights", {
error: error instanceof Error ? error.message : String(error),
projectSlug
});
throw error;
}
}
async getOrganizationTrendMetrics(timeRange) {
try {
this.logger.info("Fetching organization trend metrics", {
timeRange
});
const dateRanges = this.calculateDateRanges(timeRange);
const organization = await this.client.getTrendMetrics(
dateRanges.currentRangeStart,
dateRanges.currentRangeEnd
);
this.logger.info("Retrieved organization trend metrics", { organization });
return organization;
} catch (error) {
this.logger.error("Failed to fetch organization trend metrics", {
error: error instanceof Error ? error.message : String(error)
});
throw error;
}
}
async getTeamMetrics(teamSlug, environment, timeRange) {
try {
const dateRanges = this.calculateDateRanges(timeRange);
this.logger.info("Fetching team metrics", {
teamSlug,
timeRange
});
const response = await this.client.teamMetrics({
teamSlug,
environment,
currentRangeStart: dateRanges.currentRangeStart,
currentRangeEnd: dateRanges.currentRangeEnd,
previousRangeStart: dateRanges.previousRangeStart,
previousRangeEnd: dateRanges.previousRangeEnd
});
if (!response.team?.currentRange || !response.team?.previousRange) {
throw new Error("No team metrics data available");
}
this.logger.info("Retrieved team metrics", {
teamSlug,
teamName: response.team.name,
currentRange: {
avgLeadTimeInSec: response.team.currentRange.avgLeadTimeInSec,
numOfDeploys: response.team.currentRange.numOfDeploys,
numOfDeploysPerDay: response.team.currentRange.numOfDeploysPerDay,
failureRatePercent: response.team.currentRange.failureRatePercent,
avgMttrDurationInSec: response.team.currentRange.avgMttrDurationInSec
},
previousRange: {
avgLeadTimeInSec: response.team.previousRange.avgLeadTimeInSec,
numOfDeploys: response.team.previousRange.numOfDeploys,
numOfDeploysPerDay: response.team.previousRange.numOfDeploysPerDay,
failureRatePercent: response.team.previousRange.failureRatePercent,
avgMttrDurationInSec: response.team.previousRange.avgMttrDurationInSec
}
});
return response;
} catch (error) {
this.logger.error("Failed to fetch team metrics", {
error: error instanceof Error ? error.message : String(error),
teamSlug,
timeRange
});
throw error;
}
}
async getTeamMetricsInsights(teamSlug, environment, deploymentId, timeRange) {
try {
const dateRanges = this.calculateDateRanges(timeRange);
this.logger.info("Fetching team metrics insights", {
teamSlug,
timeRange
});
const response = await this.client.teamMetricsInsights({
teamSlug,
environment,
deploymentSlug: deploymentId,
currentRangeStart: dateRanges.currentRangeStart,
currentRangeEnd: dateRanges.currentRangeEnd,
previousRangeStart: dateRanges.previousRangeStart,
previousRangeEnd: dateRanges.previousRangeEnd
});
if (!response.data?.project?.insights) {
throw new Error("No team metrics insights data available");
}
this.logger.info("Retrieved team metrics insights", {
teamSlug,
insightsCount: response.data.project.insights.length
});
return response;
} catch (error) {
this.logger.error("Failed to fetch team metrics insights", {
error: error instanceof Error ? error.message : String(error),
teamSlug,
timeRange
});
throw error;
}
}
async getBatchTeamMetrics(teamSlugs, environment, deploymentId, timeRange) {
try {
const dateRanges = this.calculateDateRanges(timeRange);
this.logger.info("Fetching batch team metrics", {
teamSlugs,
timeRange,
environment,
deploymentId
});
const teamRequests = teamSlugs.map((teamSlug) => ({
teamSlug,
environment,
currentRangeStart: dateRanges.currentRangeStart,
currentRangeEnd: dateRanges.currentRangeEnd,
previousRangeStart: dateRanges.previousRangeStart,
previousRangeEnd: dateRanges.previousRangeEnd
}));
const response = await this.client.batchTeamMetrics(teamRequests);
if (!response.teams || response.teams.length === 0) {
throw new Error("No batch team metrics data available");
}
this.logger.info("Retrieved batch team metrics", {
teamCount: response.teams.length,
teamSlugs: response.teams.map((team) => team.name)
});
return response;
} catch (error) {
this.logger.error("Failed to fetch batch team metrics", {
error: error instanceof Error ? error.message : String(error),
teamSlugs,
timeRange
});
throw error;
}
}
}
exports.MetricsService = MetricsService;
//# sourceMappingURL=MetricsService.cjs.js.map