@grafana/data#AbsoluteTimeRange TypeScript Examples

The following examples show how to use @grafana/data#AbsoluteTimeRange. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: timePicker.test.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
describe('getZoomedTimeRange', () => {
  describe('when called', () => {
    it('then it should return correct result', () => {
      const { range } = setup();
      const expectedRange: AbsoluteTimeRange = {
        from: toUtc('2019-01-01 07:00:00').valueOf(),
        to: toUtc('2019-01-01 19:00:00').valueOf(),
      };

      const result = getZoomedTimeRange(range, 2);

      expect(result).toEqual(expectedRange);
    });
  });
});
Example #2
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
/**
   * Fetch labels for a selector. This is cached by it's args but also by the global timeRange currently selected as
   * they can change over requested time.
   * @param name
   */
  fetchSeriesLabels = async (match: string, absoluteRange: AbsoluteTimeRange): Promise<Record<string, string[]>> => {
    const rangeParams: { start?: number; end?: number } = absoluteRange ? rangeToParams(absoluteRange) : {};
    const url = '/loki/api/v1/series';
    const { start, end } = rangeParams;

    const cacheKey = this.generateCacheKey(url, start, end, match);
    const params = { match, start, end };
    let value = this.seriesCache.get(cacheKey);
    if (!value) {
      // Clear value when requesting new one. Empty object being truthy also makes sure we don't request twice.
      this.seriesCache.set(cacheKey, {});
      const data = await this.request(url, params);
      const { values } = processLabels(data);
      value = values;
      this.seriesCache.set(cacheKey, value);
    }
    return value;
  };
Example #3
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
async fetchLabelValues(key: string, absoluteRange: AbsoluteTimeRange): Promise<string[]> {
    const url = `/api/prom/label/${key}/values`;
    let values: string[] = [];
    const rangeParams: { start?: number; end?: number } = absoluteRange ? rangeToParams(absoluteRange) : {};
    const { start, end } = rangeParams;

    const cacheKey = this.generateCacheKey(url, start, end, key);
    const params = { start, end };
    let value = this.labelsCache.get(cacheKey);
    if (!value) {
      try {
        // Clear value when requesting new one. Empty object being truthy also makes sure we don't request twice.
        this.labelsCache.set(cacheKey, []);
        const res = await this.request(url, params);
        values = res.slice().sort();
        value = values;
        this.labelsCache.set(cacheKey, value);

        // Add to label options
        this.logLabelOptions = this.logLabelOptions.map(keyOption => {
          if (keyOption.value === key) {
            return {
              ...keyOption,
              children: values.map(value => ({ label: value, value })),
            };
          }
          return keyOption;
        });
      } catch (e) {
        console.error(e);
      }
    }
    return value;
  }
Example #4
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
/**
   * Fetches all label keys
   * @param absoluteRange Fetches
   */
  async fetchLogLabels(absoluteRange: AbsoluteTimeRange): Promise<any> {
    const url = '/api/prom/label';
    try {
      this.logLabelFetchTs = Date.now();
      const rangeParams = absoluteRange ? rangeToParams(absoluteRange) : {};
      const res = await this.request(url, rangeParams);
      this.labelKeys = res.slice().sort();
      this.logLabelOptions = this.labelKeys.map((key: string) => ({ label: key, value: key, isLeaf: false }));
    } catch (e) {
      console.error(e);
    }
    return [];
  }
Example #5
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
async getSeriesLabels(selector: string, absoluteRange: AbsoluteTimeRange) {
    if (this.lookupsDisabled) {
      return undefined;
    }
    try {
      return await this.fetchSeriesLabels(selector, absoluteRange);
    } catch (error) {
      // TODO: better error handling
      console.error(error);
      return undefined;
    }
  }
Example #6
Source File: language_provider.test.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
describe('Labels refresh', () => {
  const datasource = makeMockLokiDatasource({});
  const instance = new LanguageProvider(datasource);

  const rangeMock: AbsoluteTimeRange = {
    from: 1560153109000,
    to: 1560163909000,
  };

  beforeEach(() => {
    instance.fetchLogLabels = jest.fn();
  });

  afterEach(() => {
    jest.clearAllMocks();
    clear();
  });

  it("should not refresh labels if refresh interval hasn't passed", () => {
    advanceTo(new Date(2019, 1, 1, 0, 0, 0));
    instance.logLabelFetchTs = Date.now();
    advanceBy(LABEL_REFRESH_INTERVAL / 2);
    instance.refreshLogLabels(rangeMock);
    expect(instance.fetchLogLabels).not.toBeCalled();
  });

  it('should refresh labels if refresh interval passed', () => {
    advanceTo(new Date(2019, 1, 1, 0, 0, 0));
    instance.logLabelFetchTs = Date.now();
    advanceBy(LABEL_REFRESH_INTERVAL + 1);
    instance.refreshLogLabels(rangeMock);
    expect(instance.fetchLogLabels).toBeCalled();
  });
});
Example #7
Source File: language_provider.test.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
describe('Request URL', () => {
  it('should contain range params', async () => {
    const rangeMock: AbsoluteTimeRange = {
      from: 1560153109000,
      to: 1560163909000,
    };

    const datasourceWithLabels = makeMockLokiDatasource({ other: [] });
    const datasourceSpy = jest.spyOn(datasourceWithLabels as any, 'metadataRequest');

    const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
    await instance.refreshLogLabels(rangeMock, true);
    const expectedUrl = '/api/prom/label';
    expect(datasourceSpy).toHaveBeenCalledWith(expectedUrl, rangeToParams(rangeMock));
  });
});
Example #8
Source File: useLokiSyntaxAndLabels.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
useLokiSyntaxAndLabels = (languageProvider: LokiLanguageProvider, absoluteRange: AbsoluteTimeRange) => {
  const languageProviderInitialized = useInitLanguageProvider(languageProvider, absoluteRange);

  const { logLabelOptions, refreshLabels, setActiveOption } = useLokiLabels(
    languageProvider,
    languageProviderInitialized,
    absoluteRange
  );
  const { isSyntaxReady, syntax } = useLokiSyntax(languageProvider, languageProviderInitialized);

  return {
    isSyntaxReady,
    syntax,
    logLabelOptions,
    setActiveOption,
    refreshLabels,
  };
}
Example #9
Source File: useLokiSyntaxAndLabels.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
useInitLanguageProvider = (languageProvider: LokiLanguageProvider, absoluteRange: AbsoluteTimeRange) => {
  const mounted = useRefMounted();

  const [languageProviderInitialized, setLanguageProviderInitialized] = useState(false);

  // Async
  const initializeLanguageProvider = async () => {
    languageProvider.initialRange = absoluteRange;
    await languageProvider.start();
    if (mounted.current) {
      setLanguageProviderInitialized(true);
    }
  };

  useEffect(() => {
    initializeLanguageProvider();
  }, []);

  return languageProviderInitialized;
}
Example #10
Source File: useLokiLabels.test.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
describe('useLokiLabels hook', () => {
  it('should refresh labels', async () => {
    const datasource = makeMockLokiDatasource({});
    const languageProvider = new LanguageProvider(datasource);
    const logLabelOptionsMock = ['Holy mock!'];
    const rangeMock: AbsoluteTimeRange = {
      from: 1560153109000,
      to: 1560153109000,
    };

    languageProvider.logLabelOptions = ['initial'];

    languageProvider.refreshLogLabels = () => {
      languageProvider.logLabelOptions = logLabelOptionsMock;
      return Promise.resolve();
    };

    const { result, waitForNextUpdate } = renderHook(() => useLokiLabels(languageProvider, true, rangeMock));
    expect(result.current.logLabelOptions).toEqual(['initial']);
    act(() => result.current.refreshLabels());
    await waitForNextUpdate();
    expect(result.current.logLabelOptions).toEqual(logLabelOptionsMock);
  });
});
Example #11
Source File: LokiQueryEditor.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
LokiQueryEditor = memo(function LokiQueryEditor(props: Props) {
  const { query, data, datasource, onChange, onRunQuery } = props;

  let absolute: AbsoluteTimeRange;
  if (data && data.request) {
    const { range } = data.request;
    absolute = {
      from: range.from.valueOf(),
      to: range.to.valueOf(),
    };
  } else {
    absolute = {
      from: Date.now() - 10000,
      to: Date.now(),
    };
  }

  return (
    <div>
      <LokiQueryField
        datasource={datasource}
        query={query}
        onChange={onChange}
        onRunQuery={onRunQuery}
        history={[]}
        data={data}
        absoluteRange={absolute}
      />
    </div>
  );
})
Example #12
Source File: actions.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
updateTime = (config: {
  exploreId: ExploreId;
  rawRange?: RawTimeRange;
  absoluteRange?: AbsoluteTimeRange;
}): ThunkResult<void> => {
  return (dispatch, getState) => {
    const { exploreId, absoluteRange: absRange, rawRange: actionRange } = config;
    const itemState = getState().explore[exploreId];
    const timeZone = getTimeZone(getState().user);
    const { range: rangeInState } = itemState;
    let rawRange: RawTimeRange = rangeInState.raw;

    if (absRange) {
      rawRange = {
        from: dateTimeForTimeZone(timeZone, absRange.from),
        to: dateTimeForTimeZone(timeZone, absRange.to),
      };
    }

    if (actionRange) {
      rawRange = actionRange;
    }

    const range = getTimeRange(timeZone, rawRange);
    const absoluteRange: AbsoluteTimeRange = { from: range.from.valueOf(), to: range.to.valueOf() };

    getTimeSrv().init({
      time: range.raw,
      refresh: false,
      getTimezone: () => timeZone,
      timeRangeUpdated: (): any => undefined,
    });

    dispatch(changeRangeAction({ exploreId, range, absoluteRange }));
  };
}
Example #13
Source File: actions.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
updateTimeRange = (options: {
  exploreId: ExploreId;
  rawRange?: RawTimeRange;
  absoluteRange?: AbsoluteTimeRange;
}): ThunkResult<void> => {
  return (dispatch, getState) => {
    const { syncedTimes } = getState().explore;
    if (syncedTimes) {
      dispatch(updateTime({ ...options, exploreId: ExploreId.left }));
      dispatch(runQueries(ExploreId.left));
      dispatch(updateTime({ ...options, exploreId: ExploreId.right }));
      dispatch(runQueries(ExploreId.right));
    } else {
      dispatch(updateTime({ ...options }));
      dispatch(runQueries(options.exploreId));
    }
  };
}
Example #14
Source File: timePicker.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
getShiftedTimeRange = (direction: number, origRange: TimeRange): AbsoluteTimeRange => {
  const range = {
    from: toUtc(origRange.from),
    to: toUtc(origRange.to),
  };

  const timespan = (range.to.valueOf() - range.from.valueOf()) / 2;
  let to: number, from: number;

  if (direction === -1) {
    to = range.to.valueOf() - timespan;
    from = range.from.valueOf() - timespan;
  } else if (direction === 1) {
    to = range.to.valueOf() + timespan;
    from = range.from.valueOf() + timespan;
    if (to > Date.now() && range.to.valueOf() < Date.now()) {
      to = Date.now();
      from = range.from.valueOf();
    }
  } else {
    to = range.to.valueOf();
    from = range.from.valueOf();
  }

  return { from, to };
}
Example #15
Source File: timePicker.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
getZoomedTimeRange = (range: TimeRange, factor: number): AbsoluteTimeRange => {
  const timespan = range.to.valueOf() - range.from.valueOf();
  const center = range.to.valueOf() - timespan / 2;

  const to = center + (timespan * factor) / 2;
  const from = center - (timespan * factor) / 2;

  return { from, to };
}
Example #16
Source File: LokiExploreQueryEditor.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
export function LokiExploreQueryEditor(props: Props) {
  const { query, data, datasource, exploreMode, history, onChange, onRunQuery } = props;

  let absolute: AbsoluteTimeRange;
  if (data && !_.isEmpty(data.request)) {
    const { range } = data.request;

    absolute = {
      from: range.from.valueOf(),
      to: range.to.valueOf(),
    };
  } else {
    absolute = {
      from: Date.now() - 10000,
      to: Date.now(),
    };
  }

  function onChangeQueryLimit(value: string) {
    const { query, onChange } = props;
    const nextQuery = { ...query, maxLines: preprocessMaxLines(value) };
    onChange(nextQuery);
  }

  function preprocessMaxLines(value: string): number {
    if (value.length === 0) {
      // empty input - falls back to dataSource.maxLines limit
      return NaN;
    } else if (value.length > 0 && (isNaN(+value) || +value < 0)) {
      // input with at least 1 character and that is either incorrect (value in the input field is not a number) or negative
      // falls back to the limit of 0 lines
      return 0;
    } else {
      // default case - correct input
      return +value;
    }
  }

  function onMaxLinesChange(e: React.SyntheticEvent<HTMLInputElement>) {
    if (query.maxLines !== preprocessMaxLines(e.currentTarget.value)) {
      onChangeQueryLimit(e.currentTarget.value);
    }
  }

  function onReturnKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Enter') {
      onRunQuery();
    }
  }

  return (
    <LokiQueryField
      datasource={datasource}
      query={query}
      onChange={onChange}
      onRunQuery={onRunQuery}
      history={history}
      data={data}
      absoluteRange={absolute}
      ExtraFieldElement={
        exploreMode === ExploreMode.Logs ? (
          <LokiExploreExtraField
            label={'Line limit'}
            onChangeFunc={onMaxLinesChange}
            onKeyDownFunc={onReturnKeyDown}
            value={query?.maxLines?.toString() || ''}
            type={'number'}
            min={0}
          />
        ) : null
      }
    />
  );
}
Example #17
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
rangeToParams = (range: AbsoluteTimeRange) => ({ start: range.from * NS_IN_MS, end: range.to * NS_IN_MS })
Example #18
Source File: timePicker.test.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
describe('getShiftedTimeRange', () => {
  describe('when called with a direction of -1', () => {
    it('then it should return correct result', () => {
      const { range, direction } = setup({ direction: -1 });
      const expectedRange: AbsoluteTimeRange = {
        from: toUtc('2019-01-01 07:00:00').valueOf(),
        to: toUtc('2019-01-01 13:00:00').valueOf(),
      };

      const result = getShiftedTimeRange(direction, range);

      expect(result).toEqual(expectedRange);
    });
  });

  describe('when called with a direction of 1', () => {
    it('then it should return correct result', () => {
      const { range, direction } = setup({ direction: 1 });
      const expectedRange: AbsoluteTimeRange = {
        from: toUtc('2019-01-01 13:00:00').valueOf(),
        to: toUtc('2019-01-01 19:00:00').valueOf(),
      };

      const result = getShiftedTimeRange(direction, range);

      expect(result).toEqual(expectedRange);
    });
  });

  describe('when called with any other direction', () => {
    it('then it should return correct result', () => {
      const { range, direction } = setup({ direction: 0 });
      const expectedRange: AbsoluteTimeRange = {
        from: toUtc('2019-01-01 10:00:00').valueOf(),
        to: toUtc('2019-01-01 16:00:00').valueOf(),
      };

      const result = getShiftedTimeRange(direction, range);

      expect(result).toEqual(expectedRange);
    });
  });
});
Example #19
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
initialRange: AbsoluteTimeRange;
Example #20
Source File: language_provider.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
async refreshLogLabels(absoluteRange: AbsoluteTimeRange, forceRefresh?: boolean) {
    if ((this.labelKeys && Date.now() - this.logLabelFetchTs > LABEL_REFRESH_INTERVAL) || forceRefresh) {
      await this.fetchLogLabels(absoluteRange);
    }
  }
Example #21
Source File: PanelChrome.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
onChangeTimeRange = (timeRange: AbsoluteTimeRange) => {
    this.timeSrv.setTime({
      from: toUtc(timeRange.from),
      to: toUtc(timeRange.to),
    });
  };
Example #22
Source File: Explore.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
onUpdateTimeRange = (absoluteRange: AbsoluteTimeRange) => {
    const { exploreId, updateTimeRange } = this.props;
    updateTimeRange({ exploreId, absoluteRange });
  };
Example #23
Source File: language_provider.test.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
describe('Query imports', () => {
  const datasource = makeMockLokiDatasource({});

  const rangeMock: AbsoluteTimeRange = {
    from: 1560153109000,
    to: 1560163909000,
  };

  it('returns empty queries for unknown origin datasource', async () => {
    const instance = new LanguageProvider(datasource, { initialRange: rangeMock });
    const result = await instance.importQueries([{ refId: 'bar', expr: 'foo' }], 'unknown');
    expect(result).toEqual([{ refId: 'bar', expr: '' }]);
  });

  describe('prometheus query imports', () => {
    it('returns empty query from metric-only query', async () => {
      const instance = new LanguageProvider(datasource, { initialRange: rangeMock });
      const result = await instance.importPrometheusQuery('foo');
      expect(result).toEqual('');
    });

    it('returns empty query from selector query if label is not available', async () => {
      const datasourceWithLabels = makeMockLokiDatasource({ other: [] });
      const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
      const result = await instance.importPrometheusQuery('{foo="bar"}');
      expect(result).toEqual('{}');
    });

    it('returns selector query from selector query with common labels', async () => {
      const datasourceWithLabels = makeMockLokiDatasource({ foo: [] });
      const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
      const result = await instance.importPrometheusQuery('metric{foo="bar",baz="42"}');
      expect(result).toEqual('{foo="bar"}');
    });

    it('returns selector query from selector query with all labels if logging label list is empty', async () => {
      const datasourceWithLabels = makeMockLokiDatasource({});
      const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
      const result = await instance.importPrometheusQuery('metric{foo="bar",baz="42"}');
      expect(result).toEqual('{baz="42",foo="bar"}');
    });
  });
});
Example #24
Source File: LogsContainer.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
onChangeTime = (absoluteRange: AbsoluteTimeRange) => {
    const { exploreId, updateTimeRange } = this.props;
    updateTimeRange({ exploreId, absoluteRange });
  };
Example #25
Source File: useLokiSyntaxAndLabels.test.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
describe('useLokiSyntax hook', () => {
  const datasource = makeMockLokiDatasource({});
  const languageProvider = new LanguageProvider(datasource);
  const logLabelOptionsMock = ['Holy mock!'];
  const logLabelOptionsMock2 = ['Mock the hell?!'];
  const logLabelOptionsMock3 = ['Oh my mock!'];

  const rangeMock: AbsoluteTimeRange = {
    from: 1560153109000,
    to: 1560163909000,
  };

  languageProvider.refreshLogLabels = () => {
    languageProvider.logLabelOptions = logLabelOptionsMock;
    return Promise.resolve();
  };

  languageProvider.fetchLogLabels = () => {
    languageProvider.logLabelOptions = logLabelOptionsMock2;
    return Promise.resolve([]);
  };

  const activeOptionMock: CascaderOption = {
    label: '',
    value: '',
  };

  it('should provide Loki syntax when used', async () => {
    const { result, waitForNextUpdate } = renderHook(() => useLokiSyntaxAndLabels(languageProvider, rangeMock));
    expect(result.current.syntax).toEqual(null);

    await waitForNextUpdate();

    expect(result.current.syntax).toEqual(languageProvider.getSyntax());
  });

  it('should fetch labels on first call', async () => {
    const { result, waitForNextUpdate } = renderHook(() => useLokiSyntaxAndLabels(languageProvider, rangeMock));
    expect(result.current.isSyntaxReady).toBeFalsy();
    expect(result.current.logLabelOptions).toEqual([]);

    await waitForNextUpdate();

    expect(result.current.isSyntaxReady).toBeTruthy();
    expect(result.current.logLabelOptions).toEqual(logLabelOptionsMock2);
  });

  it('should try to fetch missing options when active option changes', async () => {
    const { result, waitForNextUpdate } = renderHook(() => useLokiSyntaxAndLabels(languageProvider, rangeMock));
    await waitForNextUpdate();
    expect(result.current.logLabelOptions).toEqual(logLabelOptionsMock2);

    languageProvider.fetchLabelValues = (key: string, absoluteRange: AbsoluteTimeRange) => {
      languageProvider.logLabelOptions = logLabelOptionsMock3;
      return Promise.resolve([]);
    };

    act(() => result.current.setActiveOption([activeOptionMock]));

    await waitForNextUpdate();

    expect(result.current.logLabelOptions).toEqual(logLabelOptionsMock3);
  });
});
Example #26
Source File: useLokiLabels.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
useLokiLabels = (
  languageProvider: LokiLanguageProvider,
  languageProviderInitialised: boolean,
  absoluteRange: AbsoluteTimeRange
) => {
  const mounted = useRefMounted();

  // State
  const [logLabelOptions, setLogLabelOptions] = useState([]);
  const [shouldTryRefreshLabels, setRefreshLabels] = useState(false);
  /**
   * Holds information about currently selected option from rc-cascader to perform effect
   * that loads option values not fetched yet. Based on that useLokiLabels hook decides whether or not
   * the option requires additional data fetching
   */
  const [activeOption, setActiveOption] = useState<CascaderOption[]>([]);

  // Async
  const fetchOptionValues = async (option: string) => {
    await languageProvider.fetchLabelValues(option, absoluteRange);
    if (mounted.current) {
      setLogLabelOptions(languageProvider.logLabelOptions);
    }
  };

  const tryLabelsRefresh = async () => {
    await languageProvider.refreshLogLabels(absoluteRange);

    if (mounted.current) {
      setRefreshLabels(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 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) {
      tryLabelsRefresh();
    }
  }, [shouldTryRefreshLabels]);

  // Initialize labels from the provider after it gets initialized (it's initialisation happens outside of this hook)
  useEffect(() => {
    if (languageProviderInitialised) {
      setLogLabelOptions(languageProvider.logLabelOptions);
    }
  }, [languageProviderInitialised]);

  return {
    logLabelOptions,
    refreshLabels: () => setRefreshLabels(true),
    setActiveOption,
  };
}
Example #27
Source File: language_provider.test.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
describe('Language completion provider', () => {
  const datasource = makeMockLokiDatasource({});

  const rangeMock: AbsoluteTimeRange = {
    from: 1560153109000,
    to: 1560163909000,
  };

  describe('query suggestions', () => {
    it('returns no suggestions on empty context', async () => {
      const instance = new LanguageProvider(datasource);
      const value = Plain.deserialize('');
      const result = await instance.provideCompletionItems({ text: '', prefix: '', value, wrapperClasses: [] });
      expect(result.context).toBeUndefined();

      expect(result.suggestions.length).toEqual(0);
    });

    it('returns history on empty context when history was provided', async () => {
      const instance = new LanguageProvider(datasource);
      const value = Plain.deserialize('');
      const history: LokiHistoryItem[] = [
        {
          query: { refId: '1', expr: '{app="foo"}' },
          ts: 1,
        },
      ];
      const result = await instance.provideCompletionItems(
        { text: '', prefix: '', value, wrapperClasses: [] },
        { history, absoluteRange: rangeMock }
      );
      expect(result.context).toBeUndefined();

      expect(result.suggestions).toMatchObject([
        {
          label: 'History',
          items: [
            {
              label: '{app="foo"}',
            },
          ],
        },
      ]);
    });

    it('returns function and history suggestions', async () => {
      const instance = new LanguageProvider(datasource);
      const input = createTypeaheadInput('m', 'm', undefined, 1, [], instance);
      // Historic expressions don't have to match input, filtering is done in field
      const history: LokiHistoryItem[] = [
        {
          query: { refId: '1', expr: '{app="foo"}' },
          ts: 1,
        },
      ];
      const result = await instance.provideCompletionItems(input, { history });
      expect(result.context).toBeUndefined();
      expect(result.suggestions.length).toEqual(2);
      expect(result.suggestions[0].label).toEqual('History');
      expect(result.suggestions[1].label).toEqual('Functions');
    });
  });

  describe('label key suggestions', () => {
    it('returns all label suggestions on empty selector', async () => {
      const datasource = makeMockLokiDatasource({ label1: [], label2: [] });
      const provider = await getLanguageProvider(datasource);
      const input = createTypeaheadInput('{}', '', '', 1);
      const result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock });
      expect(result.context).toBe('context-labels');
      expect(result.suggestions).toEqual([{ items: [{ label: 'label1' }, { label: 'label2' }], label: 'Labels' }]);
    });

    it('returns all label suggestions on selector when starting to type', async () => {
      const datasource = makeMockLokiDatasource({ label1: [], label2: [] });
      const provider = await getLanguageProvider(datasource);
      const input = createTypeaheadInput('{l}', '', '', 2);
      const result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock });
      expect(result.context).toBe('context-labels');
      expect(result.suggestions).toEqual([{ items: [{ label: 'label1' }, { label: 'label2' }], label: 'Labels' }]);
    });
  });

  describe('label suggestions facetted', () => {
    it('returns facetted label suggestions based on selector', async () => {
      const datasource = makeMockLokiDatasource(
        { label1: [], label2: [] },
        { '{foo="bar"}': [{ label1: 'label_val1' }] }
      );
      const provider = await getLanguageProvider(datasource);
      const input = createTypeaheadInput('{foo="bar",}', '', '', 11);
      const result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock });
      expect(result.context).toBe('context-labels');
      expect(result.suggestions).toEqual([{ items: [{ label: 'label1' }], label: 'Labels' }]);
    });

    it('returns facetted label suggestions for multipule selectors', async () => {
      const datasource = makeMockLokiDatasource(
        { label1: [], label2: [] },
        { '{baz="42",foo="bar"}': [{ label2: 'label_val2' }] }
      );
      const provider = await getLanguageProvider(datasource);
      const input = createTypeaheadInput('{baz="42",foo="bar",}', '', '', 20);
      const result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock });
      expect(result.context).toBe('context-labels');
      expect(result.suggestions).toEqual([{ items: [{ label: 'label2' }], label: 'Labels' }]);
    });
  });

  describe('label suggestions', () => {
    it('returns label values suggestions from Loki', async () => {
      const datasource = makeMockLokiDatasource({ label1: ['label1_val1', 'label1_val2'], label2: [] });
      const provider = await getLanguageProvider(datasource);
      const input = createTypeaheadInput('{label1=}', '=', 'label1');
      let result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock });

      result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock });
      expect(result.context).toBe('context-label-values');
      expect(result.suggestions).toEqual([
        { items: [{ label: 'label1_val1' }, { label: 'label1_val2' }], label: 'Label values for "label1"' },
      ]);
    });
  });
});
Example #28
Source File: time_region_manager.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
addFlotOptions(options: any, panel: any) {
    if (!panel.timeRegions || panel.timeRegions.length === 0) {
      return;
    }

    const tRange = {
      from: dateTime(this.panelCtrl.range.from).utc(),
      to: dateTime(this.panelCtrl.range.to).utc(),
    };

    let i: number,
      hRange: { from: any; to: any },
      timeRegion: any,
      regions: AbsoluteTimeRange[],
      fromStart: DateTime,
      fromEnd: DateTime,
      timeRegionColor: TimeRegionColorDefinition;

    const timeRegionsCopy = panel.timeRegions.map((a: any) => ({ ...a }));

    for (i = 0; i < timeRegionsCopy.length; i++) {
      timeRegion = timeRegionsCopy[i];

      if (!(timeRegion.fromDayOfWeek || timeRegion.from) && !(timeRegion.toDayOfWeek || timeRegion.to)) {
        continue;
      }

      if (timeRegion.from && !timeRegion.to) {
        timeRegion.to = timeRegion.from;
      }

      if (!timeRegion.from && timeRegion.to) {
        timeRegion.from = timeRegion.to;
      }

      hRange = {
        from: this.parseTimeRange(timeRegion.from),
        to: this.parseTimeRange(timeRegion.to),
      };

      if (!timeRegion.fromDayOfWeek && timeRegion.toDayOfWeek) {
        timeRegion.fromDayOfWeek = timeRegion.toDayOfWeek;
      }

      if (!timeRegion.toDayOfWeek && timeRegion.fromDayOfWeek) {
        timeRegion.toDayOfWeek = timeRegion.fromDayOfWeek;
      }

      if (timeRegion.fromDayOfWeek) {
        hRange.from.dayOfWeek = Number(timeRegion.fromDayOfWeek);
      }

      if (timeRegion.toDayOfWeek) {
        hRange.to.dayOfWeek = Number(timeRegion.toDayOfWeek);
      }

      if (hRange.from.dayOfWeek && hRange.from.h === null && hRange.from.m === null) {
        hRange.from.h = 0;
        hRange.from.m = 0;
        hRange.from.s = 0;
      }

      if (hRange.to.dayOfWeek && hRange.to.h === null && hRange.to.m === null) {
        hRange.to.h = 23;
        hRange.to.m = 59;
        hRange.to.s = 59;
      }

      if (!hRange.from || !hRange.to) {
        continue;
      }

      regions = [];

      fromStart = dateTime(tRange.from);
      fromStart.set('hour', 0);
      fromStart.set('minute', 0);
      fromStart.set('second', 0);
      fromStart.add(hRange.from.h, 'hours');
      fromStart.add(hRange.from.m, 'minutes');
      fromStart.add(hRange.from.s, 'seconds');

      while (fromStart.unix() <= tRange.to.unix()) {
        while (hRange.from.dayOfWeek && hRange.from.dayOfWeek !== fromStart.isoWeekday()) {
          fromStart.add(24, 'hours');
        }

        if (fromStart.unix() > tRange.to.unix()) {
          break;
        }

        fromEnd = dateTime(fromStart);

        if (hRange.from.h <= hRange.to.h) {
          fromEnd.add(hRange.to.h - hRange.from.h, 'hours');
        } else if (hRange.from.h > hRange.to.h) {
          while (fromEnd.hour() !== hRange.to.h) {
            fromEnd.add(1, 'hours');
          }
        } else {
          fromEnd.add(24 - hRange.from.h, 'hours');

          while (fromEnd.hour() !== hRange.to.h) {
            fromEnd.add(1, 'hours');
          }
        }

        fromEnd.set('minute', hRange.to.m);
        fromEnd.set('second', hRange.to.s);

        while (hRange.to.dayOfWeek && hRange.to.dayOfWeek !== fromEnd.isoWeekday()) {
          fromEnd.add(24, 'hours');
        }

        const outsideRange =
          (fromStart.unix() < tRange.from.unix() && fromEnd.unix() < tRange.from.unix()) ||
          (fromStart.unix() > tRange.to.unix() && fromEnd.unix() > tRange.to.unix());

        if (!outsideRange) {
          regions.push({ from: fromStart.valueOf(), to: fromEnd.valueOf() });
        }

        fromStart.add(24, 'hours');
      }

      timeRegionColor = getColor(timeRegion, this.theme);

      for (let j = 0; j < regions.length; j++) {
        const r = regions[j];
        if (timeRegion.fill) {
          options.grid.markings.push({
            xaxis: { from: r.from, to: r.to },
            color: timeRegionColor.fill,
          });
        }

        if (timeRegion.line) {
          options.grid.markings.push({
            xaxis: { from: r.from, to: r.from },
            color: timeRegionColor.line,
          });
          options.grid.markings.push({
            xaxis: { from: r.to, to: r.to },
            color: timeRegionColor.line,
          });
        }
      }
    }
  }