Skip to content

Commit d7fef8d

Browse files
authored
Profiling endpoint fixes (#1707)
- Added support to download all profile tests - profile.zip file was corrupted after download - Add suspension warning - Add Checkbox support - Support for running multiple profiling types at the same time - fix profiling test Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
1 parent 3a09361 commit d7fef8d

File tree

11 files changed

+241
-212
lines changed

11 files changed

+241
-212
lines changed

models/profiler_type.go

Lines changed: 0 additions & 110 deletions
This file was deleted.

models/profiling_start_request.go

Lines changed: 2 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import React, { Fragment, useState } from "react";
2+
import { Theme } from "@mui/material/styles";
3+
import createStyles from "@mui/styles/createStyles";
4+
import withStyles from "@mui/styles/withStyles";
5+
import { Button, Grid } from "@mui/material";
6+
import PageHeader from "../Common/PageHeader/PageHeader";
7+
import PageLayout from "../Common/Layout/PageLayout";
8+
import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
9+
import api from "../../../common/api";
10+
import { ErrorResponseHandler } from "../../../common/types";
11+
import {
12+
actionsTray,
13+
containerForHeader,
14+
inlineCheckboxes,
15+
} from "../Common/FormComponents/common/styleLibrary";
16+
import HelpBox from "../../../common/HelpBox";
17+
import WarnIcon from "../../../icons/WarnIcon";
18+
19+
const styles = (theme: Theme) =>
20+
createStyles({
21+
buttonContainer: {
22+
marginTop: 24,
23+
textAlign: "right",
24+
"& .MuiButton-root": {
25+
marginLeft: 8,
26+
},
27+
},
28+
dropdown: {
29+
marginBottom: 24,
30+
},
31+
checkboxLabel: {
32+
marginTop: 12,
33+
marginRight: 4,
34+
fontSize: 16,
35+
fontWeight: 500,
36+
},
37+
checkboxDisabled: {
38+
opacity: 0.5,
39+
},
40+
inlineCheckboxes: {
41+
...inlineCheckboxes.inlineCheckboxes,
42+
alignItems: "center",
43+
44+
"@media (max-width: 900px)": {
45+
flexFlow: "column",
46+
alignItems: "flex-start",
47+
},
48+
},
49+
...actionsTray,
50+
...containerForHeader(theme.spacing(4)),
51+
});
52+
53+
interface IProfileProps {
54+
classes: any;
55+
}
56+
57+
const Profile = ({ classes }: IProfileProps) => {
58+
const [profilingStarted, setProfilingStarted] = useState<boolean>(false);
59+
const [types, setTypes] = useState<string[]>([
60+
"cpu",
61+
"mem",
62+
"block",
63+
"mutex",
64+
"trace",
65+
"threads",
66+
"goroutines",
67+
]);
68+
69+
const typesList = [
70+
{ label: "cpu", value: "cpu" },
71+
{ label: "mem", value: "mem" },
72+
{ label: "block", value: "block" },
73+
{ label: "mutex", value: "mutex" },
74+
{ label: "trace", value: "trace" },
75+
{ label: "threads", value: "threads" },
76+
{ label: "goroutines", value: "goroutines" },
77+
];
78+
79+
const onCheckboxClick = (e: React.ChangeEvent<HTMLInputElement>) => {
80+
let newArr: string[] = [];
81+
if (types.indexOf(e.target.value) > -1) {
82+
newArr = types.filter((type) => type !== e.target.value);
83+
} else {
84+
newArr = [...types, e.target.value];
85+
}
86+
setTypes(newArr);
87+
};
88+
89+
const startProfiling = () => {
90+
if (!profilingStarted) {
91+
const typeString = types.join(",");
92+
setProfilingStarted(true);
93+
api
94+
.invoke("POST", `/api/v1/profiling/start`, {
95+
type: typeString,
96+
})
97+
.then(() => {})
98+
.catch((err: ErrorResponseHandler) => {
99+
console.log(err);
100+
setProfilingStarted(false);
101+
});
102+
}
103+
};
104+
105+
const stopProfiling = () => {
106+
if (profilingStarted) {
107+
const anchor = document.createElement("a");
108+
document.body.appendChild(anchor);
109+
let path = "/api/v1/profiling/stop";
110+
var req = new XMLHttpRequest();
111+
req.open("POST", path, true);
112+
req.responseType = "blob";
113+
req.onreadystatechange = () => {
114+
if (req.readyState === 4 && req.status === 200) {
115+
let filename = "profile.zip";
116+
setProfilingStarted(false);
117+
var link = document.createElement("a");
118+
link.href = window.URL.createObjectURL(req.response);
119+
link.download = filename;
120+
document.body.appendChild(link);
121+
link.click();
122+
document.body.removeChild(link);
123+
}
124+
};
125+
req.send();
126+
}
127+
};
128+
129+
return (
130+
<Fragment>
131+
<PageHeader label="Profile" />
132+
<PageLayout>
133+
<Grid item xs={12} className={classes.boxy}>
134+
<Grid item xs={12} className={classes.dropdown}>
135+
<Grid
136+
item
137+
xs={12}
138+
className={`${classes.inlineCheckboxes} ${
139+
profilingStarted && classes.checkboxDisabled
140+
}`}
141+
>
142+
<div className={classes.checkboxLabel}>Types to profile:</div>
143+
{typesList.map((t) => (
144+
<CheckboxWrapper
145+
checked={types.indexOf(t.value) > -1}
146+
disabled={profilingStarted}
147+
key={`checkbox-${t.label}`}
148+
id={`checkbox-${t.label}`}
149+
label={t.label}
150+
name={`checkbox-${t.label}`}
151+
onChange={onCheckboxClick}
152+
value={t.value}
153+
/>
154+
))}
155+
</Grid>
156+
</Grid>
157+
<Grid item xs={12} className={classes.buttonContainer}>
158+
<Button
159+
type="submit"
160+
variant="contained"
161+
color="primary"
162+
disabled={profilingStarted || types.length < 1}
163+
onClick={() => {
164+
startProfiling();
165+
}}
166+
>
167+
Start Profiling
168+
</Button>
169+
<Button
170+
type="submit"
171+
variant="contained"
172+
color="primary"
173+
disabled={!profilingStarted}
174+
onClick={() => {
175+
stopProfiling();
176+
}}
177+
>
178+
Stop Profiling
179+
</Button>
180+
</Grid>
181+
</Grid>
182+
{!profilingStarted && (
183+
<Fragment>
184+
<br />
185+
<HelpBox
186+
title={
187+
"During the profiling run all production traffic will be suspended."
188+
}
189+
iconComponent={<WarnIcon />}
190+
help={<Fragment />}
191+
/>
192+
</Fragment>
193+
)}
194+
</PageLayout>
195+
</Fragment>
196+
);
197+
};
198+
199+
export default withStyles(styles)(Profile);

portal-ui/src/screens/Console/Tools/Tools.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ import withSuspense from "../Common/Components/withSuspense";
2727

2828
const Inspect = withSuspense(React.lazy(() => import("./Inspect")));
2929
const Register = withSuspense(React.lazy(() => import("../Support/Register")));
30+
const Profile = withSuspense(React.lazy(() => import("../Support/Profile")));
3031

3132
const Tools = () => {
3233
return (
3334
<Router history={history}>
3435
<Switch>
3536
<Route path={IAM_PAGES.TOOLS} exact component={ToolsList} />
3637
<Route path={IAM_PAGES.REGISTER_SUPPORT} exact component={Register} />
38+
<Route path={IAM_PAGES.PROFILE} exact component={Profile} />
3739
<Route
3840
path={IAM_PAGES.CALL_HOME}
3941
exact

0 commit comments

Comments
 (0)