Skip to content

Commit

Permalink
adding latency with recharts
Browse files Browse the repository at this point in the history
  • Loading branch information
mbarrramsey committed Oct 23, 2024
1 parent af30efb commit d339518
Show file tree
Hide file tree
Showing 4 changed files with 521 additions and 171 deletions.
3 changes: 2 additions & 1 deletion weave-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"onchange": "^7.1.0",
"pako": "^2.1.0",
"pca-js": "^1.0.2",
"plotly.js": "^2.23.2",
"plotly.js": "^2.35.2",
"plotly.js-dist-min": "^2.6.3",
"prismjs": "1.29.0",
"query-string": "^8.1.0",
Expand All @@ -103,6 +103,7 @@
"react-intersection-observer": "^8.31.0",
"react-markdown": "^8.0.7",
"react-measure": "^2.3.0",
"react-plotly.js": "^2.6.0",
"react-redux": "^7.1.1",
"react-resizable": "^3.0.5",
"react-router-dom": "^5.1.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {WFHighLevelCallFilter} from './callsTableFilter';
import {DEFAULT_FILTER_CALLS} from './CallsTable';
import {getCostFromCostData} from '../CallPage/cost';

Check warning on line 8 in weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallsPage/CallsCharts.tsx

View workflow job for this annotation

GitHub Actions / WeaveJS Lint and Compile

'getCostFromCostData' is defined but never used
import GradientAreaChart from './Charts';
import {Tailwind} from '../../../../../Tailwind';

type CallsChartsProps = {
startTime?: number;
Expand Down Expand Up @@ -48,9 +49,9 @@ CallsChartsProps) => {
entity,
project,
filter,
filterModel,
filterModelProp,
0,
1000,
10, // change back to 1000 later
columns, // need to select columns for performance. not working??
columnSet,
sortCalls
Expand All @@ -59,38 +60,50 @@ CallsChartsProps) => {
const [callsResult, setCallsResult] = useState(calls.result);

Check warning on line 60 in weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallsPage/CallsCharts.tsx

View workflow job for this annotation

GitHub Actions / WeaveJS Lint and Compile

'callsResult' is assigned a value but never used

Check warning on line 60 in weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallsPage/CallsCharts.tsx

View workflow job for this annotation

GitHub Actions / WeaveJS Lint and Compile

'setCallsResult' is assigned a value but never used
const [callsTotal, setCallsTotal] = useState(calls.total);

Check warning on line 61 in weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallsPage/CallsCharts.tsx

View workflow job for this annotation

GitHub Actions / WeaveJS Lint and Compile

'callsTotal' is assigned a value but never used

Check warning on line 61 in weave-js/src/components/PagePanelComponents/Home/Browse3/pages/CallsPage/CallsCharts.tsx

View workflow job for this annotation

GitHub Actions / WeaveJS Lint and Compile

'setCallsTotal' is assigned a value but never used

// const costAndTimeData = useMemo(() => {
// return calls.result
// .filter(
// call =>
// call.traceCall?.started_at !== undefined &&
// getCostFromCostData(call.traceCall?.summary?.weave?.costs ?? {})
// .costNumeric !== undefined
// )
// .map(call => ({
// value: getCostFromCostData(call.traceCall?.summary?.weave?.costs ?? {})
// .costNumeric,
// timestamp: call.traceCall?.started_at ?? '',
// }));
// }, [calls.result]);

const costAndTimeData = useMemo(() => {
return calls.result
.filter(
call =>
call.traceCall?.started_at !== undefined &&
getCostFromCostData(call.traceCall?.summary?.weave?.costs ?? {})
.costNumeric !== undefined
)
.map(call => ({
value: getCostFromCostData(call.traceCall?.summary?.weave?.costs ?? {})
.costNumeric,
timestamp: call.traceCall?.started_at ?? '',
}));
return calls.result.map(call => ({
started_at: call.traceCall?.started_at ?? '',
// ended_at: call.traceCall?.ended_at ?? '',
latency: call.traceCall?.summary?.weave?.latency_ms ?? 0,
// timestamp: call.traceCall?.started_at ?? '',
}));
}, [calls.result]);

console.log(calls.result);
// Sum up the cost data

console.log('Cost data:', filter, filterModel, calls, costAndTimeData, calls);
console.log(
'Cost data:',
filter,
filterModelProp,
filterModel,
calls,
costAndTimeData,
calls
);

// const costSums = costconsData !== undefined ? sumCostDataForCostTable(costData) : [];
// console.log(costData2, callsResult);
return (
<>
<div>My Chart</div>
<GradientAreaChart costAndTimeData={costAndTimeData} />
{/* <FilterPanel
filterModel={filterModel}
columnInfo={filterFriendlyColumnInfo}
setFilterModel={setFilterModel}
selectedCalls={selectedCalls}
clearSelectedCalls={clearSelectedCalls}
/> */}
</>
<Tailwind>
<div className="ml-10 mr-10 rounded-lg border border-moon-250 p-[30px]">
<div>Latency</div>
<GradientAreaChart chartData={costAndTimeData} />
</div>
</Tailwind>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
CartesianGrid,
Tooltip,
ResponsiveContainer,
LineChart,
Line,
} from 'recharts';
import moment from 'moment'; // Optional, for formatting timestamps
import {
Expand All @@ -15,51 +17,62 @@ import {
TEAL_500,
TEAL_600,
} from '../../../../../../common/css/color.styles';

const data = [
{timestamp: 1665619200000, value: 30}, // Example timestamps (in milliseconds)
{timestamp: 1665705600000, value: 20},
{timestamp: 1665792000000, value: 50},
{timestamp: 1665878400000, value: 40},
{timestamp: 1665964800000, value: 70},
{timestamp: 1666051200000, value: 60},
];
import _ from 'lodash';

type GradientAreaChartProps = {
costAndTimeData: {
value: number | undefined;
timestamp: string;
}[];
chartData: ChartData[];
};

type ChartData = {
started_at: string;
latency: number;
};

export const GradientAreaChart = ({
costAndTimeData,
}: GradientAreaChartProps) => {
const formattedData = costAndTimeData.map(d => ({
...d,
timestamp: moment(d.timestamp).valueOf(), // Convert to milliseconds
}));
type LatencyData = {
latency: number;
started_at: string;
};

export const GradientAreaChart = ({chartData}: GradientAreaChartProps) => {
const pointsPerGroup = 20; // Group data every 5 points for averaging

const calculatePercentile = (sortedArray: number[], percentile: number) => {
const index = Math.ceil((percentile / 100.0) * sortedArray.length) - 1;
return sortedArray[index];
};

// Generate an array of unique monthly ticks
const startMonth = moment(formattedData[0]?.timestamp).startOf('month');
const endMonth = moment(
formattedData[formattedData.length - 1]?.timestamp
).endOf('month');
const monthlyTicks = [];
const aggregateLatencyData = (data: ChartData[]) => {
// Group the data by 15-minute intervals
return _(data)
.groupBy(d =>
moment(d.started_at)
.startOf('minute')
.minute(Math.floor(moment(d.started_at).minute() / 15) * 15)
.format()
) // Group by 15-minute intervals
.map((group, date) => {
const latencies = group.map(d => d.latency).sort((a, b) => a - b);
const p50 = calculatePercentile(latencies, 50);
const p95 = calculatePercentile(latencies, 95);
const p99 = calculatePercentile(latencies, 99);
const formattedInterval = moment(date).format('MMM DD, YYYY HH:mm'); // Format the 15-minute interval label

let currentMonth = startMonth.clone();
while (currentMonth <= endMonth) {
monthlyTicks.push(currentMonth.valueOf());
currentMonth.add(1, 'month');
}
return {
timestamp: formattedInterval,
p50,
p95,
p99,
};
})
.value();
};

const startTimestamp = formattedData[0]?.timestamp;
const endTimestamp = formattedData[formattedData.length - 1]?.timestamp;
const aggregatedData = aggregateLatencyData(chartData);

return (
<ResponsiveContainer width="100%" height={400}>
<AreaChart
data={formattedData}
<LineChart
data={aggregatedData}
margin={{top: 10, right: 30, left: 0, bottom: 0}}>
<defs>
<linearGradient id="colorValue" x1="0" y1="0" x2="0" y2="1">
Expand All @@ -70,27 +83,45 @@ export const GradientAreaChart = ({
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="timestamp"
type="number"
// scale='point'
// domain={['auto', 'auto']}
domain={['dataMin', 'dataMax']} // Use 'dataMin' and 'dataMax' for exact fit
ticks={monthlyTicks} // Use generated monthly ticks
tickFormatter={tick => moment(tick).format('MMM YYYY')}
type="category"
domain={['auto', 'auto']}
// ticks={ticks}
// tickFormatter={tick => moment(tick).format('MMM DD, YYYY')}
/>

<YAxis />
<Tooltip
labelFormatter={label => moment(label).format('MMM DD, YYYY')} // Format tooltip
cursor={{stroke: TEAL_400, strokeWidth: 2}} // Set crosshair color and thickness
labelFormatter={label => moment(label).format('MMM DD, YYYY')}
cursor={{stroke: TEAL_400, strokeWidth: 2}}
/>
<Line
type="linear"
dataKey="p50"
stroke="#8884d8"
dot={false}
name="p50"
/>
<Line
type="linear"
dataKey="p95"
stroke="#82ca9d"
dot={false}
name="p95"
/>
<Area
<Line
type="linear"
dataKey="p99"
stroke="#ff7300"
dot={false}
name="p99"
/>
{/* <Area
type="monotone"
dataKey="value"
stroke={TEAL_500}
fillOpacity={1}
fill="url(#colorValue)"
/>
</AreaChart>
/> */}
</LineChart>
</ResponsiveContainer>
);
};
Expand Down
Loading

0 comments on commit d339518

Please sign in to comment.