Skip to content

Commit

Permalink
Fix issues with PerformanceReport Page (commit data, hiding missing d…
Browse files Browse the repository at this point in the history
…ata) (#1461)

Co-authored-by: Travis Stark <[email protected]>
  • Loading branch information
TravisStark and Travis Stark authored Jan 9, 2025
1 parent 55ee5f4 commit 183a15f
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 98 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"react": "^18.2.0",
"react-apexcharts": "^1.4.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.8.1",
"react-scripts": "5.0.1",
"recoil": "^0.7.6",
Expand Down
3 changes: 2 additions & 1 deletion src/common/Axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import axios from 'axios';

export const AxiosConfig = axios.create({
baseURL: process.env.REACT_APP_LAMBDA_URL,
timeout: 3000,
// timeout in milliseconds; increased from 3000ms due to large number of commit data requests
timeout: 4000,
headers: {
'Content-Type': 'application/json',
},
Expand Down
4 changes: 1 addition & 3 deletions src/common/Constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

export const USE_CASE: string[] = ['statsd', 'logs', 'disk'];
export const REPORTED_METRICS: string[] = [
'cpu_usage',
'procstat_cpu_usage',
'procstat_memory_rss',
'procstat_memory_swap',
Expand All @@ -18,8 +17,7 @@ export const TRANSACTION_PER_MINUTE: number[] = [100, 1000, 5000];
export const OWNER_REPOSITORY: string = 'aws';
export const SERVICE_NAME: string = 'AmazonCloudWatchAgent';
export const CONVERT_REPORTED_METRICS_NAME: { [metric_name: string]: string } = {
cpu_usage: 'CPU Usage',
procstat_cpu_usage: 'Procstat CPU Usage',
procstat_cpu_usage: 'CPU Usage',
procstat_memory_rss: 'Memory Resource',
procstat_memory_swap: 'Memory Swap',
procstat_memory_vms: 'Virtual Memory',
Expand Down
6 changes: 4 additions & 2 deletions src/containers/PerformanceReport/data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ export interface PerformanceMetricReport {
};

UseCase: { S: string };
Service: { S: string };
UniqueID: { S: string };
}

// PerformanceMetric shows all collected metrics when running performance metrics
export interface PerformanceMetric {
cpu_usage?: { M: PerformanceMetricStatistic };
procstat_cpu_usage?: { M: PerformanceMetricStatistic };
procstat_memory_rss?: { M: PerformanceMetricStatistic };
procstat_memory_swap?: { M: PerformanceMetricStatistic };
Expand All @@ -72,13 +73,15 @@ export interface PerformanceMetricStatistic {
export interface ServiceLatestVersion {
// Release version for the service
tag_name: string;
body: string;
}

export interface ServicePRInformation {
// Release version for the service
title: string;
html_url: string;
number: number;
sha: string;
}

export interface UseCaseData {
Expand All @@ -87,7 +90,6 @@ export interface UseCaseData {
instance_type?: string;
data: {
[data_rate: string]: {
cpu_usage?: string;
procstat_cpu_usage?: string;
procstat_memory_rss?: string;
procstat_memory_swap?: string;
Expand Down
102 changes: 71 additions & 31 deletions src/containers/PerformanceReport/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
import { CircularProgress, Container, Link, MenuItem, Paper, Select, Table, TableBody, TableCell, TableContainer, TableRow, Typography } from '@mui/material';
import { Button, CircularProgress, Container, Link, MenuItem, Paper, Select, Table, TableBody, TableCell, TableContainer, TableRow, Typography } from '@mui/material';
import moment from 'moment';
import * as React from 'react';
import { TRANSACTION_PER_MINUTE } from '../../common/Constant';
import { usePageEffect } from '../../core/page';
import { PerformanceTable } from '../../core/table';
import { UseCaseData } from './data';
import { GetLatestPerformanceReports, GetServiceLatestVersion } from './service';
import { ServicePRInformation, UseCaseData } from './data';
import { createDefaultServicePRInformation, GetLatestPerformanceReports, GetServiceLatestVersion, GetServicePRInformation } from './service';
import { PasswordDialog } from '../../common/Dialog';
import { SelectChangeEvent } from '@mui/material/Select';
import ReactMarkdown from 'react-markdown';

export default function PerformanceReport(props: { password: string; password_is_set: boolean; set_password_state: any }): JSX.Element {
usePageEffect({ title: 'Amazon CloudWatch Agent' });
const { password, password_is_set, set_password_state } = props;
const [{ version, commit_date, commit_title, commit_hash, commit_url, use_cases, ami_id, collection_period }] = useStatePerformanceReport(password);
const [{ version, commit_date, commit_title, commit_hash, commit_url, use_cases, ami_id, collection_period, body }] = useStatePerformanceReport(password);
const [{ data_type }, setDataTypeState] = useStateDataType();
const [isHidden, setIsHidden] = React.useState(true);

const handleDataTypeChange = (event: SelectChangeEvent) => {
setDataTypeState({ data_type: event.target.value });
};

const toggleContent = () => {
setIsHidden(!isHidden);
};
const selectedUseCaseData: UseCaseData[] = use_cases.filter((useCase: UseCaseData) => useCase?.data_type?.toLowerCase() === data_type.toLowerCase());

return (
<Container>
Expand Down Expand Up @@ -56,7 +69,7 @@ export default function PerformanceReport(props: { password: string; password_is
aria-label="a dense table"
>
<TableBody>
{['Version', 'Architectural', 'Collection Period', 'Testing AMI', 'Commit Hash', 'Commit Name', 'Commit Date', 'Data Type']?.map((name) => (
{['Version', 'Architectural', 'Collection Period', 'Testing AMI', 'Commit Hash', 'Commit Name', 'Commit Date', 'Data Type', 'Release Notes']?.map((name) => (
<TableRow key={name}>
<TableCell
sx={{
Expand All @@ -69,7 +82,6 @@ export default function PerformanceReport(props: { password: string; password_is
<TableCell
sx={{
border: '1px solid #000',
textAlign: 'center',
}}
>
{name === 'Version' ? (
Expand All @@ -88,24 +100,33 @@ export default function PerformanceReport(props: { password: string; password_is
</Link>
) : name === 'Commit Date' ? (
<Typography variant="h4">{commit_date}</Typography>
) : (
<Select
sx={{ height: '41px' }}
value={data_type}
onChange={(e: {
target: {
value: string;
};
}) =>
setDataTypeState({
data_type: e.target.value,
})
}
>
) : name === 'Data Type' ? (
<Select sx={{ height: '41px' }} value={data_type} onChange={handleDataTypeChange}>
<MenuItem value={'Metrics'}>Metric</MenuItem>
<MenuItem value={'Traces'}>Trace</MenuItem>
<MenuItem value={'Logs'}>Logs</MenuItem>
</Select>
) : (
<div>
<Button
onClick={toggleContent}
className="toggle-button"
variant="outlined"
sx={{
marginBottom: 0,
backgroundColor: '#ffffff',
borderColor: '#333333',
color: '#333333',
'&:hover': {
backgroundColor: '#f5f5f5',
borderColor: '#333333',
},
}}
>
{isHidden ? 'Show release notes' : 'Hide release notes'}
</Button>
{!isHidden && <ReactMarkdown className="markdown-content">{body}</ReactMarkdown>}
</div>
)}
</TableCell>
</TableRow>
Expand All @@ -120,7 +141,7 @@ export default function PerformanceReport(props: { password: string; password_is
<Typography sx={{ mb: 2, fontWeight: 'bold' }} variant="h3">
{data_type} (TPM: {tpm}){' '}
</Typography>
<PerformanceTable data_rate={String(tpm)} use_cases={use_cases.filter((use_case: UseCaseData) => use_case?.data_type === data_type.toLowerCase())} />
<PerformanceTable key={data_type} data_rate={String(tpm)} use_cases={selectedUseCaseData} />
</Container>
))}
</Container>
Expand All @@ -140,6 +161,7 @@ function useStatePerformanceReport(password: string) {
ami_id: undefined as string | undefined,
collection_period: undefined as string | undefined,
error: undefined as string | undefined,
body: undefined as string | undefined,
});

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

const use_cases: UseCaseData[] = [];
// We only get the latest commit ID; therefore, only use case are different; however, general metadata
// information (e.g Commit_Hash, Commit_Date of the PR) would be the same for all datas.
// information (e.g Commit_Hash, Commit_Date of the PR) would be the same for all data.
const commit_hash = performance_reports.at(0)?.CommitHash.S || '';
const commitHashes = performance_reports.map((report) => report.CommitHash?.S);
const commit_date = performance_reports.at(0)?.CommitDate.N;
const collection_period = performance_reports.at(0)?.CollectionPeriod.S;
const ami_id = performance_reports.at(0)?.InstanceAMI.S;
Expand All @@ -166,11 +189,10 @@ function useStatePerformanceReport(password: string) {
name: pReport?.UseCase.S,
data_type: pReport?.DataType.S,
instance_type: pReport?.InstanceType.S,
data: TRANSACTION_PER_MINUTE.reduce(
data: Object.keys(pReport?.Results.M).reduce(
(accu, tpm) => ({
...accu,
[tpm]: {
cpu_usage: pReport?.Results.M[tpm]?.M?.cpu_usage?.M?.Average?.N,
procstat_cpu_usage: pReport?.Results.M[tpm]?.M?.procstat_cpu_usage?.M?.Average?.N,
procstat_memory_rss: pReport?.Results.M[tpm]?.M?.procstat_memory_rss?.M?.Average?.N,
procstat_memory_swap: pReport?.Results.M[tpm]?.M?.procstat_memory_swap?.M?.Average?.N,
Expand All @@ -187,26 +209,44 @@ function useStatePerformanceReport(password: string) {
),
});
}
// const commit_info = await GetServicePRInformation(password, commit_hash);
const commit_info: ServicePRInformation[] = await GetServicePRInformation(password, commitHashes);
const commit_info_finalized = commit_info.find((value) => value !== undefined) ?? createDefaultServicePRInformation();

setState((prev: any) => ({
...prev,
version: service_info.tag_name,
ami_id: ami_id,
collection_period: collection_period,
use_cases: use_cases,
// commit_title: `${commit_info?.title} (#${commit_info?.number})`,
// commit_url: commit_info?.html_url,
commit_hash: commit_hash,
commit_title: `PlaceHolder`,
commit_url: `www.github.com/aws/amazon-cloudwatch-agent`,
commit_date: moment.unix(Number(commit_date)).format('dddd, MMMM Do, YYYY h:mm:ss A'),
commit_title: `${commit_info_finalized?.title} (#${commit_info_finalized?.number})`,
commit_url: commit_info_finalized?.html_url,
commit_hash: commit_info_finalized?.sha ?? commit_hash,
commit_date: formatUnixTimestamp(commit_date ?? 0),
body: service_info.body ?? 'Release notes unavailable',
}));
})();
}, [password, setState]);
return [state, setState] as const;
}

export const formatUnixTimestamp = (timestamp: string | number, format: string = 'dddd, MMMM Do, YYYY h:mm:ss A'): string => {
try {
// Handle string input
const unixTime = typeof timestamp === 'string' ? Number(timestamp) : timestamp;

// Validate timestamp
if (!Number.isFinite(unixTime) || unixTime < 0) {
console.log('invalid unix timestamp:');
return moment.unix(0).format(format);
}

return moment.unix(unixTime).format(format);
} catch (error) {
console.error('Error formatting unix timestamp:', error);
return moment.unix(0).format(format);
}
};

function useStateDataType() {
const [state, setState] = React.useState({
data_type: 'Metrics' as 'Metrics' | 'Traces' | 'Logs' | string,
Expand Down
49 changes: 33 additions & 16 deletions src/containers/PerformanceReport/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,38 @@ export async function GetServiceLatestVersion(password: string): Promise<Service
});
}

export async function GetServicePRInformation(password: string, commit_sha: string): Promise<ServicePRInformation> {
AxiosConfig.defaults.headers['x-api-key'] = password;
return AxiosConfig.post('/', {
Action: 'Github',
URL: 'GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls',
Params: {
owner: OWNER_REPOSITORY,
repo: process.env.REACT_APP_GITHUB_REPOSITORY,
commit_sha: commit_sha,
},
})
.then(function (body: { data: any[] }) {
return Promise.resolve(body.data.at(0));
})
.catch(function (error: unknown) {
return Promise.reject(error);
export async function GetServicePRInformation(password: string, commitHashes: string[]): Promise<ServicePRInformation[]> {
try {
AxiosConfig.defaults.headers['x-api-key'] = password;
const prInformation = commitHashes.map(async (commitHash) => {
const result = await AxiosConfig.post('/', {
Action: 'Github',
URL: 'GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls',
Params: {
owner: OWNER_REPOSITORY,
repo: process.env.REACT_APP_GITHUB_REPOSITORY,
commit_sha: commitHash,
},
});
if (result.data?.data?.length === undefined) {
console.log('PR Info not found for: ' + commitHash);
return undefined;
}

return result.data?.data?.at(0);
});

return Promise.all(prInformation);
} catch (error) {
return Promise.reject(error);
}
}

export function createDefaultServicePRInformation(): ServicePRInformation {
return {
title: 'PR data unavailable',
html_url: 'https://github.com/aws/amazon-cloudwatch-agent/pulls',
number: 0,
sha: 'default-sha',
};
}
8 changes: 6 additions & 2 deletions src/containers/PerformanceTrend/data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,13 @@ export interface ServiceCommitInformation {
// Release version for the service
author: {
login: string;
date: string;
};
commit: { message: string };
commit: {
message: string;
author: {
date: string;
};
};
sha: string;
}

Expand Down
Loading

0 comments on commit 183a15f

Please sign in to comment.