Skip to content

Commit 183a15f

Browse files
authored
Fix issues with PerformanceReport Page (commit data, hiding missing data) (#1461)
Co-authored-by: Travis Stark <[email protected]>
1 parent 55ee5f4 commit 183a15f

File tree

10 files changed

+227
-98
lines changed

10 files changed

+227
-98
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"react": "^18.2.0",
3232
"react-apexcharts": "^1.4.0",
3333
"react-dom": "^18.2.0",
34+
"react-markdown": "^9.0.1",
3435
"react-router-dom": "^6.8.1",
3536
"react-scripts": "5.0.1",
3637
"recoil": "^0.7.6",

src/common/Axios.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import axios from 'axios';
55

66
export const AxiosConfig = axios.create({
77
baseURL: process.env.REACT_APP_LAMBDA_URL,
8-
timeout: 3000,
8+
// timeout in milliseconds; increased from 3000ms due to large number of commit data requests
9+
timeout: 4000,
910
headers: {
1011
'Content-Type': 'application/json',
1112
},

src/common/Constant.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
export const USE_CASE: string[] = ['statsd', 'logs', 'disk'];
55
export const REPORTED_METRICS: string[] = [
6-
'cpu_usage',
76
'procstat_cpu_usage',
87
'procstat_memory_rss',
98
'procstat_memory_swap',
@@ -18,8 +17,7 @@ export const TRANSACTION_PER_MINUTE: number[] = [100, 1000, 5000];
1817
export const OWNER_REPOSITORY: string = 'aws';
1918
export const SERVICE_NAME: string = 'AmazonCloudWatchAgent';
2019
export const CONVERT_REPORTED_METRICS_NAME: { [metric_name: string]: string } = {
21-
cpu_usage: 'CPU Usage',
22-
procstat_cpu_usage: 'Procstat CPU Usage',
20+
procstat_cpu_usage: 'CPU Usage',
2321
procstat_memory_rss: 'Memory Resource',
2422
procstat_memory_swap: 'Memory Swap',
2523
procstat_memory_vms: 'Virtual Memory',

src/containers/PerformanceReport/data.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ export interface PerformanceMetricReport {
4343
};
4444

4545
UseCase: { S: string };
46+
Service: { S: string };
47+
UniqueID: { S: string };
4648
}
4749

4850
// PerformanceMetric shows all collected metrics when running performance metrics
4951
export interface PerformanceMetric {
50-
cpu_usage?: { M: PerformanceMetricStatistic };
5152
procstat_cpu_usage?: { M: PerformanceMetricStatistic };
5253
procstat_memory_rss?: { M: PerformanceMetricStatistic };
5354
procstat_memory_swap?: { M: PerformanceMetricStatistic };
@@ -72,13 +73,15 @@ export interface PerformanceMetricStatistic {
7273
export interface ServiceLatestVersion {
7374
// Release version for the service
7475
tag_name: string;
76+
body: string;
7577
}
7678

7779
export interface ServicePRInformation {
7880
// Release version for the service
7981
title: string;
8082
html_url: string;
8183
number: number;
84+
sha: string;
8285
}
8386

8487
export interface UseCaseData {
@@ -87,7 +90,6 @@ export interface UseCaseData {
8790
instance_type?: string;
8891
data: {
8992
[data_rate: string]: {
90-
cpu_usage?: string;
9193
procstat_cpu_usage?: string;
9294
procstat_memory_rss?: string;
9395
procstat_memory_swap?: string;

src/containers/PerformanceReport/index.tsx

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: MIT
3-
import { CircularProgress, Container, Link, MenuItem, Paper, Select, Table, TableBody, TableCell, TableContainer, TableRow, Typography } from '@mui/material';
3+
import { Button, CircularProgress, Container, Link, MenuItem, Paper, Select, Table, TableBody, TableCell, TableContainer, TableRow, Typography } from '@mui/material';
44
import moment from 'moment';
55
import * as React from 'react';
66
import { TRANSACTION_PER_MINUTE } from '../../common/Constant';
77
import { usePageEffect } from '../../core/page';
88
import { PerformanceTable } from '../../core/table';
9-
import { UseCaseData } from './data';
10-
import { GetLatestPerformanceReports, GetServiceLatestVersion } from './service';
9+
import { ServicePRInformation, UseCaseData } from './data';
10+
import { createDefaultServicePRInformation, GetLatestPerformanceReports, GetServiceLatestVersion, GetServicePRInformation } from './service';
1111
import { PasswordDialog } from '../../common/Dialog';
12+
import { SelectChangeEvent } from '@mui/material/Select';
13+
import ReactMarkdown from 'react-markdown';
14+
1215
export default function PerformanceReport(props: { password: string; password_is_set: boolean; set_password_state: any }): JSX.Element {
1316
usePageEffect({ title: 'Amazon CloudWatch Agent' });
1417
const { password, password_is_set, set_password_state } = props;
15-
const [{ version, commit_date, commit_title, commit_hash, commit_url, use_cases, ami_id, collection_period }] = useStatePerformanceReport(password);
18+
const [{ version, commit_date, commit_title, commit_hash, commit_url, use_cases, ami_id, collection_period, body }] = useStatePerformanceReport(password);
1619
const [{ data_type }, setDataTypeState] = useStateDataType();
20+
const [isHidden, setIsHidden] = React.useState(true);
21+
22+
const handleDataTypeChange = (event: SelectChangeEvent) => {
23+
setDataTypeState({ data_type: event.target.value });
24+
};
25+
26+
const toggleContent = () => {
27+
setIsHidden(!isHidden);
28+
};
29+
const selectedUseCaseData: UseCaseData[] = use_cases.filter((useCase: UseCaseData) => useCase?.data_type?.toLowerCase() === data_type.toLowerCase());
1730

1831
return (
1932
<Container>
@@ -56,7 +69,7 @@ export default function PerformanceReport(props: { password: string; password_is
5669
aria-label="a dense table"
5770
>
5871
<TableBody>
59-
{['Version', 'Architectural', 'Collection Period', 'Testing AMI', 'Commit Hash', 'Commit Name', 'Commit Date', 'Data Type']?.map((name) => (
72+
{['Version', 'Architectural', 'Collection Period', 'Testing AMI', 'Commit Hash', 'Commit Name', 'Commit Date', 'Data Type', 'Release Notes']?.map((name) => (
6073
<TableRow key={name}>
6174
<TableCell
6275
sx={{
@@ -69,7 +82,6 @@ export default function PerformanceReport(props: { password: string; password_is
6982
<TableCell
7083
sx={{
7184
border: '1px solid #000',
72-
textAlign: 'center',
7385
}}
7486
>
7587
{name === 'Version' ? (
@@ -88,24 +100,33 @@ export default function PerformanceReport(props: { password: string; password_is
88100
</Link>
89101
) : name === 'Commit Date' ? (
90102
<Typography variant="h4">{commit_date}</Typography>
91-
) : (
92-
<Select
93-
sx={{ height: '41px' }}
94-
value={data_type}
95-
onChange={(e: {
96-
target: {
97-
value: string;
98-
};
99-
}) =>
100-
setDataTypeState({
101-
data_type: e.target.value,
102-
})
103-
}
104-
>
103+
) : name === 'Data Type' ? (
104+
<Select sx={{ height: '41px' }} value={data_type} onChange={handleDataTypeChange}>
105105
<MenuItem value={'Metrics'}>Metric</MenuItem>
106106
<MenuItem value={'Traces'}>Trace</MenuItem>
107107
<MenuItem value={'Logs'}>Logs</MenuItem>
108108
</Select>
109+
) : (
110+
<div>
111+
<Button
112+
onClick={toggleContent}
113+
className="toggle-button"
114+
variant="outlined"
115+
sx={{
116+
marginBottom: 0,
117+
backgroundColor: '#ffffff',
118+
borderColor: '#333333',
119+
color: '#333333',
120+
'&:hover': {
121+
backgroundColor: '#f5f5f5',
122+
borderColor: '#333333',
123+
},
124+
}}
125+
>
126+
{isHidden ? 'Show release notes' : 'Hide release notes'}
127+
</Button>
128+
{!isHidden && <ReactMarkdown className="markdown-content">{body}</ReactMarkdown>}
129+
</div>
109130
)}
110131
</TableCell>
111132
</TableRow>
@@ -120,7 +141,7 @@ export default function PerformanceReport(props: { password: string; password_is
120141
<Typography sx={{ mb: 2, fontWeight: 'bold' }} variant="h3">
121142
{data_type} (TPM: {tpm}){' '}
122143
</Typography>
123-
<PerformanceTable data_rate={String(tpm)} use_cases={use_cases.filter((use_case: UseCaseData) => use_case?.data_type === data_type.toLowerCase())} />
144+
<PerformanceTable key={data_type} data_rate={String(tpm)} use_cases={selectedUseCaseData} />
124145
</Container>
125146
))}
126147
</Container>
@@ -140,6 +161,7 @@ function useStatePerformanceReport(password: string) {
140161
ami_id: undefined as string | undefined,
141162
collection_period: undefined as string | undefined,
142163
error: undefined as string | undefined,
164+
body: undefined as string | undefined,
143165
});
144166

145167
React.useEffect(() => {
@@ -155,8 +177,9 @@ function useStatePerformanceReport(password: string) {
155177

156178
const use_cases: UseCaseData[] = [];
157179
// We only get the latest commit ID; therefore, only use case are different; however, general metadata
158-
// information (e.g Commit_Hash, Commit_Date of the PR) would be the same for all datas.
180+
// information (e.g Commit_Hash, Commit_Date of the PR) would be the same for all data.
159181
const commit_hash = performance_reports.at(0)?.CommitHash.S || '';
182+
const commitHashes = performance_reports.map((report) => report.CommitHash?.S);
160183
const commit_date = performance_reports.at(0)?.CommitDate.N;
161184
const collection_period = performance_reports.at(0)?.CollectionPeriod.S;
162185
const ami_id = performance_reports.at(0)?.InstanceAMI.S;
@@ -166,11 +189,10 @@ function useStatePerformanceReport(password: string) {
166189
name: pReport?.UseCase.S,
167190
data_type: pReport?.DataType.S,
168191
instance_type: pReport?.InstanceType.S,
169-
data: TRANSACTION_PER_MINUTE.reduce(
192+
data: Object.keys(pReport?.Results.M).reduce(
170193
(accu, tpm) => ({
171194
...accu,
172195
[tpm]: {
173-
cpu_usage: pReport?.Results.M[tpm]?.M?.cpu_usage?.M?.Average?.N,
174196
procstat_cpu_usage: pReport?.Results.M[tpm]?.M?.procstat_cpu_usage?.M?.Average?.N,
175197
procstat_memory_rss: pReport?.Results.M[tpm]?.M?.procstat_memory_rss?.M?.Average?.N,
176198
procstat_memory_swap: pReport?.Results.M[tpm]?.M?.procstat_memory_swap?.M?.Average?.N,
@@ -187,26 +209,44 @@ function useStatePerformanceReport(password: string) {
187209
),
188210
});
189211
}
190-
// const commit_info = await GetServicePRInformation(password, commit_hash);
212+
const commit_info: ServicePRInformation[] = await GetServicePRInformation(password, commitHashes);
213+
const commit_info_finalized = commit_info.find((value) => value !== undefined) ?? createDefaultServicePRInformation();
191214

192215
setState((prev: any) => ({
193216
...prev,
194217
version: service_info.tag_name,
195218
ami_id: ami_id,
196219
collection_period: collection_period,
197220
use_cases: use_cases,
198-
// commit_title: `${commit_info?.title} (#${commit_info?.number})`,
199-
// commit_url: commit_info?.html_url,
200-
commit_hash: commit_hash,
201-
commit_title: `PlaceHolder`,
202-
commit_url: `www.github.com/aws/amazon-cloudwatch-agent`,
203-
commit_date: moment.unix(Number(commit_date)).format('dddd, MMMM Do, YYYY h:mm:ss A'),
221+
commit_title: `${commit_info_finalized?.title} (#${commit_info_finalized?.number})`,
222+
commit_url: commit_info_finalized?.html_url,
223+
commit_hash: commit_info_finalized?.sha ?? commit_hash,
224+
commit_date: formatUnixTimestamp(commit_date ?? 0),
225+
body: service_info.body ?? 'Release notes unavailable',
204226
}));
205227
})();
206228
}, [password, setState]);
207229
return [state, setState] as const;
208230
}
209231

232+
export const formatUnixTimestamp = (timestamp: string | number, format: string = 'dddd, MMMM Do, YYYY h:mm:ss A'): string => {
233+
try {
234+
// Handle string input
235+
const unixTime = typeof timestamp === 'string' ? Number(timestamp) : timestamp;
236+
237+
// Validate timestamp
238+
if (!Number.isFinite(unixTime) || unixTime < 0) {
239+
console.log('invalid unix timestamp:');
240+
return moment.unix(0).format(format);
241+
}
242+
243+
return moment.unix(unixTime).format(format);
244+
} catch (error) {
245+
console.error('Error formatting unix timestamp:', error);
246+
return moment.unix(0).format(format);
247+
}
248+
};
249+
210250
function useStateDataType() {
211251
const [state, setState] = React.useState({
212252
data_type: 'Metrics' as 'Metrics' | 'Traces' | 'Logs' | string,

src/containers/PerformanceReport/service.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,38 @@ export async function GetServiceLatestVersion(password: string): Promise<Service
6363
});
6464
}
6565

66-
export async function GetServicePRInformation(password: string, commit_sha: string): Promise<ServicePRInformation> {
67-
AxiosConfig.defaults.headers['x-api-key'] = password;
68-
return AxiosConfig.post('/', {
69-
Action: 'Github',
70-
URL: 'GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls',
71-
Params: {
72-
owner: OWNER_REPOSITORY,
73-
repo: process.env.REACT_APP_GITHUB_REPOSITORY,
74-
commit_sha: commit_sha,
75-
},
76-
})
77-
.then(function (body: { data: any[] }) {
78-
return Promise.resolve(body.data.at(0));
79-
})
80-
.catch(function (error: unknown) {
81-
return Promise.reject(error);
66+
export async function GetServicePRInformation(password: string, commitHashes: string[]): Promise<ServicePRInformation[]> {
67+
try {
68+
AxiosConfig.defaults.headers['x-api-key'] = password;
69+
const prInformation = commitHashes.map(async (commitHash) => {
70+
const result = await AxiosConfig.post('/', {
71+
Action: 'Github',
72+
URL: 'GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls',
73+
Params: {
74+
owner: OWNER_REPOSITORY,
75+
repo: process.env.REACT_APP_GITHUB_REPOSITORY,
76+
commit_sha: commitHash,
77+
},
78+
});
79+
if (result.data?.data?.length === undefined) {
80+
console.log('PR Info not found for: ' + commitHash);
81+
return undefined;
82+
}
83+
84+
return result.data?.data?.at(0);
8285
});
86+
87+
return Promise.all(prInformation);
88+
} catch (error) {
89+
return Promise.reject(error);
90+
}
91+
}
92+
93+
export function createDefaultServicePRInformation(): ServicePRInformation {
94+
return {
95+
title: 'PR data unavailable',
96+
html_url: 'https://github.com/aws/amazon-cloudwatch-agent/pulls',
97+
number: 0,
98+
sha: 'default-sha',
99+
};
83100
}

src/containers/PerformanceTrend/data.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,13 @@ export interface ServiceCommitInformation {
7777
// Release version for the service
7878
author: {
7979
login: string;
80-
date: string;
8180
};
82-
commit: { message: string };
81+
commit: {
82+
message: string;
83+
author: {
84+
date: string;
85+
};
86+
};
8387
sha: string;
8488
}
8589

0 commit comments

Comments
 (0)