diff --git a/components/change-failure-rate/changeFailureRate.js b/components/change-failure-rate/changeFailureRate.js
new file mode 100644
index 0000000..c60947e
--- /dev/null
+++ b/components/change-failure-rate/changeFailureRate.js
@@ -0,0 +1,28 @@
+// components/deploymentFrequency.js
+import { useState, useEffect } from 'react';
+import { getDaysBetweenDates } from '@/components/date-range-selector'
+
+export default function useChangeFailureRate(appName, dateRange) {
+ const [cfrData, setCfrData] = useState([]);
+ const [loading, setLoading] = useState(true); // Add loading state
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ const req = `${process.env.NEXT_PUBLIC_PELORUS_API_URL}/sdp/change_failure_rate/${appName}/data?range=${getDaysBetweenDates(dateRange)}d&start=${dateRange.to.getTime() / 1000}`;
+ const response = await fetch(req);
+ const data = await response.json();
+ const sortedData = data.sort((d1, d2) => (d1.timestamp > d2.timestamp) ? 1 : (d1.timestamp < d2.timestamp) ? -1 : 0);
+ setCfrData(sortedData);
+ } catch (error) {
+ console.error('Error fetching deployment frequency data:', error);
+ } finally {
+ setLoading(false); // Set loading to false regardless of success or failure
+ }
+ };
+
+ fetchData();
+ }, [appName, dateRange]);
+
+ return { cfrData, loading }; // Return loading state along with cfrData
+}
diff --git a/components/change-failure-rate/iso-chart.jsx b/components/change-failure-rate/chart.jsx
similarity index 55%
rename from components/change-failure-rate/iso-chart.jsx
rename to components/change-failure-rate/chart.jsx
index 3fd9c9d..3f186c6 100644
--- a/components/change-failure-rate/iso-chart.jsx
+++ b/components/change-failure-rate/chart.jsx
@@ -5,10 +5,8 @@ import { format } from 'date-fns'
import { useTheme } from "next-themes"
import { XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ComposedChart, Area, Line, ReferenceLine } from 'recharts'
import { ChangeFailureRateTooltip } from './tooltip'
-
-const dateFormatter = date => {
- return format(new Date(date), "MMM d")
-}
+import { dateFormatter, dayFormatter } from '@/lib/date-funcs';
+import useChangeFailureRate from './changeFailureRate'
const calculateMean = data => {
if (data.length < 1) {
@@ -17,7 +15,39 @@ const calculateMean = data => {
return data.reduce((prev, current) => prev + current) / data.length
}
-export function IsolatedChangeFailureRateChart({ data }) {
+function eventsPerDay(data) {
+ // Object to store the count of deployments per day
+ const countPerDay = {};
+
+ // Loop through each item in the data array
+ data.forEach(item => {
+ // Convert timestamp to Date object and extract the date
+ const date = new Date(item.timestamp * 1000);
+ // Format the date to YYYY-MM-DD
+ const formattedDate = date.toLocaleDateString().split('T')[0];
+
+ // Increment the count of deployments for the corresponding date
+ if (countPerDay[formattedDate]) {
+ countPerDay[formattedDate]++;
+ } else {
+ countPerDay[formattedDate] = 1;
+ }
+ });
+
+ // Convert the deployments count per day object into an array of objects
+ const result = Object.keys(countPerDay).map(date => ({
+ // Convert date back to epoch format and assign to day_epoch property
+ day_epoch: new Date(date).getTime() / 1000,
+ // Assign the count of deployments to the count property
+ count: countPerDay[date]
+ }));
+
+ // Return the result
+ return result;
+}
+
+
+export function ChangeFailureRateChart({ dateRange, appName }) {
const { resolvedTheme } = useTheme()
const animationDuration = 1000
@@ -36,27 +66,37 @@ export function IsolatedChangeFailureRateChart({ data }) {
const strokeRollingAverage = '#f43f5e' // Rose 500
const strokeGoal = '#f59e0b' // Amber 500
+ const { cfrData, loading } = useChangeFailureRate(appName, dateRange);
+ console.log('Chart cfrData: ', cfrData)
+
+ if (loading) {
+ return
Loading...
; // Render loading state while data is being fetched
+ }
+
+ var countPerDay = eventsPerDay(cfrData);
+ console.log('Count per day', countPerDay)
+
// Calculate the mean
- const averages = data.map(element => {
+ const averages = cfrData.map(element => {
return element.rollingAverage
})
const chartMean = calculateMean(averages)
- // Reports
- const [reportChangeFailureRateData, setReportChangeFailureRateData] = useState(null)
- const [showReportChangeFailureRateData, setShowReportChangeFailureRateData] = useState(false)
+ // // Reports
+ // const [reportChangeFailureRateData, setReportChangeFailureRateData] = useState(null)
+ // const [showReportChangeFailureRateData, setShowReportChangeFailureRateData] = useState(false)
- function handleChartClick(event) {
- setReportChangeFailureRateData(event)
- setShowReportChangeFailureRateData(true)
- }
+ // function handleChartClick(event) {
+ // setReportChangeFailureRateData(event)
+ // setShowReportChangeFailureRateData(true)
+ // }
- // Anomaly detection
- const showAnomalyWarning = data.some((day) => {
- if (day.rollingAverage < day.expectedRange[0] || day.rollingAverage > day.expectedRange[1]) { return true }
- return false
- })
+ // // Anomaly detection
+ // const showAnomalyWarning = data.some((day) => {
+ // if (day.rollingAverage < day.expectedRange[0] || day.rollingAverage > day.expectedRange[1]) { return true }
+ // return false
+ // })
const customAnomalyLabel = props => {
return (
@@ -70,20 +110,20 @@ export function IsolatedChangeFailureRateChart({ data }) {
return (
<>
-
+
-
- `${tick}%`} />
+
+
} cursor={{ stroke: strokeCursor }} />
-
+
- {data.map((day, index) => (
+ {/* {data.map((day, index) => (
day.rollingAverage < day.expectedRange[0] || day.rollingAverage > day.expectedRange[1] && (
)
- ))}
+ ))} */}
{/* */}
diff --git a/components/change-failure-rate/table.jsx b/components/change-failure-rate/table.jsx
index 143914e..af409e3 100644
--- a/components/change-failure-rate/table.jsx
+++ b/components/change-failure-rate/table.jsx
@@ -9,250 +9,48 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table"
-import { Calendar, GitBranch, GitCommit, Globe } from "lucide-react"
+import { Orbit, CalendarCheck, Ticket } from "lucide-react"
+import useChangeFailureRate from "./changeFailureRate";
+import { dateFormatter, dayFormatter } from '@/lib/date-funcs';
+
+export function ChangeFailureRateTable({ dateRange, appName }) {
+
+ const { cfrData, loading } = useChangeFailureRate(appName, dateRange);
+ console.log('Table cfrData: ', cfrData)
+
+ if (loading) {
+ return Loading...
; // Render loading state while data is being fetched
+ }
-export function ChangeFailureRateTable({ data }) {
return (
- Deployment name
- Service
- Date
- Status
+ Ticket Reference
+ App Name
+ Date Created
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
-
-
-
-
- project-crimson-prototype-q6yb8whv
-
-
-
-
- Main
-
-
- 0577e50 Commit name description
-
-
-
-
-
- Jul 26, 2023
-
-
-
-
+ {cfrData.map (({ issue_id, timestamp }) => (
+
+
+
+ {issue_id}
+
+
+
+
+ {appName}
+
+
+
+
+ { dateFormatter(timestamp) }
+
+
+
+ ))}
)
diff --git a/components/change-failure-rate/tooltip.jsx b/components/change-failure-rate/tooltip.jsx
index ed3b971..162bd1e 100644
--- a/components/change-failure-rate/tooltip.jsx
+++ b/components/change-failure-rate/tooltip.jsx
@@ -23,12 +23,12 @@ export const ChangeFailureRateTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
-
{format(new Date(label), "MMM d, y")}
+
{format(new Date(label * 1000), "MMM d, y")}
{payload.map((data, index) => (
{toSentence(data.name)}
-
{data.value instanceof Array ? data.value.join('-') : data.value}%
+
{data.value instanceof Array ? data.value.join('-') : data.value} issues
))}
diff --git a/components/dashboard.jsx b/components/dashboard.jsx
index ce1862e..a112358 100644
--- a/components/dashboard.jsx
+++ b/components/dashboard.jsx
@@ -17,8 +17,8 @@ import {
import { DeploymentFrequencyChart } from '@/components/deployment-frequency/chart'
import { LeadTimeForChangeChart } from '@/components/lead-time-for-change/chart'
-import { IsolatedChangeFailureRateChart } from '@/components/change-failure-rate/iso-chart'
-import { IsolatedMeanTimeToRecoveryChart } from '@/components/mean-time-to-recovery/iso-chart'
+import { ChangeFailureRateChart } from '@/components/change-failure-rate/chart'
+import { MeanTimeToRecoveryChart } from '@/components/mean-time-to-recovery/chart'
import { DeploymentFrequencyTabTrigger } from './deployment-frequency/tab-trigger'
import { ChangeFailureRateTabTrigger } from './change-failure-rate/tab-trigger'
@@ -91,7 +91,6 @@ export function Dashboard({ data, appList }) {
@@ -158,26 +157,26 @@ export function Dashboard({ data, appList }) {
-
+
-
+
diff --git a/components/deployment-frequency/tab-trigger.jsx b/components/deployment-frequency/tab-trigger.jsx
index af80399..263fcaa 100644
--- a/components/deployment-frequency/tab-trigger.jsx
+++ b/components/deployment-frequency/tab-trigger.jsx
@@ -1,6 +1,6 @@
'use client'
-import { Rocket, ArrowDown, ArrowUp } from 'lucide-react'
+import { Rocket, ArrowUp } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { InfoTooltip } from '@/components/info-tooltip'
import { DeploymentFrequencyRating } from '@/components/deployment-frequency/rating'
diff --git a/components/deployment-frequency/table.jsx b/components/deployment-frequency/table.jsx
index 2f6f1dd..462d536 100644
--- a/components/deployment-frequency/table.jsx
+++ b/components/deployment-frequency/table.jsx
@@ -10,7 +10,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table"
-import { Orbit, FileCode, Clock } from "lucide-react"
+import { Orbit, FileCode, CalendarCheck, Blocks, Fingerprint } from "lucide-react"
import useDeploymentFrequencyData from './deploymentFrequency';
import { dateFormatter } from '@/lib/date-funcs';
@@ -37,17 +37,17 @@ export function DeploymentFrequencyTable({ dateRange, appName }) {
- {appName}
+ {appName}
- {image}
+ {image}
- { dateFormatter(timestamp) }
+ { dateFormatter(timestamp) }
diff --git a/components/lead-time-for-change/table.jsx b/components/lead-time-for-change/table.jsx
index 92280aa..70e34fe 100644
--- a/components/lead-time-for-change/table.jsx
+++ b/components/lead-time-for-change/table.jsx
@@ -10,7 +10,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table"
-import { Calendar, GitBranch, GitCommit, Globe, Timer } from "lucide-react"
+import { Calendar, GitCommit, GitGraph, Timer } from "lucide-react"
import { getDaysBetweenDates } from '@/components/date-range-selector'
import {dateFormatter, dayFormatter} from '@/lib/date-funcs';
@@ -39,12 +39,12 @@ export function LeadTimeForChangeTable({ dateRange, appName }) {
- {commit}
+ {commit}
- { dateFormatter(timestamp) }
+ { dateFormatter(timestamp) }
diff --git a/components/mean-time-to-recovery/iso-chart.jsx b/components/mean-time-to-recovery/chart.jsx
similarity index 67%
rename from components/mean-time-to-recovery/iso-chart.jsx
rename to components/mean-time-to-recovery/chart.jsx
index 93f8c30..0e228aa 100644
--- a/components/mean-time-to-recovery/iso-chart.jsx
+++ b/components/mean-time-to-recovery/chart.jsx
@@ -5,10 +5,8 @@ import { useTheme } from "next-themes"
import { format } from 'date-fns'
import { XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ComposedChart, Area, Line, ReferenceLine } from 'recharts'
import { MeanTimeToRecoveryTooltip } from './tooltip'
-
-const dateFormatter = date => {
- return format(new Date(date), "MMM d")
-}
+import useMeanTimeToRestore from './meantimetorestore'
+import { dateFormatter, dayFormatter } from '@/lib/date-funcs';
const calculateMean = data => {
if (data.length < 1) {
@@ -17,7 +15,7 @@ const calculateMean = data => {
return data.reduce((prev, current) => prev + current) / data.length
}
-export function IsolatedMeanTimeToRecoveryChart({ data }) {
+export function MeanTimeToRecoveryChart({ appName, dateRange }) {
const { resolvedTheme } = useTheme()
const animationDuration = 1000
@@ -36,27 +34,34 @@ export function IsolatedMeanTimeToRecoveryChart({ data }) {
const strokeRollingAverage = '#10b981' // Emerald 500
const strokeGoal = '#f59e0b' // Amber 500
+ const { mttrData, loading } = useMeanTimeToRestore(appName, dateRange);
+ console.log('Chart mttrData: ', mttrData)
+
+ if (loading) {
+ return Loading...
; // Render loading state while data is being fetched
+ }
+
// Calculate the mean
- const averages = data.map(element => {
+ const averages = mttrData.map(element => {
return element.rollingAverage
})
const chartMean = calculateMean(averages)
- // Reports
- const [reportMeanTimeToRecoveryData, setReportMeanTimeToRecoveryData] = useState(null)
- const [showReportMeanTimeToRecoveryData, setShowReportMeanTimeToRecoveryData] = useState(false)
+ // // Reports
+ // const [reportMeanTimeToRecoveryData, setReportMeanTimeToRecoveryData] = useState(null)
+ // const [showReportMeanTimeToRecoveryData, setShowReportMeanTimeToRecoveryData] = useState(false)
- function handleChartClick(event) {
- setReportMeanTimeToRecoveryData(event)
- setShowReportMeanTimeToRecoveryData(true)
- }
+ // function handleChartClick(event) {
+ // setReportMeanTimeToRecoveryData(event)
+ // setShowReportMeanTimeToRecoveryData(true)
+ // }
- // Anomaly detection
- const showAnomalyWarning = data.some((day) => {
- if (day.rollingAverage < day.expectedRange[0] || day.rollingAverage > day.expectedRange[1]) { return true }
- return false
- })
+ // // Anomaly detection
+ // const showAnomalyWarning = data.some((day) => {
+ // if (day.rollingAverage < day.expectedRange[0] || day.rollingAverage > day.expectedRange[1]) { return true }
+ // return false
+ // })
const customAnomalyLabel = props => {
return (
@@ -70,20 +75,20 @@ export function IsolatedMeanTimeToRecoveryChart({ data }) {
return (
<>
-
+
-
- `${tick}d`} />
+
+
} cursor={{ stroke: strokeCursor }} />
-
+
- {data.map((day, index) => (
+ {/* {data.map((day, index) => (
day.rollingAverage < day.expectedRange[0] || day.rollingAverage > day.expectedRange[1] && (
)
- ))}
+ ))} */}
{/* */}
diff --git a/components/mean-time-to-recovery/meantimetorestore.js b/components/mean-time-to-recovery/meantimetorestore.js
new file mode 100644
index 0000000..7d9af01
--- /dev/null
+++ b/components/mean-time-to-recovery/meantimetorestore.js
@@ -0,0 +1,29 @@
+// components/deploymentFrequency.js
+import { useState, useEffect } from 'react';
+import { getDaysBetweenDates } from '@/components/date-range-selector'
+
+export default function useMeanTimeToRestore(appName, dateRange) {
+ const [mttrData, setMttrData] = useState([]);
+ const [loading, setLoading] = useState(true); // Add loading state
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ const req = `${process.env.NEXT_PUBLIC_PELORUS_API_URL}/sdp/mean_time_to_restore/${appName}/data?range=${getDaysBetweenDates(dateRange)}d&start=${dateRange.to.getTime() / 1000}`;
+ console.log(req)
+ const response = await fetch(req);
+ const data = await response.json();
+ const sortedData = data.sort((d1, d2) => (d1.timestamp > d2.timestamp) ? 1 : (d1.timestamp < d2.timestamp) ? -1 : 0);
+ setMttrData(sortedData);
+ } catch (error) {
+ console.error('Error fetching deployment frequency data:', error);
+ } finally {
+ setLoading(false); // Set loading to false regardless of success or failure
+ }
+ };
+
+ fetchData();
+ }, [appName, dateRange]);
+
+ return { mttrData, loading }; // Return loading state along with dfData
+}
\ No newline at end of file
diff --git a/components/mean-time-to-recovery/table.jsx b/components/mean-time-to-recovery/table.jsx
index 17266c4..b98fbe3 100644
--- a/components/mean-time-to-recovery/table.jsx
+++ b/components/mean-time-to-recovery/table.jsx
@@ -9,290 +9,54 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table"
-import { Calendar, GitBranch, GitCommit, Globe, Timer } from "lucide-react"
+import { Orbit, FileCode, CalendarCheck, Ticket, Timer } from "lucide-react"
+import useMeanTimeToRestore from "./meantimetorestore";
+import { dateFormatter, dayFormatter } from '@/lib/date-funcs';
+
+export function MeanTimeToRecoveryTable({ dateRange, appName }) {
+
+ const { mttrData, loading } = useMeanTimeToRestore(appName, dateRange);
+ console.log('Table mttrData: ', mttrData)
+
+ if (loading) {
+ return Loading...
; // Render loading state while data is being fetched
+ }
-export function MeanTimeToRecoveryTable({ data }) {
return (
- Failed deployment
- Pull request
- Mean time
- Status
+ Ticket Reference
+ App Name
+ Time to Resolve
+ Date Resolved
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
-
-
-
- Main
-
-
- project-crimson-prototype-q6yb8whv
-
- Jul 19, 2023
-
-
-
- Feature/authentication
-
-
- 0577e50 Commit name description
-
- Jul 26, 2023
-
-
-
-
- 8 days
-
-
-
-
+ {mttrData.map (({ issue_id, time_to_resolve, timestamp }) => (
+
+
+
+ {issue_id}
+
+
+
+
+ {appName}
+
+
+
+
+ {dayFormatter(time_to_resolve)}
+
+
+
+
+ { dateFormatter(timestamp) }
+
+
+
+ ))}
)
diff --git a/components/mean-time-to-recovery/tooltip.jsx b/components/mean-time-to-recovery/tooltip.jsx
index a21aa30..81da4a2 100644
--- a/components/mean-time-to-recovery/tooltip.jsx
+++ b/components/mean-time-to-recovery/tooltip.jsx
@@ -23,7 +23,7 @@ export const MeanTimeToRecoveryTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
-
{format(new Date(label), "MMM d, y")}
+
{format(new Date(label * 1000), "MMM d, y")}
{payload.map((data, index) => (
diff --git a/package.json b/package.json
index d886a9d..aae0817 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"eslint-config-next": "13.4.12",
"framer-motion": "^10.13.1",
"init": "^0.1.2",
- "lucide-react": "^0.263.1",
+ "lucide-react": "^0.315.0",
"next": "^13.4.12",
"next-auth": "^4.22.3",
"next-themes": "^0.2.1",