useLokiLabels.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { useState, useEffect } from 'react';
  2. import { DataSourceStatus } from '@grafana/ui/src/types/datasource';
  3. import { AbsoluteTimeRange } from '@grafana/data';
  4. import LokiLanguageProvider from 'app/plugins/datasource/loki/language_provider';
  5. import { CascaderOption } from 'app/plugins/datasource/loki/components/LokiQueryFieldForm';
  6. import { useRefMounted } from 'app/core/hooks/useRefMounted';
  7. /**
  8. *
  9. * @param languageProvider
  10. * @param languageProviderInitialised
  11. * @param activeOption rc-cascader provided option used to fetch option's values that hasn't been loaded yet
  12. *
  13. * @description Fetches missing labels and enables labels refresh
  14. */
  15. export const useLokiLabels = (
  16. languageProvider: LokiLanguageProvider,
  17. languageProviderInitialised: boolean,
  18. activeOption: CascaderOption[],
  19. absoluteRange: AbsoluteTimeRange,
  20. datasourceStatus: DataSourceStatus,
  21. initialDatasourceStatus?: DataSourceStatus // used for test purposes
  22. ) => {
  23. const mounted = useRefMounted();
  24. // State
  25. const [logLabelOptions, setLogLabelOptions] = useState([]);
  26. const [shouldTryRefreshLabels, setRefreshLabels] = useState(false);
  27. const [prevDatasourceStatus, setPrevDatasourceStatus] = useState(
  28. initialDatasourceStatus || DataSourceStatus.Connected
  29. );
  30. const [shouldForceRefreshLabels, setForceRefreshLabels] = useState(false);
  31. // Async
  32. const fetchOptionValues = async (option: string) => {
  33. await languageProvider.fetchLabelValues(option, absoluteRange);
  34. if (mounted.current) {
  35. setLogLabelOptions(languageProvider.logLabelOptions);
  36. }
  37. };
  38. const tryLabelsRefresh = async () => {
  39. await languageProvider.refreshLogLabels(absoluteRange, shouldForceRefreshLabels);
  40. if (mounted.current) {
  41. setRefreshLabels(false);
  42. setForceRefreshLabels(false);
  43. setLogLabelOptions(languageProvider.logLabelOptions);
  44. }
  45. };
  46. // Effects
  47. // This effect performs loading of options that hasn't been loaded yet
  48. // It's a subject of activeOption state change only. This is because of specific behavior or rc-cascader
  49. // https://github.com/react-component/cascader/blob/master/src/Cascader.jsx#L165
  50. useEffect(() => {
  51. if (languageProviderInitialised) {
  52. const targetOption = activeOption[activeOption.length - 1];
  53. if (targetOption) {
  54. const nextOptions = logLabelOptions.map(option => {
  55. if (option.value === targetOption.value) {
  56. return {
  57. ...option,
  58. loading: true,
  59. };
  60. }
  61. return option;
  62. });
  63. setLogLabelOptions(nextOptions); // to set loading
  64. fetchOptionValues(targetOption.value);
  65. }
  66. }
  67. }, [activeOption]);
  68. // This effect is performed on shouldTryRefreshLabels or shouldForceRefreshLabels state change only.
  69. // Since shouldTryRefreshLabels is reset AFTER the labels are refreshed we are secured in case of trying to refresh
  70. // when previous refresh hasn't finished yet
  71. useEffect(() => {
  72. if (shouldTryRefreshLabels || shouldForceRefreshLabels) {
  73. tryLabelsRefresh();
  74. }
  75. }, [shouldTryRefreshLabels, shouldForceRefreshLabels]);
  76. // This effect is performed on datasourceStatus state change only.
  77. // We want to make sure to only force refresh AFTER a disconnected state thats why we store the previous datasourceStatus in state
  78. useEffect(() => {
  79. if (datasourceStatus === DataSourceStatus.Connected && prevDatasourceStatus === DataSourceStatus.Disconnected) {
  80. setForceRefreshLabels(true);
  81. }
  82. setPrevDatasourceStatus(datasourceStatus);
  83. }, [datasourceStatus]);
  84. return {
  85. logLabelOptions,
  86. setLogLabelOptions,
  87. refreshLabels: () => setRefreshLabels(true),
  88. };
  89. };