PromSettings.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import React, { SyntheticEvent } from 'react';
  2. import {
  3. DataSourcePluginOptionsEditorProps,
  4. onUpdateDatasourceJsonDataOptionChecked,
  5. SelectableValue,
  6. updateDatasourcePluginJsonDataOption,
  7. } from '@grafana/data';
  8. import {
  9. InlineField,
  10. InlineSwitch,
  11. EventsWithValidation,
  12. InlineFormLabel,
  13. LegacyForms,
  14. regexValidation,
  15. } from '@grafana/ui';
  16. import { PromOptions } from '../types';
  17. import { ExemplarsSettings } from './ExemplarsSettings';
  18. const { Select, Input, FormField } = LegacyForms;
  19. const httpOptions = [
  20. { value: 'POST', label: 'POST' },
  21. { value: 'GET', label: 'GET' },
  22. ];
  23. type Props = Pick<DataSourcePluginOptionsEditorProps<PromOptions>, 'options' | 'onOptionsChange'>;
  24. export const PromSettings = (props: Props) => {
  25. const { options, onOptionsChange } = props;
  26. // We are explicitly adding httpMethod so it is correctly displayed in dropdown. This way, it is more predictable for users.
  27. if (!options.jsonData.httpMethod) {
  28. options.jsonData.httpMethod = 'POST';
  29. }
  30. return (
  31. <>
  32. <div className="gf-form-group">
  33. <div className="gf-form-inline">
  34. <div className="gf-form">
  35. <FormField
  36. label="Scrape interval"
  37. labelWidth={13}
  38. inputEl={
  39. <Input
  40. className="width-6"
  41. value={options.jsonData.timeInterval}
  42. spellCheck={false}
  43. placeholder="15s"
  44. onChange={onChangeHandler('timeInterval', options, onOptionsChange)}
  45. validationEvents={promSettingsValidationEvents}
  46. />
  47. }
  48. tooltip="Set this to the typical scrape and evaluation interval configured in Prometheus. Defaults to 15s."
  49. />
  50. </div>
  51. </div>
  52. <div className="gf-form-inline">
  53. <div className="gf-form">
  54. <FormField
  55. label="Query timeout"
  56. labelWidth={13}
  57. inputEl={
  58. <Input
  59. className="width-6"
  60. value={options.jsonData.queryTimeout}
  61. onChange={onChangeHandler('queryTimeout', options, onOptionsChange)}
  62. spellCheck={false}
  63. placeholder="60s"
  64. validationEvents={promSettingsValidationEvents}
  65. />
  66. }
  67. tooltip="Set the Prometheus query timeout."
  68. />
  69. </div>
  70. </div>
  71. <div className="gf-form">
  72. <InlineFormLabel
  73. width={13}
  74. tooltip="You can use either POST or GET HTTP method to query your Prometheus data source. POST is the recommended method as it allows bigger queries. Change this to GET if you have a Prometheus version older than 2.1 or if POST requests are restricted in your network."
  75. >
  76. HTTP Method
  77. </InlineFormLabel>
  78. <Select
  79. aria-label="Select HTTP method"
  80. options={httpOptions}
  81. value={httpOptions.find((o) => o.value === options.jsonData.httpMethod)}
  82. onChange={onChangeHandler('httpMethod', options, onOptionsChange)}
  83. width={7}
  84. />
  85. </div>
  86. </div>
  87. <h3 className="page-heading">Misc</h3>
  88. <div className="gf-form-group">
  89. <div className="gf-form">
  90. <InlineField
  91. labelWidth={28}
  92. label="Disable metrics lookup"
  93. tooltip="Checking this option will disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with bigger Prometheus instances."
  94. >
  95. <InlineSwitch
  96. value={options.jsonData.disableMetricsLookup ?? false}
  97. onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'disableMetricsLookup')}
  98. />
  99. </InlineField>
  100. </div>
  101. <div className="gf-form-inline">
  102. <div className="gf-form max-width-30">
  103. <FormField
  104. label="Custom query parameters"
  105. labelWidth={14}
  106. tooltip="Add Custom parameters to all Prometheus or Thanos queries."
  107. inputEl={
  108. <Input
  109. className="width-25"
  110. value={options.jsonData.customQueryParameters}
  111. onChange={onChangeHandler('customQueryParameters', options, onOptionsChange)}
  112. spellCheck={false}
  113. placeholder="Example: max_source_resolution=5m&timeout=10"
  114. />
  115. }
  116. />
  117. </div>
  118. </div>
  119. </div>
  120. <ExemplarsSettings
  121. options={options.jsonData.exemplarTraceIdDestinations}
  122. onChange={(exemplarOptions) =>
  123. updateDatasourcePluginJsonDataOption(
  124. { onOptionsChange, options },
  125. 'exemplarTraceIdDestinations',
  126. exemplarOptions
  127. )
  128. }
  129. />
  130. </>
  131. );
  132. };
  133. export const promSettingsValidationEvents = {
  134. [EventsWithValidation.onBlur]: [
  135. regexValidation(
  136. /^$|^\d+(ms|[Mwdhmsy])$/,
  137. 'Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s'
  138. ),
  139. ],
  140. };
  141. export const getValueFromEventItem = (eventItem: SyntheticEvent<HTMLInputElement> | SelectableValue<string>) => {
  142. if (!eventItem) {
  143. return '';
  144. }
  145. if (eventItem.hasOwnProperty('currentTarget')) {
  146. return eventItem.currentTarget.value;
  147. }
  148. return (eventItem as SelectableValue<string>).value;
  149. };
  150. const onChangeHandler =
  151. (key: keyof PromOptions, options: Props['options'], onOptionsChange: Props['onOptionsChange']) =>
  152. (eventItem: SyntheticEvent<HTMLInputElement> | SelectableValue<string>) => {
  153. onOptionsChange({
  154. ...options,
  155. jsonData: {
  156. ...options.jsonData,
  157. [key]: getValueFromEventItem(eventItem),
  158. },
  159. });
  160. };