PromQueryBuilderOptions.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import React, { SyntheticEvent } from 'react';
  2. import { CoreApp, SelectableValue } from '@grafana/data';
  3. import { EditorRow, EditorField, EditorSwitch } from '@grafana/experimental';
  4. import { RadioButtonGroup, Select } from '@grafana/ui';
  5. import { getQueryTypeChangeHandler, getQueryTypeOptions } from '../../components/PromExploreExtraField';
  6. import { FORMAT_OPTIONS, INTERVAL_FACTOR_OPTIONS } from '../../components/PromQueryEditor';
  7. import { PromQuery } from '../../types';
  8. import { AutoSizeInput } from '../shared/AutoSizeInput';
  9. import { QueryOptionGroup } from '../shared/QueryOptionGroup';
  10. import { getLegendModeLabel, PromQueryLegendEditor } from './PromQueryLegendEditor';
  11. export interface UIOptions {
  12. exemplars: boolean;
  13. type: boolean;
  14. format: boolean;
  15. minStep: boolean;
  16. legend: boolean;
  17. resolution: boolean;
  18. }
  19. export interface Props {
  20. query: PromQuery;
  21. app?: CoreApp;
  22. onChange: (update: PromQuery) => void;
  23. onRunQuery: () => void;
  24. }
  25. export const PromQueryBuilderOptions = React.memo<Props>(({ query, app, onChange, onRunQuery }) => {
  26. const onChangeFormat = (value: SelectableValue<string>) => {
  27. onChange({ ...query, format: value.value });
  28. onRunQuery();
  29. };
  30. const onChangeStep = (evt: React.FormEvent<HTMLInputElement>) => {
  31. onChange({ ...query, interval: evt.currentTarget.value });
  32. onRunQuery();
  33. };
  34. const queryTypeOptions = getQueryTypeOptions(app === CoreApp.Explore);
  35. const onQueryTypeChange = getQueryTypeChangeHandler(query, onChange);
  36. const onExemplarChange = (event: SyntheticEvent<HTMLInputElement>) => {
  37. const isEnabled = event.currentTarget.checked;
  38. onChange({ ...query, exemplar: isEnabled });
  39. onRunQuery();
  40. };
  41. const onIntervalFactorChange = (value: SelectableValue<number>) => {
  42. onChange({ ...query, intervalFactor: value.value });
  43. onRunQuery();
  44. };
  45. const formatOption = FORMAT_OPTIONS.find((option) => option.value === query.format) || FORMAT_OPTIONS[0];
  46. const queryTypeValue = getQueryTypeValue(query);
  47. const queryTypeLabel = queryTypeOptions.find((x) => x.value === queryTypeValue)!.label;
  48. return (
  49. <EditorRow>
  50. <QueryOptionGroup title="Options" collapsedInfo={getCollapsedInfo(query, formatOption.label!, queryTypeLabel)}>
  51. <PromQueryLegendEditor
  52. legendFormat={query.legendFormat}
  53. onChange={(legendFormat) => onChange({ ...query, legendFormat })}
  54. onRunQuery={onRunQuery}
  55. />
  56. <EditorField
  57. label="Min step"
  58. tooltip={
  59. <>
  60. An additional lower limit for the step parameter of the Prometheus query and for the{' '}
  61. <code>$__interval</code> and <code>$__rate_interval</code> variables.
  62. </>
  63. }
  64. >
  65. <AutoSizeInput
  66. type="text"
  67. aria-label="Set lower limit for the step parameter"
  68. placeholder={'auto'}
  69. minWidth={10}
  70. onCommitChange={onChangeStep}
  71. defaultValue={query.interval}
  72. />
  73. </EditorField>
  74. <EditorField label="Format">
  75. <Select value={formatOption} allowCustomValue onChange={onChangeFormat} options={FORMAT_OPTIONS} />
  76. </EditorField>
  77. <EditorField label="Type">
  78. <RadioButtonGroup options={queryTypeOptions} value={queryTypeValue} onChange={onQueryTypeChange} />
  79. </EditorField>
  80. {shouldShowExemplarSwitch(query, app) && (
  81. <EditorField label="Exemplars">
  82. <EditorSwitch value={query.exemplar} onChange={onExemplarChange} />
  83. </EditorField>
  84. )}
  85. {query.intervalFactor && query.intervalFactor > 1 && (
  86. <EditorField label="Resolution">
  87. <Select
  88. aria-label="Select resolution"
  89. isSearchable={false}
  90. options={INTERVAL_FACTOR_OPTIONS}
  91. onChange={onIntervalFactorChange}
  92. value={INTERVAL_FACTOR_OPTIONS.find((option) => option.value === query.intervalFactor)}
  93. />
  94. </EditorField>
  95. )}
  96. </QueryOptionGroup>
  97. </EditorRow>
  98. );
  99. });
  100. function shouldShowExemplarSwitch(query: PromQuery, app?: CoreApp) {
  101. if (app === CoreApp.UnifiedAlerting || !query.range) {
  102. return false;
  103. }
  104. return true;
  105. }
  106. function getQueryTypeValue(query: PromQuery) {
  107. return query.range && query.instant ? 'both' : query.instant ? 'instant' : 'range';
  108. }
  109. function getCollapsedInfo(query: PromQuery, formatOption: string, queryType: string): string[] {
  110. const items: string[] = [];
  111. items.push(`Legend: ${getLegendModeLabel(query.legendFormat)}`);
  112. items.push(`Format: ${formatOption}`);
  113. items.push(`Step: ${query.interval ?? 'auto'}`);
  114. items.push(`Type: ${queryType}`);
  115. if (query.exemplar) {
  116. items.push(`Exemplars: true`);
  117. }
  118. return items;
  119. }
  120. PromQueryBuilderOptions.displayName = 'PromQueryBuilderOptions';