mirror of
https://github.com/grafana/grafana.git
synced 2025-02-16 18:34:52 -06:00
* Explore: Adds support for new loki 'start' and 'end' params for labels endpoint Also initializes absoluteRange when explore is initialized Closes #16788 * Explore: Dispatches updateTimeRangeAction instead of passing absoluteRange when initializing Also removes dependency on sinon from loki language provider test * Loki: Refactors transformation of absolute time range to URL params into small utility function * Makes use of rangeToParams() util function in loki language provider test Also updates LanguageProvider.request() interface so that url should be type string, and adds optional params argument
101 lines
3.6 KiB
TypeScript
101 lines
3.6 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { DataSourceStatus } from '@grafana/ui/src/types/datasource';
|
|
import { AbsoluteTimeRange } from '@grafana/data';
|
|
|
|
import LokiLanguageProvider from 'app/plugins/datasource/loki/language_provider';
|
|
import { CascaderOption } from 'app/plugins/datasource/loki/components/LokiQueryFieldForm';
|
|
import { useRefMounted } from 'app/core/hooks/useRefMounted';
|
|
|
|
/**
|
|
*
|
|
* @param languageProvider
|
|
* @param languageProviderInitialised
|
|
* @param activeOption rc-cascader provided option used to fetch option's values that hasn't been loaded yet
|
|
*
|
|
* @description Fetches missing labels and enables labels refresh
|
|
*/
|
|
export const useLokiLabels = (
|
|
languageProvider: LokiLanguageProvider,
|
|
languageProviderInitialised: boolean,
|
|
activeOption: CascaderOption[],
|
|
absoluteRange: AbsoluteTimeRange,
|
|
datasourceStatus: DataSourceStatus,
|
|
initialDatasourceStatus?: DataSourceStatus // used for test purposes
|
|
) => {
|
|
const mounted = useRefMounted();
|
|
|
|
// State
|
|
const [logLabelOptions, setLogLabelOptions] = useState([]);
|
|
const [shouldTryRefreshLabels, setRefreshLabels] = useState(false);
|
|
const [prevDatasourceStatus, setPrevDatasourceStatus] = useState(
|
|
initialDatasourceStatus || DataSourceStatus.Connected
|
|
);
|
|
const [shouldForceRefreshLabels, setForceRefreshLabels] = useState(false);
|
|
|
|
// Async
|
|
const fetchOptionValues = async (option: string) => {
|
|
await languageProvider.fetchLabelValues(option, absoluteRange);
|
|
if (mounted.current) {
|
|
setLogLabelOptions(languageProvider.logLabelOptions);
|
|
}
|
|
};
|
|
|
|
const tryLabelsRefresh = async () => {
|
|
await languageProvider.refreshLogLabels(absoluteRange, shouldForceRefreshLabels);
|
|
|
|
if (mounted.current) {
|
|
setRefreshLabels(false);
|
|
setForceRefreshLabels(false);
|
|
setLogLabelOptions(languageProvider.logLabelOptions);
|
|
}
|
|
};
|
|
|
|
// Effects
|
|
|
|
// This effect performs loading of options that hasn't been loaded yet
|
|
// It's a subject of activeOption state change only. This is because of specific behavior or rc-cascader
|
|
// https://github.com/react-component/cascader/blob/master/src/Cascader.jsx#L165
|
|
useEffect(() => {
|
|
if (languageProviderInitialised) {
|
|
const targetOption = activeOption[activeOption.length - 1];
|
|
if (targetOption) {
|
|
const nextOptions = logLabelOptions.map(option => {
|
|
if (option.value === targetOption.value) {
|
|
return {
|
|
...option,
|
|
loading: true,
|
|
};
|
|
}
|
|
return option;
|
|
});
|
|
setLogLabelOptions(nextOptions); // to set loading
|
|
fetchOptionValues(targetOption.value);
|
|
}
|
|
}
|
|
}, [activeOption]);
|
|
|
|
// This effect is performed on shouldTryRefreshLabels or shouldForceRefreshLabels state change only.
|
|
// Since shouldTryRefreshLabels is reset AFTER the labels are refreshed we are secured in case of trying to refresh
|
|
// when previous refresh hasn't finished yet
|
|
useEffect(() => {
|
|
if (shouldTryRefreshLabels || shouldForceRefreshLabels) {
|
|
tryLabelsRefresh();
|
|
}
|
|
}, [shouldTryRefreshLabels, shouldForceRefreshLabels]);
|
|
|
|
// This effect is performed on datasourceStatus state change only.
|
|
// We want to make sure to only force refresh AFTER a disconnected state thats why we store the previous datasourceStatus in state
|
|
useEffect(() => {
|
|
if (datasourceStatus === DataSourceStatus.Connected && prevDatasourceStatus === DataSourceStatus.Disconnected) {
|
|
setForceRefreshLabels(true);
|
|
}
|
|
setPrevDatasourceStatus(datasourceStatus);
|
|
}, [datasourceStatus]);
|
|
|
|
return {
|
|
logLabelOptions,
|
|
setLogLabelOptions,
|
|
refreshLabels: () => setRefreshLabels(true),
|
|
};
|
|
};
|