UNPKG

@enginuity-io/dora-metrics-backend

Version:
392 lines (383 loc) 12.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var knex = require('knex'); var express = require('express'); var cors = require('cors'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var knex__default = /*#__PURE__*/_interopDefaultLegacy(knex); var cors__default = /*#__PURE__*/_interopDefaultLegacy(cors); var __defProp$1 = Object.defineProperty; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$1 = (obj, key, value) => { __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; class DoraMetricsService { constructor(database, logger) { this.database = database; this.logger = logger; // Store metadata for summary endpoint __publicField$1(this, "deploymentFrequencyMetadata"); __publicField$1(this, "leadTimeMetadata"); __publicField$1(this, "mttrMetadata"); __publicField$1(this, "failureRateMetadata"); this.deploymentFrequencyMetadata = { score: "Elite", value: "Multiple deploys per day", trend: "improving" }; this.leadTimeMetadata = { score: "Elite", value: "< 1 day", trend: "stable" }; this.mttrMetadata = { score: "Elite", value: "< 1 hour", trend: "improving" }; this.failureRateMetadata = { score: "High", value: "0-15%", trend: "stable" }; } /** * Get a list of all projects available in DevLake */ async getProjects() { try { this.logger.info("Fetching projects from DevLake"); return [ "elite-project-cicd", "high-project-cicd", "medium-project-cicd", "low-project-cicd" ]; } catch (error) { this.logger.error("Error fetching projects:", error); throw error; } } /** * Get deployment frequency data for a project */ async getDeploymentFrequency(projectKey, timeRange = "30d") { try { this.logger.info(`Fetching deployment frequency for project ${projectKey} with timeRange ${timeRange}`); const today = /* @__PURE__ */ new Date(); const data = Array.from({ length: 30 }, (_, i) => { const date = new Date(today); date.setDate(date.getDate() - (29 - i)); return { period: date.toISOString().split("T")[0], deploymentCount: Math.floor(Math.random() * 5) + 1 // 1-6 deploys per day }; }); this.deploymentFrequencyMetadata = { score: "Elite", value: "Multiple deploys per day", trend: "improving" }; return data; } catch (error) { this.logger.error(`Error fetching deployment frequency for project ${projectKey}:`, error); throw error; } } /** * Get lead time for changes data for a project */ async getLeadTimeForChanges(projectKey, timeRange = "30d") { try { this.logger.info(`Fetching lead time for changes for project ${projectKey} with timeRange ${timeRange}`); const today = /* @__PURE__ */ new Date(); const data = Array.from({ length: 30 }, (_, i) => { const date = new Date(today); date.setDate(date.getDate() - (29 - i)); return { date: date.toISOString().split("T")[0], leadTime: Math.floor(Math.random() * 20) + 1 // 1-21 hours }; }); this.leadTimeMetadata = { score: "Elite", value: "< 1 day", trend: "stable" }; return data; } catch (error) { this.logger.error(`Error fetching lead time for changes for project ${projectKey}:`, error); throw error; } } /** * Get mean time to restore data for a project */ async getMeanTimeToRestore(projectKey, timeRange = "30d") { try { this.logger.info(`Fetching MTTR for project ${projectKey} with timeRange ${timeRange}`); const today = /* @__PURE__ */ new Date(); const data = Array.from({ length: 30 }, (_, i) => { const date = new Date(today); date.setDate(date.getDate() - (29 - i)); return { date: date.toISOString().split("T")[0], mttr: Math.floor(Math.random() * 50) + 10 // 10-60 minutes (converted to hours) }; }); this.mttrMetadata = { score: "Elite", value: "< 1 hour", trend: "improving" }; return data; } catch (error) { this.logger.error(`Error fetching MTTR for project ${projectKey}:`, error); throw error; } } /** * Get change failure rate data for a project */ async getChangeFailureRate(projectKey, timeRange = "30d") { try { this.logger.info(`Fetching change failure rate for project ${projectKey} with timeRange ${timeRange}`); const today = /* @__PURE__ */ new Date(); const data = Array.from({ length: 30 }, (_, i) => { const date = new Date(today); date.setDate(date.getDate() - (29 - i)); return { date: date.toISOString().split("T")[0], rate: Math.floor(Math.random() * 15) // 0-15% failure rate }; }); this.failureRateMetadata = { score: "High", value: "0-15%", trend: "stable" }; return data; } catch (error) { this.logger.error(`Error fetching change failure rate for project ${projectKey}:`, error); throw error; } } /** * Get summary of all DORA metrics for a project */ async getDoraMetricsSummary(projectKey, timeRange = "30d") { try { this.logger.info(`Fetching DORA metrics summary for project ${projectKey} with timeRange ${timeRange}`); return { deploymentFrequency: { value: "Multiple deploys per day", level: "elite" }, leadTimeForChanges: { value: "24 hours", level: "elite" }, meanTimeToRestore: { value: "1 hour", level: "elite" }, changeFailureRate: { value: "5%", level: "elite" } }; } catch (error) { this.logger.error(`Error fetching DORA metrics summary for project ${projectKey}:`, error); throw error; } } } var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; class DevLakeDatabase { constructor(config, logger) { __publicField(this, "client"); const dbConfig = config.getConfig("doraMetrics.database"); const connection = { host: dbConfig.getString("connection.host"), port: dbConfig.getNumber("connection.port"), user: dbConfig.getString("connection.user"), password: dbConfig.getString("connection.password"), database: dbConfig.getString("connection.database") }; logger.info("Creating connection to Apache DevLake database"); this.client = knex__default["default"]({ client: "mysql2", connection, pool: { min: 2, max: 10 } }); } async testConnection() { try { await this.client.raw("SELECT 1"); return true; } catch (error) { return false; } } getClient() { return this.client; } async listTables() { const result = await this.client.raw("SHOW TABLES"); return result[0].map((row) => Object.values(row)[0]); } async describeTable(tableName) { const result = await this.client.raw(`DESCRIBE ${tableName}`); return result[0]; } } function createRouter(options) { const { logger, config, service } = options; const router = express.Router(); const frontendUrl = config.getOptionalString("doraMetrics.frontendUrl") || "http://localhost:8000"; router.use(cors__default["default"]({ origin: frontendUrl, credentials: true })); router.get("/health", (_, res) => { logger.info("DORA Metrics plugin health check"); res.send({ status: "ok" }); }); router.get("/projects", async (_, res) => { try { const projects = await service.getProjects(); res.json(projects); } catch (error) { logger.error(`Error fetching projects: ${error}`); res.status(500).json({ error: "Error fetching projects" }); } }); router.get("/metrics/deployment-frequency", async (req, res) => { const { projectKey, timeRange = "30d" } = req.query; if (!projectKey) { return res.status(400).json({ error: "Project key is required" }); } try { const data = await service.getDeploymentFrequency( projectKey, timeRange ); res.json(data); } catch (error) { logger.error(`Error fetching deployment frequency: ${error}`); res.status(500).json({ error: "Error fetching deployment frequency" }); } }); router.get("/metrics/lead-time", async (req, res) => { const { projectKey, timeRange = "30d" } = req.query; if (!projectKey) { return res.status(400).json({ error: "Project key is required" }); } try { const data = await service.getLeadTimeForChanges( projectKey, timeRange ); res.json(data); } catch (error) { logger.error(`Error fetching lead time: ${error}`); res.status(500).json({ error: "Error fetching lead time" }); } }); router.get("/metrics/mttr", async (req, res) => { const { projectKey, timeRange = "30d" } = req.query; if (!projectKey) { return res.status(400).json({ error: "Project key is required" }); } try { const data = await service.getMeanTimeToRestore( projectKey, timeRange ); res.json(data); } catch (error) { logger.error(`Error fetching MTTR: ${error}`); res.status(500).json({ error: "Error fetching MTTR" }); } }); router.get("/metrics/failure-rate", async (req, res) => { const { projectKey, timeRange = "30d" } = req.query; if (!projectKey) { return res.status(400).json({ error: "Project key is required" }); } try { const data = await service.getChangeFailureRate( projectKey, timeRange ); res.json(data); } catch (error) { logger.error(`Error fetching failure rate: ${error}`); res.status(500).json({ error: "Error fetching failure rate" }); } }); router.get("/metrics/summary", async (req, res) => { const { projectKey, timeRange = "30d" } = req.query; if (!projectKey) { return res.status(400).json({ error: "Project key is required" }); } try { const data = await service.getDoraMetricsSummary( projectKey, timeRange ); res.json(data); } catch (error) { logger.error(`Error fetching metrics summary: ${error}`); res.status(500).json({ error: "Error fetching metrics summary" }); } }); router.get("/auth/guest/refresh", (req, res) => { logger.info("Guest auth refresh request"); res.json({ profile: { email: "guest@example.com", displayName: "Guest User" }, backstageIdentity: { token: "guest-token", identity: { type: "user", ownershipEntityRefs: ["user:default/guest"], userEntityRef: "user:default/guest" } }, expiresAt: new Date(Date.now() + 3600 * 1e3).toISOString() }); }); router.get("/auth/session", (req, res) => { logger.info("Auth session request"); res.json({ identity: { type: "user", ownershipEntityRefs: ["user:default/guest"], userEntityRef: "user:default/guest" }, token: "guest-token", expiresAt: new Date(Date.now() + 3600 * 1e3).toISOString() }); }); return router; } exports.DevLakeDatabase = DevLakeDatabase; exports.DoraMetricsService = DoraMetricsService; exports.createRouter = createRouter; //# sourceMappingURL=index.cjs.js.map