vmui: Improve DownloadConfig button interaction with VMAnomaly (#6397)

Co-authored-by: Dzmitry Lazerka <dlazerka@gmail.com>
This commit is contained in:
Dima Lazerka 2024-06-06 02:07:59 -07:00 committed by Aliaksandr Valialkin
parent 2e3c039113
commit 362ee240cd
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
7 changed files with 34 additions and 8 deletions

View file

@ -71,6 +71,7 @@
"eslint": "^8.44.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-react": "^7.29.4",
"http-proxy-middleware": "^3.0.0",
"react-app-rewired": "^2.2.1",
"webpack": "^5.88.1"
},

View file

@ -9,6 +9,9 @@ import useDeviceDetect from "../../hooks/useDeviceDetect";
import { useAppState } from "../../state/common/StateContext";
import classNames from "classnames";
import "./style.scss";
import { useQueryState } from "../../state/query/QueryStateContext";
import { useTimeState } from "../../state/time/TimeStateContext";
import { getStepFromDuration } from "../../utils/time";
const AnomalyConfig: FC = () => {
const { serverUrl } = useAppState();
@ -20,6 +23,8 @@ const AnomalyConfig: FC = () => {
setFalse: setCloseModal,
} = useBoolean(false);
const { query } = useQueryState();
const { period } = useTimeState();
const [isLoading, setIsLoading] = useState(false);
const [textConfig, setTextConfig] = useState<string>("");
const [downloadUrl, setDownloadUrl] = useState<string>("");
@ -28,15 +33,22 @@ const AnomalyConfig: FC = () => {
const fetchConfig = async () => {
setIsLoading(true);
try {
const url = `${serverUrl}/api/vmanomaly/config.yaml`;
const queryParam = encodeURIComponent(query[0] || "");
const stepParam = encodeURIComponent(period.step || getStepFromDuration(period.end - period.start, false));
const url = `${serverUrl}/api/vmanomaly/config.yaml?query=${queryParam}&step=${stepParam}`;
const response = await fetch(url);
const contentType = response.headers.get("Content-Type");
if (!response.ok) {
setError(` ${response.status} ${response.statusText}`);
} else {
const bodyText = await response.text();
setError(` ${response.status} ${response.statusText}: ${bodyText}`);
} else if (contentType == "application/yaml") {
const blob = await response.blob();
const yamlAsString = await blob.text();
setTextConfig(yamlAsString);
setDownloadUrl(URL.createObjectURL(blob));
} else {
setError("Response Content-Type is not YAML, does `Server URL` point to VMAnomaly server?");
}
} catch (error) {
console.error(error);

View file

@ -88,9 +88,11 @@ const Modal: FC<ModalProps> = ({
</Button>
</div>
</div>
{/* tabIndex to fix Ctrl-A */}
<div
className="vm-modal-content-body"
onMouseDown={handleMouseDown}
tabIndex={0}
>
{children}
</div>

View file

@ -12,7 +12,7 @@ import { useTimeState } from "../state/time/TimeStateContext";
import { useCustomPanelState } from "../state/customPanel/CustomPanelStateContext";
import { isHistogramData } from "../utils/metric";
import { useGraphState } from "../state/graph/GraphStateContext";
import { getSecondsFromDuration, getStepFromDuration } from "../utils/time";
import { getStepFromDuration } from "../utils/time";
import { AppType } from "../types/appType";
interface FetchQueryParams {
@ -183,7 +183,7 @@ export const useFetchQuery = ({
setQueryErrors(expr.map(() => ErrorTypes.validQuery));
} else if (isValidHttpUrl(serverUrl)) {
const updatedPeriod = { ...period };
updatedPeriod.step = isAnomalyUI ? `${getSecondsFromDuration(customStep)*1000}ms` : customStep;
updatedPeriod.step = customStep;
return expr.map(q => displayChart
? getQueryRangeUrl(serverUrl, q, updatedPeriod, nocache, isTracingEnabled)
: getQueryUrl(serverUrl, q, updatedPeriod, nocache, isTracingEnabled));

View file

@ -87,7 +87,7 @@ const ExploreAnomaly: FC = () => {
setHideError={setHideError}
stats={queryStats}
onRunQuery={handleRunQuery}
hideButtons={{ addQuery: true, prettify: true, autocomplete: true, traceQuery: true, anomalyConfig: true }}
hideButtons={{ addQuery: true, prettify: false, autocomplete: false, traceQuery: true, anomalyConfig: true }}
/>
{isLoading && <Spinner/>}
{(!hideError && error) && <Alert variant="error">{error}</Alert>}

View file

@ -0,0 +1,11 @@
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
"/api",
createProxyMiddleware({
target: "http://localhost:8490/api",
changeOrigin: true,
})
);
};

View file

@ -34,7 +34,7 @@ export const humanizeSeconds = (num: number): string => {
return getDurationFromMilliseconds(dayjs.duration(num, "seconds").asMilliseconds());
};
export const roundStep = (step: number) => {
export const roundStep = (step: number): string => {
let result = roundToMilliseconds(step);
const integerStep = Math.round(step);
@ -87,7 +87,7 @@ export const getSecondsFromDuration = (dur: string) => {
return dayjs.duration(durObject).asSeconds();
};
export const getStepFromDuration = (dur: number, histogram?: boolean) => {
export const getStepFromDuration = (dur: number, histogram?: boolean): string => {
const size = histogram ? MAX_ITEMS_PER_HISTOGRAM : MAX_ITEMS_PER_CHART;
return roundStep(dur / size);
};