@perses-dev/prometheus-plugin 0.56.0 → 0.57.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mf/js/Prometheus.2bb892ab.js +6 -0
- package/__mf/js/async/1233.0ab88b51.js +1 -0
- package/__mf/js/async/1324.ce01eced.js +1 -0
- package/__mf/js/async/1432.0c3e4ed0.js +1 -0
- package/__mf/js/async/1490.7e5068f1.js +22 -0
- package/__mf/js/async/1605.dc180cb8.js +110 -0
- package/__mf/js/async/1616.7587ce79.js +1 -0
- package/__mf/js/async/1728.af16c4ec.js +1 -0
- package/__mf/js/async/1969.372d36b8.js +1 -0
- package/__mf/js/async/2043.d0fbb886.js +2 -0
- package/__mf/js/async/2186.e58838a5.js +38 -0
- package/__mf/js/async/2506.1e336b3b.js +1 -0
- package/__mf/js/async/2984.7182c2f5.js +1 -0
- package/__mf/js/async/2999.1d8347df.js +1 -0
- package/__mf/js/async/3184.6b4ad42e.js +1 -0
- package/__mf/js/async/3664.ba8b26b6.js +2 -0
- package/__mf/js/async/392.7cda691a.js +2 -0
- package/__mf/js/async/3963.5fef6ffb.js +1 -0
- package/__mf/js/async/3996.69a9c1dc.js +1 -0
- package/__mf/js/async/{1964.1d168a86.js → 4121.828d661d.js} +2 -2
- package/__mf/js/async/4626.173e602a.js +1 -0
- package/__mf/js/async/4987.c12b89cb.js +1 -0
- package/__mf/js/async/{8930.700a5439.js → 5002.e4f54e8e.js} +1 -1
- package/__mf/js/async/5071.e1c33fa7.js +1 -0
- package/__mf/js/async/529.2303b01b.js +1 -0
- package/__mf/js/async/5440.c13c3533.js +2 -0
- package/__mf/js/async/5501.6166367c.js +2 -0
- package/__mf/js/async/{5214.0fca84ed.js → 5587.4d72fc35.js} +1 -1
- package/__mf/js/async/5763.4ba478ff.js +1 -0
- package/__mf/js/async/5922.d1619ac1.js +1 -0
- package/__mf/js/async/6149.19799c37.js +7 -0
- package/__mf/js/async/6274.478a68f8.js +2 -0
- package/__mf/js/async/6283.181cb622.js +2 -0
- package/__mf/js/async/6969.b959b6f8.js +1 -0
- package/__mf/js/async/{4062.06f48b93.js → 7177.205c9aaf.js} +1 -1
- package/__mf/js/async/7192.d835931b.js +1 -0
- package/__mf/js/async/7894.9c5245d7.js +1 -0
- package/__mf/js/async/7968.6ac0ce96.js +1 -0
- package/__mf/js/async/7978.9532d5b8.js +1 -0
- package/__mf/js/async/8356.789e1dfb.js +1 -0
- package/__mf/js/async/8470.9b14a625.js +2 -0
- package/__mf/js/async/873.448eab23.js +1 -0
- package/__mf/js/async/8888.59eb50a2.js +1 -0
- package/__mf/js/async/9020.c19782f1.js +1 -0
- package/__mf/js/async/9184.43a8d927.js +1 -0
- package/__mf/js/async/9235.36c3cd8c.js +1 -0
- package/__mf/js/async/9351.715f25c3.js +1 -0
- package/__mf/js/async/941.53b13124.js +2 -0
- package/__mf/js/async/9518.38e38a33.js +1 -0
- package/__mf/js/async/9588.9081c7de.js +1 -0
- package/__mf/js/async/9605.a92ec9c1.js +1 -0
- package/__mf/js/async/9836.00da6086.js +1 -0
- package/__mf/js/async/__federation_expose_PrometheusDatasource.6f63e147.js +1 -0
- package/__mf/js/async/__federation_expose_PrometheusExplorer.584a073d.js +1 -0
- package/__mf/js/async/__federation_expose_PrometheusLabelNamesVariable.40984a4d.js +1 -0
- package/__mf/js/async/__federation_expose_PrometheusLabelValuesVariable.bd3eb00c.js +1 -0
- package/__mf/js/async/__federation_expose_PrometheusPromQLVariable.5cca8417.js +1 -0
- package/__mf/js/async/__federation_expose_PrometheusTimeSeriesQuery.f59141f4.js +1 -0
- package/__mf/js/main.9617b605.js +6 -0
- package/lib/bootstrap.js +1 -1
- package/lib/bootstrap.js.map +1 -1
- package/lib/cjs/components/PromQLEditor.js +4 -7
- package/lib/cjs/components/promql/ast.js +10 -10
- package/lib/cjs/components/promql/format.js +3 -3
- package/lib/cjs/components/promql/utils.js +5 -5
- package/lib/cjs/components/query.js +3 -3
- package/lib/cjs/explore/PrometheusExplorer.js +10 -6
- package/lib/cjs/explore/PrometheusMetricsFinder/PrometheusMetricsFinder.js +4 -4
- package/lib/cjs/explore/PrometheusMetricsFinder/display/list/MetricList.js +3 -3
- package/lib/cjs/explore/PrometheusMetricsFinder/filter/FilterInputs.js +4 -4
- package/lib/cjs/explore/PrometheusMetricsFinder/overview/MetricOverview.js +3 -3
- package/lib/cjs/explore/PrometheusMetricsFinder/overview/tabs/JobTab.js +4 -4
- package/lib/cjs/explore/PrometheusMetricsFinder/overview/tabs/OverviewTab.js +4 -4
- package/lib/cjs/explore/PrometheusMetricsFinder/utils.js +5 -5
- package/lib/cjs/index-federation.js +12 -12
- package/lib/cjs/model/parse-sample-values.js +3 -3
- package/lib/cjs/model/prometheus-client.js +29 -19
- package/lib/cjs/model/prometheus-selectors.js +5 -5
- package/lib/cjs/model/time.js +4 -4
- package/lib/cjs/plugins/PrometheusDatasourceEditor.js +175 -2
- package/lib/cjs/plugins/prometheus-datasource.js +17 -9
- package/lib/cjs/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.js +36 -1
- package/lib/cjs/plugins/prometheus-time-series-query/query-editor-model.js +4 -4
- package/lib/cjs/plugins/prometheus-variables.js +52 -33
- package/lib/cjs/utils/utils.js +4 -4
- package/lib/components/PromQLEditor.d.ts +5 -1
- package/lib/components/PromQLEditor.d.ts.map +1 -1
- package/lib/components/PromQLEditor.js +5 -8
- package/lib/components/PromQLEditor.js.map +1 -1
- package/lib/components/TreeNode.js +1 -1
- package/lib/components/TreeNode.js.map +1 -1
- package/lib/components/promql/format.js +1 -1
- package/lib/components/promql/format.js.map +1 -1
- package/lib/explore/PrometheusExplorer.d.ts.map +1 -1
- package/lib/explore/PrometheusExplorer.js +10 -6
- package/lib/explore/PrometheusExplorer.js.map +1 -1
- package/lib/explore/PrometheusMetricsFinder/PrometheusMetricsFinder.js +1 -1
- package/lib/explore/PrometheusMetricsFinder/PrometheusMetricsFinder.js.map +1 -1
- package/lib/explore/PrometheusMetricsFinder/display/MetricChip.js +1 -1
- package/lib/explore/PrometheusMetricsFinder/display/MetricChip.js.map +1 -1
- package/lib/explore/PrometheusMetricsFinder/display/list/MetricList.js +1 -1
- package/lib/explore/PrometheusMetricsFinder/display/list/MetricList.js.map +1 -1
- package/lib/explore/PrometheusMetricsFinder/filter/FilterInputs.js +1 -1
- package/lib/explore/PrometheusMetricsFinder/filter/FilterInputs.js.map +1 -1
- package/lib/explore/PrometheusMetricsFinder/filter/FinderFilters.js +1 -1
- package/lib/explore/PrometheusMetricsFinder/filter/FinderFilters.js.map +1 -1
- package/lib/explore/PrometheusMetricsFinder/overview/MetricOverview.js +1 -1
- package/lib/explore/PrometheusMetricsFinder/overview/MetricOverview.js.map +1 -1
- package/lib/model/prometheus-client.d.ts +1 -0
- package/lib/model/prometheus-client.d.ts.map +1 -1
- package/lib/model/prometheus-client.js +19 -9
- package/lib/model/prometheus-client.js.map +1 -1
- package/lib/plugins/MatcherEditor.js +1 -1
- package/lib/plugins/MatcherEditor.js.map +1 -1
- package/lib/plugins/PrometheusDatasourceEditor.d.ts.map +1 -1
- package/lib/plugins/PrometheusDatasourceEditor.js +135 -3
- package/lib/plugins/PrometheusDatasourceEditor.js.map +1 -1
- package/lib/plugins/prometheus-datasource.js +17 -9
- package/lib/plugins/prometheus-datasource.js.map +1 -1
- package/lib/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.d.ts.map +1 -1
- package/lib/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.js +39 -4
- package/lib/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.js.map +1 -1
- package/lib/plugins/prometheus-time-series-query/get-time-series-data.d.ts.map +1 -1
- package/lib/plugins/prometheus-time-series-query/get-time-series-data.js.map +1 -1
- package/lib/plugins/prometheus-variables.d.ts.map +1 -1
- package/lib/plugins/prometheus-variables.js +47 -28
- package/lib/plugins/prometheus-variables.js.map +1 -1
- package/lib/plugins/types.d.ts +1 -0
- package/lib/plugins/types.d.ts.map +1 -1
- package/lib/plugins/types.js.map +1 -1
- package/mf-manifest.json +268 -253
- package/mf-stats.json +271 -254
- package/package.json +7 -7
- package/__mf/js/Prometheus.4d0d5812.js +0 -5
- package/__mf/js/async/1339.194207db.js +0 -1
- package/__mf/js/async/1441.c735f7dd.js +0 -1
- package/__mf/js/async/1576.8eac7ce9.js +0 -1
- package/__mf/js/async/212.5fcca998.js +0 -1
- package/__mf/js/async/2292.57d8fd0d.js +0 -2
- package/__mf/js/async/3224.b63f87bf.js +0 -1
- package/__mf/js/async/3507.f1653337.js +0 -101
- package/__mf/js/async/3749.3ecd9372.js +0 -1
- package/__mf/js/async/3863.7192dfdf.js +0 -2
- package/__mf/js/async/3960.3eedafbd.js +0 -2
- package/__mf/js/async/3980.0b0d272c.js +0 -2
- package/__mf/js/async/4075.dab1b7b8.js +0 -1
- package/__mf/js/async/4238.c48b1950.js +0 -1
- package/__mf/js/async/4421.1fcb466e.js +0 -1
- package/__mf/js/async/4535.f24704ea.js +0 -1
- package/__mf/js/async/4557.f3eb9456.js +0 -2
- package/__mf/js/async/4576.f42daf99.js +0 -1
- package/__mf/js/async/4665.cad36935.js +0 -1
- package/__mf/js/async/4676.b7a22f90.js +0 -22
- package/__mf/js/async/5257.ce463cb7.js +0 -1
- package/__mf/js/async/5409.955ffd51.js +0 -1
- package/__mf/js/async/5614.cce8ba96.js +0 -1
- package/__mf/js/async/5724.794828e3.js +0 -1
- package/__mf/js/async/5774.a3fae698.js +0 -1
- package/__mf/js/async/5790.a9b31ca8.js +0 -1
- package/__mf/js/async/58.1c9a8daa.js +0 -2
- package/__mf/js/async/5981.eb502d27.js +0 -2
- package/__mf/js/async/6292.2afe0c6d.js +0 -1
- package/__mf/js/async/6341.20eccf91.js +0 -7
- package/__mf/js/async/6377.c40920f2.js +0 -2
- package/__mf/js/async/6770.7099bb3b.js +0 -1
- package/__mf/js/async/684.4495f632.js +0 -1
- package/__mf/js/async/694.8462a746.js +0 -1
- package/__mf/js/async/7272.6fa2f127.js +0 -1
- package/__mf/js/async/7376.2e948f2b.js +0 -1
- package/__mf/js/async/738.a1ffff79.js +0 -1
- package/__mf/js/async/7740.a8777825.js +0 -1
- package/__mf/js/async/8045.7f554a45.js +0 -10
- package/__mf/js/async/8164.bb3d3363.js +0 -1
- package/__mf/js/async/8216.e689c178.js +0 -1
- package/__mf/js/async/8488.cbbe542b.js +0 -1
- package/__mf/js/async/8587.40df6f5c.js +0 -1
- package/__mf/js/async/8706.89677575.js +0 -1
- package/__mf/js/async/9010.bdb2ef97.js +0 -1
- package/__mf/js/async/9173.915b80af.js +0 -2
- package/__mf/js/async/9550.642ce5ad.js +0 -38
- package/__mf/js/async/9817.70eae424.js +0 -1
- package/__mf/js/async/__federation_expose_PrometheusDatasource.45ee94e2.js +0 -1
- package/__mf/js/async/__federation_expose_PrometheusExplorer.b8e555e1.js +0 -1
- package/__mf/js/async/__federation_expose_PrometheusLabelNamesVariable.00dfb1dd.js +0 -1
- package/__mf/js/async/__federation_expose_PrometheusLabelValuesVariable.956ef2d0.js +0 -1
- package/__mf/js/async/__federation_expose_PrometheusPromQLVariable.59f2d170.js +0 -1
- package/__mf/js/async/__federation_expose_PrometheusTimeSeriesQuery.d7143352.js +0 -1
- package/__mf/js/main.afc2ee60.js +0 -5
- /package/__mf/css/async/{1339.d3010b86.css → 1233.d3010b86.css} +0 -0
- /package/__mf/css/async/{1576.d3010b86.css → 1324.d3010b86.css} +0 -0
- /package/__mf/css/async/{4576.d3010b86.css → 9518.d3010b86.css} +0 -0
- /package/__mf/js/async/{4676.b7a22f90.js.LICENSE.txt → 1490.7e5068f1.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{8045.7f554a45.js.LICENSE.txt → 1605.dc180cb8.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{2292.57d8fd0d.js.LICENSE.txt → 2043.d0fbb886.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{58.1c9a8daa.js.LICENSE.txt → 3664.ba8b26b6.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{5981.eb502d27.js.LICENSE.txt → 392.7cda691a.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{1964.1d168a86.js.LICENSE.txt → 4121.828d661d.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{6377.c40920f2.js.LICENSE.txt → 5440.c13c3533.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{4557.f3eb9456.js.LICENSE.txt → 5501.6166367c.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{6341.20eccf91.js.LICENSE.txt → 6149.19799c37.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3960.3eedafbd.js.LICENSE.txt → 6274.478a68f8.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3980.0b0d272c.js.LICENSE.txt → 6283.181cb622.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{9173.915b80af.js.LICENSE.txt → 8470.9b14a625.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3863.7192dfdf.js.LICENSE.txt → 941.53b13124.js.LICENSE.txt} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/model/prometheus-client.ts"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { fetch, fetchJson, RequestHeaders } from '@perses-dev/core';\nimport { DatasourceClient } from '@perses-dev/plugin-system';\nimport {\n InstantQueryRequestParameters,\n InstantQueryResponse,\n LabelNamesRequestParameters,\n LabelNamesResponse,\n LabelValuesRequestParameters,\n LabelValuesResponse,\n MetricMetadataRequestParameters,\n MetricMetadataResponse,\n ParseQueryRequestParameters,\n ParseQueryResponse,\n RangeQueryRequestParameters,\n RangeQueryResponse,\n SeriesRequestParameters,\n SeriesResponse,\n SuccessResponse,\n} from './api-types';\n\ninterface PrometheusClientOptions {\n datasourceUrl: string;\n headers?: RequestHeaders;\n}\n\nexport interface PrometheusClient extends DatasourceClient {\n options: PrometheusClientOptions;\n instantQuery(\n params: InstantQueryRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<InstantQueryResponse>;\n rangeQuery(\n params: RangeQueryRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<RangeQueryResponse>;\n labelNames(\n params: LabelNamesRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<LabelNamesResponse>;\n labelValues(\n params: LabelValuesRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<LabelValuesResponse>;\n metricMetadata(\n params: MetricMetadataRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<MetricMetadataResponse>;\n series(params: SeriesRequestParameters, headers?: RequestHeaders, signal?: AbortSignal): Promise<SeriesResponse>;\n parseQuery(\n params: ParseQueryRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<ParseQueryResponse>;\n}\n\nexport interface QueryOptions {\n datasourceUrl: string;\n headers?: RequestHeaders;\n abortSignal?: AbortSignal;\n}\n\n/**\n * Calls the `/-/healthy` endpoint to check if the datasource is healthy.\n */\nexport function healthCheck(queryOptions: QueryOptions) {\n return async (): Promise<boolean> => {\n const url = `${queryOptions.datasourceUrl}/-/healthy`;\n\n try {\n const resp = await fetch(url, { headers: queryOptions.headers, signal: queryOptions.abortSignal });\n return resp.status === 200;\n } catch {\n return false;\n }\n };\n}\n\n/**\n * Calls the `/api/v1/query` endpoint to get metrics data.\n */\nexport function instantQuery(\n params: InstantQueryRequestParameters,\n queryOptions: QueryOptions\n): Promise<InstantQueryResponse> {\n return fetchWithPost<InstantQueryRequestParameters, InstantQueryResponse>('/api/v1/query', params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/query_range` endpoint to get metrics data.\n */\nexport function rangeQuery(\n params: RangeQueryRequestParameters,\n queryOptions: QueryOptions\n): Promise<RangeQueryResponse> {\n return fetchWithPost<RangeQueryRequestParameters, RangeQueryResponse>('/api/v1/query_range', params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/labels` endpoint to get a list of label names.\n */\nexport function labelNames(\n params: LabelNamesRequestParameters,\n queryOptions: QueryOptions\n): Promise<LabelNamesResponse> {\n return fetchWithPost<LabelNamesRequestParameters, LabelNamesResponse>('/api/v1/labels', params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/label/{labelName}/values` endpoint to get a list of values for a label.\n */\nexport function labelValues(\n params: LabelValuesRequestParameters,\n queryOptions: QueryOptions\n): Promise<LabelValuesResponse> {\n const { labelName, ...searchParams } = params;\n\n // In case label name is empty, we'll receive a 404, so we can replace it by an empty list, which is less confusing.\n // Note that an empty list is the prometheus result if the label does not exist.\n if (labelName.length === 0) {\n return new Promise((resolve) => {\n resolve({ data: [] as string[] } as SuccessResponse<string[]>);\n });\n }\n\n const apiURI = `/api/v1/label/${encodeURIComponent(labelName)}/values`;\n return fetchWithGet<typeof searchParams, LabelValuesResponse>(apiURI, searchParams, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/label/{labelName}/values` endpoint to get a list of values for a label.\n */\nexport function metricMetadata(\n params: MetricMetadataRequestParameters,\n queryOptions: QueryOptions\n): Promise<MetricMetadataResponse> {\n const apiURI = `/api/v1/metadata`;\n return fetchWithGet<MetricMetadataRequestParameters, MetricMetadataResponse>(apiURI, params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/series` endpoint to finding series by label matchers.\n */\nexport function series(params: SeriesRequestParameters, queryOptions: QueryOptions): Promise<SeriesResponse> {\n const apiURI = `/api/v1/series`;\n return fetchWithPost<SeriesRequestParameters, SeriesResponse>(apiURI, params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/parse_query` to parse the given promQL expresion into an abstract syntax tree (AST).\n */\nexport function parseQuery(\n params: ParseQueryRequestParameters,\n queryOptions: QueryOptions\n): Promise<ParseQueryResponse> {\n const apiURI = `/api/v1/parse_query`;\n return fetchWithPost<ParseQueryRequestParameters, ParseQueryResponse>(apiURI, params, queryOptions);\n}\n\nfunction fetchWithGet<T extends RequestParams<T>, TResponse>(\n apiURI: string,\n params: T,\n queryOptions: QueryOptions\n): Promise<TResponse> {\n const { datasourceUrl, headers } = queryOptions;\n let url = `${datasourceUrl}${apiURI}`;\n const urlParams = createSearchParams(params).toString();\n if (urlParams !== '') {\n url += `?${urlParams}`;\n }\n return fetchJson<TResponse>(url, { method: 'GET', headers });\n}\n\nfunction fetchWithPost<T extends RequestParams<T>, TResponse>(\n apiURI: string,\n params: T,\n queryOptions: QueryOptions\n): Promise<TResponse> {\n const { datasourceUrl, headers, abortSignal: signal } = queryOptions;\n const url = `${datasourceUrl}${apiURI}`;\n const init = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n ...headers,\n },\n signal,\n body: createSearchParams(params),\n };\n return fetchResults<TResponse>(url, init);\n}\n\n// Request parameter values we know how to serialize\ntype ParamValue = string | string[] | number | undefined;\n\n// Used to constrain the types that can be passed to createSearchParams to\n// just the ones we know how to serialize\ntype RequestParams<T> = {\n [K in keyof T]: ParamValue;\n};\n\n/**\n * Creates URLSearchParams from a request params object.\n */\nfunction createSearchParams<T extends RequestParams<T>>(params: T): URLSearchParams {\n const searchParams = new URLSearchParams();\n for (const key in params) {\n const value: ParamValue = params[key];\n if (value === undefined) continue;\n\n if (typeof value === 'string') {\n searchParams.append(key, value);\n continue;\n }\n\n if (typeof value === 'number') {\n searchParams.append(key, value.toString());\n continue;\n }\n\n for (const val of value) {\n searchParams.append(key, val);\n }\n }\n return searchParams;\n}\n\n/**\n * Fetch JSON and parse warnings for query inspector\n */\nexport async function fetchResults<T>(...args: Parameters<typeof global.fetch>): Promise<T> {\n const response = await fetch(...args);\n const json: T = await response.json();\n return { ...json, rawResponse: response };\n}\n"],"names":["fetch","fetchJson","healthCheck","queryOptions","url","datasourceUrl","resp","headers","signal","abortSignal","status","instantQuery","params","fetchWithPost","rangeQuery","labelNames","labelValues","labelName","searchParams","length","Promise","resolve","data","apiURI","encodeURIComponent","fetchWithGet","metricMetadata","series","parseQuery","urlParams","createSearchParams","toString","method","init","body","fetchResults","URLSearchParams","key","value","undefined","append","val","args","response","json","rawResponse"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/model/prometheus-client.ts"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { fetch, fetchJson, RequestHeaders } from '@perses-dev/core';\nimport { DatasourceClient } from '@perses-dev/plugin-system';\nimport {\n InstantQueryRequestParameters,\n InstantQueryResponse,\n LabelNamesRequestParameters,\n LabelNamesResponse,\n LabelValuesRequestParameters,\n LabelValuesResponse,\n MetricMetadataRequestParameters,\n MetricMetadataResponse,\n ParseQueryRequestParameters,\n ParseQueryResponse,\n RangeQueryRequestParameters,\n RangeQueryResponse,\n SeriesRequestParameters,\n SeriesResponse,\n SuccessResponse,\n} from './api-types';\n\ninterface PrometheusClientOptions {\n datasourceUrl: string;\n headers?: RequestHeaders;\n}\n\nexport interface PrometheusClient extends DatasourceClient {\n options: PrometheusClientOptions;\n instantQuery(\n params: InstantQueryRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<InstantQueryResponse>;\n rangeQuery(\n params: RangeQueryRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<RangeQueryResponse>;\n labelNames(\n params: LabelNamesRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<LabelNamesResponse>;\n labelValues(\n params: LabelValuesRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<LabelValuesResponse>;\n metricMetadata(\n params: MetricMetadataRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<MetricMetadataResponse>;\n series(params: SeriesRequestParameters, headers?: RequestHeaders, signal?: AbortSignal): Promise<SeriesResponse>;\n parseQuery(\n params: ParseQueryRequestParameters,\n headers?: RequestHeaders,\n signal?: AbortSignal\n ): Promise<ParseQueryResponse>;\n}\n\nexport interface QueryOptions {\n datasourceUrl: string;\n headers?: RequestHeaders;\n abortSignal?: AbortSignal;\n queryParams?: Record<string, string>;\n}\n\n/**\n * Builds a query string from datasource-level query parameters.\n * Optionally merges with existing URLSearchParams.\n * Returns empty string if no parameters, otherwise returns query string with leading '?'.\n */\nfunction buildQueryString(queryParams?: Record<string, string>, initialParams?: URLSearchParams): string {\n const urlParams = initialParams || new URLSearchParams();\n\n if (queryParams) {\n Object.entries(queryParams).forEach(([key, value]) => {\n urlParams.set(key, value);\n });\n }\n\n const queryString = urlParams.toString();\n return queryString !== '' ? `?${queryString}` : '';\n}\n\n/**\n * Calls the `/-/healthy` endpoint to check if the datasource is healthy.\n */\nexport function healthCheck(queryOptions: QueryOptions) {\n return async (): Promise<boolean> => {\n const url = `${queryOptions.datasourceUrl}/-/healthy${buildQueryString(queryOptions.queryParams)}`;\n\n try {\n const resp = await fetch(url, { headers: queryOptions.headers, signal: queryOptions.abortSignal });\n return resp.status === 200;\n } catch {\n return false;\n }\n };\n}\n\n/**\n * Calls the `/api/v1/query` endpoint to get metrics data.\n */\nexport function instantQuery(\n params: InstantQueryRequestParameters,\n queryOptions: QueryOptions\n): Promise<InstantQueryResponse> {\n return fetchWithPost<InstantQueryRequestParameters, InstantQueryResponse>('/api/v1/query', params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/query_range` endpoint to get metrics data.\n */\nexport function rangeQuery(\n params: RangeQueryRequestParameters,\n queryOptions: QueryOptions\n): Promise<RangeQueryResponse> {\n return fetchWithPost<RangeQueryRequestParameters, RangeQueryResponse>('/api/v1/query_range', params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/labels` endpoint to get a list of label names.\n */\nexport function labelNames(\n params: LabelNamesRequestParameters,\n queryOptions: QueryOptions\n): Promise<LabelNamesResponse> {\n return fetchWithPost<LabelNamesRequestParameters, LabelNamesResponse>('/api/v1/labels', params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/label/{labelName}/values` endpoint to get a list of values for a label.\n */\nexport function labelValues(\n params: LabelValuesRequestParameters,\n queryOptions: QueryOptions\n): Promise<LabelValuesResponse> {\n const { labelName, ...searchParams } = params;\n\n // In case label name is empty, we'll receive a 404, so we can replace it by an empty list, which is less confusing.\n // Note that an empty list is the prometheus result if the label does not exist.\n if (labelName.length === 0) {\n return new Promise((resolve) => {\n resolve({ data: [] as string[] } as SuccessResponse<string[]>);\n });\n }\n\n const apiURI = `/api/v1/label/${encodeURIComponent(labelName)}/values`;\n return fetchWithGet<typeof searchParams, LabelValuesResponse>(apiURI, searchParams, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/label/{labelName}/values` endpoint to get a list of values for a label.\n */\nexport function metricMetadata(\n params: MetricMetadataRequestParameters,\n queryOptions: QueryOptions\n): Promise<MetricMetadataResponse> {\n const apiURI = `/api/v1/metadata`;\n return fetchWithGet<MetricMetadataRequestParameters, MetricMetadataResponse>(apiURI, params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/series` endpoint to finding series by label matchers.\n */\nexport function series(params: SeriesRequestParameters, queryOptions: QueryOptions): Promise<SeriesResponse> {\n const apiURI = `/api/v1/series`;\n return fetchWithPost<SeriesRequestParameters, SeriesResponse>(apiURI, params, queryOptions);\n}\n\n/**\n * Calls the `/api/v1/parse_query` to parse the given promQL expresion into an abstract syntax tree (AST).\n */\nexport function parseQuery(\n params: ParseQueryRequestParameters,\n queryOptions: QueryOptions\n): Promise<ParseQueryResponse> {\n const apiURI = `/api/v1/parse_query`;\n return fetchWithPost<ParseQueryRequestParameters, ParseQueryResponse>(apiURI, params, queryOptions);\n}\n\nfunction fetchWithGet<T extends RequestParams<T>, TResponse>(\n apiURI: string,\n params: T,\n queryOptions: QueryOptions\n): Promise<TResponse> {\n const { datasourceUrl, headers, queryParams } = queryOptions;\n const url = `${datasourceUrl}${apiURI}${buildQueryString(queryParams, createSearchParams(params))}`;\n return fetchJson<TResponse>(url, { method: 'GET', headers });\n}\n\nfunction fetchWithPost<T extends RequestParams<T>, TResponse>(\n apiURI: string,\n params: T,\n queryOptions: QueryOptions\n): Promise<TResponse> {\n const { datasourceUrl, headers, abortSignal: signal, queryParams } = queryOptions;\n const url = `${datasourceUrl}${apiURI}${buildQueryString(queryParams)}`;\n\n const init = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n ...headers,\n },\n signal,\n body: createSearchParams(params),\n };\n return fetchResults<TResponse>(url, init);\n}\n\n// Request parameter values we know how to serialize\ntype ParamValue = string | string[] | number | undefined;\n\n// Used to constrain the types that can be passed to createSearchParams to\n// just the ones we know how to serialize\ntype RequestParams<T> = {\n [K in keyof T]: ParamValue;\n};\n\n/**\n * Creates URLSearchParams from a request params object.\n */\nfunction createSearchParams<T extends RequestParams<T>>(params: T): URLSearchParams {\n const searchParams = new URLSearchParams();\n for (const key in params) {\n const value: ParamValue = params[key];\n if (value === undefined) continue;\n\n if (typeof value === 'string') {\n searchParams.append(key, value);\n continue;\n }\n\n if (typeof value === 'number') {\n searchParams.append(key, value.toString());\n continue;\n }\n\n for (const val of value) {\n searchParams.append(key, val);\n }\n }\n return searchParams;\n}\n\n/**\n * Fetch JSON and parse warnings for query inspector\n */\nexport async function fetchResults<T>(...args: Parameters<typeof global.fetch>): Promise<T> {\n const response = await fetch(...args);\n const json: T = await response.json();\n return { ...json, rawResponse: response };\n}\n"],"names":["fetch","fetchJson","buildQueryString","queryParams","initialParams","urlParams","URLSearchParams","Object","entries","forEach","key","value","set","queryString","toString","healthCheck","queryOptions","url","datasourceUrl","resp","headers","signal","abortSignal","status","instantQuery","params","fetchWithPost","rangeQuery","labelNames","labelValues","labelName","searchParams","length","Promise","resolve","data","apiURI","encodeURIComponent","fetchWithGet","metricMetadata","series","parseQuery","createSearchParams","method","init","body","fetchResults","undefined","append","val","args","response","json","rawResponse"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
2
|
// Copyright 2023 The Perses Authors
|
|
2
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -10,7 +11,6 @@
|
|
|
10
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
12
|
// See the License for the specific language governing permissions and
|
|
12
13
|
// limitations under the License.
|
|
13
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
import { Stack, TextField, Button, Box, IconButton } from '@mui/material';
|
|
15
15
|
import { produce } from 'immer';
|
|
16
16
|
import TrashIcon from 'mdi-material-ui/TrashCan';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/plugins/MatcherEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Stack, TextField, Button, Box, IconButton } from '@mui/material';\nimport { produce } from 'immer';\nimport TrashIcon from 'mdi-material-ui/TrashCan';\nimport { ReactElement } from 'react';\n\ntype MatcherEditorProps = {\n matchers: string[];\n onChange: (matchers: string[]) => void;\n isReadonly?: boolean;\n};\n\nexport function MatcherEditor({ matchers, onChange, isReadonly }: MatcherEditorProps): ReactElement {\n return (\n <Stack spacing={1} mb={2}>\n {matchers.map((matcher, index) => (\n <Box key={index} display=\"flex\">\n <TextField\n fullWidth\n label=\"Series Selector\"\n value={matcher}\n InputProps={{\n readOnly: isReadonly,\n }}\n onChange={(e) => {\n const newMatchers = produce(matchers, (draft) => {\n draft[index] = e.target.value;\n });\n onChange(newMatchers);\n }}\n />\n <IconButton\n onClick={() => {\n const newMatchers = produce(matchers, (draft) => {\n draft.splice(index, 1);\n });\n onChange(newMatchers);\n }}\n disabled={isReadonly}\n >\n <TrashIcon />\n </IconButton>\n </Box>\n ))}\n <Box>\n <Button\n fullWidth={false}\n color=\"secondary\"\n variant=\"outlined\"\n onClick={() => {\n const newMatchers = produce(matchers, (draft) => {\n draft.push('');\n });\n onChange(newMatchers);\n }}\n disabled={isReadonly}\n >\n Add Series Selector\n </Button>\n </Box>\n </Stack>\n );\n}\n"],"names":["Stack","TextField","Button","Box","IconButton","produce","TrashIcon","MatcherEditor","matchers","onChange","isReadonly","spacing","mb","map","matcher","index","display","fullWidth","label","value","InputProps","readOnly","e","newMatchers","draft","target","onClick","splice","disabled","color","variant","push"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC
|
|
1
|
+
{"version":3,"sources":["../../../src/plugins/MatcherEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Stack, TextField, Button, Box, IconButton } from '@mui/material';\nimport { produce } from 'immer';\nimport TrashIcon from 'mdi-material-ui/TrashCan';\nimport { ReactElement } from 'react';\n\ntype MatcherEditorProps = {\n matchers: string[];\n onChange: (matchers: string[]) => void;\n isReadonly?: boolean;\n};\n\nexport function MatcherEditor({ matchers, onChange, isReadonly }: MatcherEditorProps): ReactElement {\n return (\n <Stack spacing={1} mb={2}>\n {matchers.map((matcher, index) => (\n <Box key={index} display=\"flex\">\n <TextField\n fullWidth\n label=\"Series Selector\"\n value={matcher}\n InputProps={{\n readOnly: isReadonly,\n }}\n onChange={(e) => {\n const newMatchers = produce(matchers, (draft) => {\n draft[index] = e.target.value;\n });\n onChange(newMatchers);\n }}\n />\n <IconButton\n onClick={() => {\n const newMatchers = produce(matchers, (draft) => {\n draft.splice(index, 1);\n });\n onChange(newMatchers);\n }}\n disabled={isReadonly}\n >\n <TrashIcon />\n </IconButton>\n </Box>\n ))}\n <Box>\n <Button\n fullWidth={false}\n color=\"secondary\"\n variant=\"outlined\"\n onClick={() => {\n const newMatchers = produce(matchers, (draft) => {\n draft.push('');\n });\n onChange(newMatchers);\n }}\n disabled={isReadonly}\n >\n Add Series Selector\n </Button>\n </Box>\n </Stack>\n );\n}\n"],"names":["Stack","TextField","Button","Box","IconButton","produce","TrashIcon","MatcherEditor","matchers","onChange","isReadonly","spacing","mb","map","matcher","index","display","fullWidth","label","value","InputProps","readOnly","e","newMatchers","draft","target","onClick","splice","disabled","color","variant","push"],"mappings":";AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,KAAK,EAAEC,SAAS,EAAEC,MAAM,EAAEC,GAAG,EAAEC,UAAU,QAAQ,gBAAgB;AAC1E,SAASC,OAAO,QAAQ,QAAQ;AAChC,OAAOC,eAAe,2BAA2B;AASjD,OAAO,SAASC,cAAc,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,UAAU,EAAsB;IAClF,qBACE,MAACV;QAAMW,SAAS;QAAGC,IAAI;;YACpBJ,SAASK,GAAG,CAAC,CAACC,SAASC,sBACtB,MAACZ;oBAAgBa,SAAQ;;sCACvB,KAACf;4BACCgB,SAAS;4BACTC,OAAM;4BACNC,OAAOL;4BACPM,YAAY;gCACVC,UAAUX;4BACZ;4BACAD,UAAU,CAACa;gCACT,MAAMC,cAAclB,QAAQG,UAAU,CAACgB;oCACrCA,KAAK,CAACT,MAAM,GAAGO,EAAEG,MAAM,CAACN,KAAK;gCAC/B;gCACAV,SAASc;4BACX;;sCAEF,KAACnB;4BACCsB,SAAS;gCACP,MAAMH,cAAclB,QAAQG,UAAU,CAACgB;oCACrCA,MAAMG,MAAM,CAACZ,OAAO;gCACtB;gCACAN,SAASc;4BACX;4BACAK,UAAUlB;sCAEV,cAAA,KAACJ;;;mBAxBKS;0BA4BZ,KAACZ;0BACC,cAAA,KAACD;oBACCe,WAAW;oBACXY,OAAM;oBACNC,SAAQ;oBACRJ,SAAS;wBACP,MAAMH,cAAclB,QAAQG,UAAU,CAACgB;4BACrCA,MAAMO,IAAI,CAAC;wBACb;wBACAtB,SAASc;oBACX;oBACAK,UAAUlB;8BACX;;;;;AAMT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrometheusDatasourceEditor.d.ts","sourceRoot":"","sources":["../../../src/plugins/PrometheusDatasourceEditor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PrometheusDatasourceEditor.d.ts","sourceRoot":"","sources":["../../../src/plugins/PrometheusDatasourceEditor.tsx"],"names":[],"mappings":"AAkBA,OAAc,EAAE,YAAY,EAAoB,MAAM,OAAO,CAAC;AAC9D,OAAO,EAA2B,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAS5E,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,wBAAwB,CAAC;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,+BAA+B,GAAG,YAAY,CA6L/F"}
|
|
@@ -12,11 +12,82 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
14
14
|
import { HTTPSettingsEditor } from '@perses-dev/plugin-system';
|
|
15
|
-
import { TextField, Typography } from '@mui/material';
|
|
16
|
-
import
|
|
15
|
+
import { Box, TextField, Typography, IconButton } from '@mui/material';
|
|
16
|
+
import PlusIcon from 'mdi-material-ui/Plus';
|
|
17
|
+
import MinusIcon from 'mdi-material-ui/Minus';
|
|
18
|
+
import React, { useState, useRef } from 'react';
|
|
17
19
|
import { DEFAULT_SCRAPE_INTERVAL } from './types';
|
|
18
20
|
export function PrometheusDatasourceEditor(props) {
|
|
19
21
|
const { value, onChange, isReadonly } = props;
|
|
22
|
+
// Counter for generating unique IDs
|
|
23
|
+
const nextIdRef = useRef(0);
|
|
24
|
+
// Use local state to maintain an array of entries during editing, instead of
|
|
25
|
+
// manipulating a map directly which causes weird UX.
|
|
26
|
+
const [entries, setEntries] = useState(()=>{
|
|
27
|
+
const queryParams = value.queryParams ?? {};
|
|
28
|
+
return Object.entries(queryParams).map(([key, value])=>({
|
|
29
|
+
id: String(nextIdRef.current++),
|
|
30
|
+
key,
|
|
31
|
+
value
|
|
32
|
+
}));
|
|
33
|
+
});
|
|
34
|
+
// Check for duplicate keys
|
|
35
|
+
const keyMap = new Map();
|
|
36
|
+
const duplicateKeys = new Set();
|
|
37
|
+
entries.forEach(({ key })=>{
|
|
38
|
+
if (key !== '') {
|
|
39
|
+
const count = (keyMap.get(key) || 0) + 1;
|
|
40
|
+
keyMap.set(key, count);
|
|
41
|
+
if (count > 1) {
|
|
42
|
+
duplicateKeys.add(key);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const hasDuplicates = duplicateKeys.size > 0;
|
|
47
|
+
// Convert entries array to object and trigger onChange
|
|
48
|
+
const syncToParent = (newEntries)=>{
|
|
49
|
+
const newParams = {};
|
|
50
|
+
newEntries.forEach(({ key, value })=>{
|
|
51
|
+
if (key !== '') {
|
|
52
|
+
newParams[key] = value;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
onChange({
|
|
56
|
+
...value,
|
|
57
|
+
queryParams: Object.keys(newParams).length > 0 ? newParams : undefined
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const handleQueryParamChange = (id, field, newValue)=>{
|
|
61
|
+
const newEntries = entries.map((entry)=>{
|
|
62
|
+
if (entry.id !== id) return entry;
|
|
63
|
+
return field === 'key' ? {
|
|
64
|
+
...entry,
|
|
65
|
+
key: newValue
|
|
66
|
+
} : {
|
|
67
|
+
...entry,
|
|
68
|
+
value: newValue
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
setEntries(newEntries);
|
|
72
|
+
syncToParent(newEntries);
|
|
73
|
+
};
|
|
74
|
+
const addQueryParam = ()=>{
|
|
75
|
+
const newEntries = [
|
|
76
|
+
...entries,
|
|
77
|
+
{
|
|
78
|
+
id: String(nextIdRef.current++),
|
|
79
|
+
key: '',
|
|
80
|
+
value: ''
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
setEntries(newEntries);
|
|
84
|
+
syncToParent(newEntries);
|
|
85
|
+
};
|
|
86
|
+
const removeQueryParam = (id)=>{
|
|
87
|
+
const newEntries = entries.filter((entry)=>entry.id !== id);
|
|
88
|
+
setEntries(newEntries);
|
|
89
|
+
syncToParent(newEntries);
|
|
90
|
+
};
|
|
20
91
|
const initialSpecDirect = {
|
|
21
92
|
directUrl: ''
|
|
22
93
|
};
|
|
@@ -67,6 +138,7 @@ export function PrometheusDatasourceEditor(props) {
|
|
|
67
138
|
children: "General Settings"
|
|
68
139
|
}),
|
|
69
140
|
/*#__PURE__*/ _jsx(TextField, {
|
|
141
|
+
size: "small",
|
|
70
142
|
fullWidth: true,
|
|
71
143
|
label: "Scrape Interval",
|
|
72
144
|
value: value.scrapeInterval || '',
|
|
@@ -80,7 +152,8 @@ export function PrometheusDatasourceEditor(props) {
|
|
|
80
152
|
onChange: (e)=>onChange({
|
|
81
153
|
...value,
|
|
82
154
|
scrapeInterval: e.target.value
|
|
83
|
-
})
|
|
155
|
+
}),
|
|
156
|
+
helperText: "Set it to match the typical scrape interval used in your Prometheus instance."
|
|
84
157
|
}),
|
|
85
158
|
/*#__PURE__*/ _jsx(HTTPSettingsEditor, {
|
|
86
159
|
value: value,
|
|
@@ -88,6 +161,65 @@ export function PrometheusDatasourceEditor(props) {
|
|
|
88
161
|
isReadonly: isReadonly,
|
|
89
162
|
initialSpecDirect: initialSpecDirect,
|
|
90
163
|
initialSpecProxy: initialSpecProxy
|
|
164
|
+
}),
|
|
165
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
166
|
+
variant: "h5",
|
|
167
|
+
mt: 2,
|
|
168
|
+
mb: 1,
|
|
169
|
+
children: "Query Parameters"
|
|
170
|
+
}),
|
|
171
|
+
entries.length > 0 && /*#__PURE__*/ _jsx(_Fragment, {
|
|
172
|
+
children: entries.map((entry)=>/*#__PURE__*/ _jsxs(Box, {
|
|
173
|
+
display: "flex",
|
|
174
|
+
alignItems: "center",
|
|
175
|
+
gap: 2,
|
|
176
|
+
mb: 1,
|
|
177
|
+
children: [
|
|
178
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
179
|
+
size: "small",
|
|
180
|
+
label: "Key",
|
|
181
|
+
value: entry.key,
|
|
182
|
+
placeholder: "Parameter name",
|
|
183
|
+
disabled: isReadonly,
|
|
184
|
+
onChange: (e)=>handleQueryParamChange(entry.id, 'key', e.target.value),
|
|
185
|
+
error: duplicateKeys.has(entry.key),
|
|
186
|
+
sx: {
|
|
187
|
+
minWidth: 150
|
|
188
|
+
}
|
|
189
|
+
}),
|
|
190
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
191
|
+
size: "small",
|
|
192
|
+
label: "Value",
|
|
193
|
+
value: entry.value,
|
|
194
|
+
placeholder: "Parameter value",
|
|
195
|
+
disabled: isReadonly,
|
|
196
|
+
onChange: (e)=>handleQueryParamChange(entry.id, 'value', e.target.value),
|
|
197
|
+
sx: {
|
|
198
|
+
minWidth: 150,
|
|
199
|
+
flexGrow: 1
|
|
200
|
+
}
|
|
201
|
+
}),
|
|
202
|
+
!isReadonly && /*#__PURE__*/ _jsx(IconButton, {
|
|
203
|
+
onClick: ()=>removeQueryParam(entry.id),
|
|
204
|
+
children: /*#__PURE__*/ _jsx(MinusIcon, {})
|
|
205
|
+
})
|
|
206
|
+
]
|
|
207
|
+
}, entry.id))
|
|
208
|
+
}),
|
|
209
|
+
hasDuplicates && /*#__PURE__*/ _jsx(Typography, {
|
|
210
|
+
variant: "body2",
|
|
211
|
+
color: "error",
|
|
212
|
+
mb: 1,
|
|
213
|
+
children: "Duplicate parameter keys detected. Each key must be unique."
|
|
214
|
+
}),
|
|
215
|
+
entries.length === 0 && /*#__PURE__*/ _jsx(Typography, {
|
|
216
|
+
variant: "body2",
|
|
217
|
+
color: "textSecondary",
|
|
218
|
+
children: "No query parameters configured. Use query parameters to pass additional options to Prometheus (e.g., dedup=false for Thanos)."
|
|
219
|
+
}),
|
|
220
|
+
!isReadonly && /*#__PURE__*/ _jsx(IconButton, {
|
|
221
|
+
onClick: addQueryParam,
|
|
222
|
+
children: /*#__PURE__*/ _jsx(PlusIcon, {})
|
|
91
223
|
})
|
|
92
224
|
]
|
|
93
225
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/plugins/PrometheusDatasourceEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { DurationString } from '@perses-dev/core';\nimport { HTTPSettingsEditor } from '@perses-dev/plugin-system';\nimport { TextField, Typography } from '@mui/material';\nimport React, { ReactElement } from 'react';\nimport { DEFAULT_SCRAPE_INTERVAL, PrometheusDatasourceSpec } from './types';\n\nexport interface PrometheusDatasourceEditorProps {\n value: PrometheusDatasourceSpec;\n onChange: (next: PrometheusDatasourceSpec) => void;\n isReadonly?: boolean;\n}\n\nexport function PrometheusDatasourceEditor(props: PrometheusDatasourceEditorProps): ReactElement {\n const { value, onChange, isReadonly } = props;\n\n const initialSpecDirect: PrometheusDatasourceSpec = {\n directUrl: '',\n };\n\n const initialSpecProxy: PrometheusDatasourceSpec = {\n proxy: {\n kind: 'HTTPProxy',\n spec: {\n allowedEndpoints: [\n // list of standard endpoints suggested by default\n {\n endpointPattern: '/api/v1/labels',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/series',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/metadata',\n method: 'GET',\n },\n {\n endpointPattern: '/api/v1/query',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/query_range',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/label/([a-zA-Z0-9_-]+)/values',\n method: 'GET',\n },\n {\n endpointPattern: '/api/v1/parse_query',\n method: 'POST',\n },\n ],\n url: '',\n },\n },\n };\n\n return (\n <>\n <Typography variant=\"h4\" mb={2}>\n General Settings\n </Typography>\n <TextField\n fullWidth\n label=\"Scrape Interval\"\n value={value.scrapeInterval || ''}\n placeholder={`Default: ${DEFAULT_SCRAPE_INTERVAL}`}\n InputProps={{\n readOnly: isReadonly,\n }}\n InputLabelProps={{ shrink: isReadonly ? true : undefined }}\n onChange={(e) => onChange({ ...value, scrapeInterval: e.target.value as DurationString })}\n />\n <HTTPSettingsEditor\n value={value}\n onChange={onChange}\n isReadonly={isReadonly}\n initialSpecDirect={initialSpecDirect}\n initialSpecProxy={initialSpecProxy}\n />\n </>\n );\n}\n"],"names":["HTTPSettingsEditor","TextField","Typography","React","DEFAULT_SCRAPE_INTERVAL","PrometheusDatasourceEditor","props","value","onChange","isReadonly","initialSpecDirect","directUrl","initialSpecProxy","proxy","kind","spec","allowedEndpoints","endpointPattern","method","url","variant","mb","fullWidth","label","scrapeInterval","placeholder","InputProps","readOnly","InputLabelProps","shrink","undefined","e","target"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAGjC,SAASA,kBAAkB,QAAQ,4BAA4B;AAC/D,SAASC,SAAS,EAAEC,UAAU,QAAQ,gBAAgB;AACtD,OAAOC,WAA6B,QAAQ;AAC5C,SAASC,uBAAuB,QAAkC,UAAU;AAQ5E,OAAO,SAASC,2BAA2BC,KAAsC;IAC/E,MAAM,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,UAAU,EAAE,GAAGH;IAExC,MAAMI,oBAA8C;QAClDC,WAAW;IACb;IAEA,MAAMC,mBAA6C;QACjDC,OAAO;YACLC,MAAM;YACNC,MAAM;gBACJC,kBAAkB;oBAChB,kDAAkD;oBAClD;wBACEC,iBAAiB;wBACjBC,QAAQ;oBACV;oBACA;wBACED,iBAAiB;wBACjBC,QAAQ;oBACV;oBACA;wBACED,iBAAiB;wBACjBC,QAAQ;oBACV;oBACA;wBACED,iBAAiB;wBACjBC,QAAQ;oBACV;oBACA;wBACED,iBAAiB;wBACjBC,QAAQ;oBACV;oBACA;wBACED,iBAAiB;wBACjBC,QAAQ;oBACV;oBACA;wBACED,iBAAiB;wBACjBC,QAAQ;oBACV;iBACD;gBACDC,KAAK;YACP;QACF;IACF;IAEA,qBACE;;0BACE,KAACjB;gBAAWkB,SAAQ;gBAAKC,IAAI;0BAAG;;0BAGhC,KAACpB;gBACCqB,SAAS;gBACTC,OAAM;gBACNhB,OAAOA,MAAMiB,cAAc,IAAI;gBAC/BC,aAAa,CAAC,SAAS,EAAErB,yBAAyB;gBAClDsB,YAAY;oBACVC,UAAUlB;gBACZ;gBACAmB,iBAAiB;oBAAEC,QAAQpB,aAAa,OAAOqB;gBAAU;gBACzDtB,UAAU,CAACuB,IAAMvB,SAAS;wBAAE,GAAGD,KAAK;wBAAEiB,gBAAgBO,EAAEC,MAAM,CAACzB,KAAK;oBAAmB;;0BAEzF,KAACP;gBACCO,OAAOA;gBACPC,UAAUA;gBACVC,YAAYA;gBACZC,mBAAmBA;gBACnBE,kBAAkBA;;;;AAI1B"}
|
|
1
|
+
{"version":3,"sources":["../../../src/plugins/PrometheusDatasourceEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { DurationString } from '@perses-dev/core';\nimport { HTTPSettingsEditor } from '@perses-dev/plugin-system';\nimport { Box, TextField, Typography, IconButton } from '@mui/material';\nimport PlusIcon from 'mdi-material-ui/Plus';\nimport MinusIcon from 'mdi-material-ui/Minus';\nimport React, { ReactElement, useState, useRef } from 'react';\nimport { DEFAULT_SCRAPE_INTERVAL, PrometheusDatasourceSpec } from './types';\n\ninterface QueryParamEntry {\n // Unique identifier for the entry, added to avoid using array index as key\n id: string;\n key: string;\n value: string;\n}\n\nexport interface PrometheusDatasourceEditorProps {\n value: PrometheusDatasourceSpec;\n onChange: (next: PrometheusDatasourceSpec) => void;\n isReadonly?: boolean;\n}\n\nexport function PrometheusDatasourceEditor(props: PrometheusDatasourceEditorProps): ReactElement {\n const { value, onChange, isReadonly } = props;\n\n // Counter for generating unique IDs\n const nextIdRef = useRef(0);\n\n // Use local state to maintain an array of entries during editing, instead of\n // manipulating a map directly which causes weird UX.\n const [entries, setEntries] = useState<QueryParamEntry[]>(() => {\n const queryParams = value.queryParams ?? {};\n return Object.entries(queryParams).map(([key, value]) => ({\n id: String(nextIdRef.current++),\n key,\n value,\n }));\n });\n\n // Check for duplicate keys\n const keyMap = new Map<string, number>();\n const duplicateKeys = new Set<string>();\n entries.forEach(({ key }) => {\n if (key !== '') {\n const count = (keyMap.get(key) || 0) + 1;\n keyMap.set(key, count);\n if (count > 1) {\n duplicateKeys.add(key);\n }\n }\n });\n const hasDuplicates = duplicateKeys.size > 0;\n\n // Convert entries array to object and trigger onChange\n const syncToParent = (newEntries: QueryParamEntry[]) => {\n const newParams: Record<string, string> = {};\n newEntries.forEach(({ key, value }) => {\n if (key !== '') {\n newParams[key] = value;\n }\n });\n\n onChange({\n ...value,\n queryParams: Object.keys(newParams).length > 0 ? newParams : undefined,\n });\n };\n\n const handleQueryParamChange = (id: string, field: 'key' | 'value', newValue: string) => {\n const newEntries = entries.map((entry) => {\n if (entry.id !== id) return entry;\n return field === 'key' ? { ...entry, key: newValue } : { ...entry, value: newValue };\n });\n setEntries(newEntries);\n syncToParent(newEntries);\n };\n\n const addQueryParam = () => {\n const newEntries = [...entries, { id: String(nextIdRef.current++), key: '', value: '' }];\n setEntries(newEntries);\n syncToParent(newEntries);\n };\n\n const removeQueryParam = (id: string) => {\n const newEntries = entries.filter((entry) => entry.id !== id);\n setEntries(newEntries);\n syncToParent(newEntries);\n };\n\n const initialSpecDirect: PrometheusDatasourceSpec = {\n directUrl: '',\n };\n\n const initialSpecProxy: PrometheusDatasourceSpec = {\n proxy: {\n kind: 'HTTPProxy',\n spec: {\n allowedEndpoints: [\n // list of standard endpoints suggested by default\n {\n endpointPattern: '/api/v1/labels',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/series',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/metadata',\n method: 'GET',\n },\n {\n endpointPattern: '/api/v1/query',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/query_range',\n method: 'POST',\n },\n {\n endpointPattern: '/api/v1/label/([a-zA-Z0-9_-]+)/values',\n method: 'GET',\n },\n {\n endpointPattern: '/api/v1/parse_query',\n method: 'POST',\n },\n ],\n url: '',\n },\n },\n };\n\n return (\n <>\n <Typography variant=\"h4\" mb={2}>\n General Settings\n </Typography>\n <TextField\n size=\"small\"\n fullWidth\n label=\"Scrape Interval\"\n value={value.scrapeInterval || ''}\n placeholder={`Default: ${DEFAULT_SCRAPE_INTERVAL}`}\n InputProps={{\n readOnly: isReadonly,\n }}\n InputLabelProps={{ shrink: isReadonly ? true : undefined }}\n onChange={(e) => onChange({ ...value, scrapeInterval: e.target.value as DurationString })}\n helperText=\"Set it to match the typical scrape interval used in your Prometheus instance.\"\n />\n <HTTPSettingsEditor\n value={value}\n onChange={onChange}\n isReadonly={isReadonly}\n initialSpecDirect={initialSpecDirect}\n initialSpecProxy={initialSpecProxy}\n />\n <Typography variant=\"h5\" mt={2} mb={1}>\n Query Parameters\n </Typography>\n {entries.length > 0 && (\n <>\n {entries.map((entry) => (\n <Box key={entry.id} display=\"flex\" alignItems=\"center\" gap={2} mb={1}>\n <TextField\n size=\"small\"\n label=\"Key\"\n value={entry.key}\n placeholder=\"Parameter name\"\n disabled={isReadonly}\n onChange={(e) => handleQueryParamChange(entry.id, 'key', e.target.value)}\n error={duplicateKeys.has(entry.key)}\n sx={{ minWidth: 150 }}\n />\n <TextField\n size=\"small\"\n label=\"Value\"\n value={entry.value}\n placeholder=\"Parameter value\"\n disabled={isReadonly}\n onChange={(e) => handleQueryParamChange(entry.id, 'value', e.target.value)}\n sx={{ minWidth: 150, flexGrow: 1 }}\n />\n {!isReadonly && (\n <IconButton onClick={() => removeQueryParam(entry.id)}>\n <MinusIcon />\n </IconButton>\n )}\n </Box>\n ))}\n </>\n )}\n {hasDuplicates && (\n <Typography variant=\"body2\" color=\"error\" mb={1}>\n Duplicate parameter keys detected. Each key must be unique.\n </Typography>\n )}\n {entries.length === 0 && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No query parameters configured. Use query parameters to pass additional options to Prometheus (e.g.,\n dedup=false for Thanos).\n </Typography>\n )}\n {!isReadonly && (\n <IconButton onClick={addQueryParam}>\n <PlusIcon />\n </IconButton>\n )}\n </>\n );\n}\n"],"names":["HTTPSettingsEditor","Box","TextField","Typography","IconButton","PlusIcon","MinusIcon","React","useState","useRef","DEFAULT_SCRAPE_INTERVAL","PrometheusDatasourceEditor","props","value","onChange","isReadonly","nextIdRef","entries","setEntries","queryParams","Object","map","key","id","String","current","keyMap","Map","duplicateKeys","Set","forEach","count","get","set","add","hasDuplicates","size","syncToParent","newEntries","newParams","keys","length","undefined","handleQueryParamChange","field","newValue","entry","addQueryParam","removeQueryParam","filter","initialSpecDirect","directUrl","initialSpecProxy","proxy","kind","spec","allowedEndpoints","endpointPattern","method","url","variant","mb","fullWidth","label","scrapeInterval","placeholder","InputProps","readOnly","InputLabelProps","shrink","e","target","helperText","mt","display","alignItems","gap","disabled","error","has","sx","minWidth","flexGrow","onClick","color"],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ import { PrometheusDatasourceEditor } from './PrometheusDatasourceEditor';
|
|
|
15
15
|
/**
|
|
16
16
|
* Creates a PrometheusClient for a specific datasource spec.
|
|
17
17
|
*/ const createClient = (spec, options)=>{
|
|
18
|
-
const { directUrl, proxy } = spec;
|
|
18
|
+
const { directUrl, proxy, queryParams } = spec;
|
|
19
19
|
const { proxyUrl } = options;
|
|
20
20
|
// Use the direct URL if specified, but fallback to the proxyUrl by default if not specified
|
|
21
21
|
const datasourceUrl = directUrl ?? proxyUrl;
|
|
@@ -30,42 +30,50 @@ import { PrometheusDatasourceEditor } from './PrometheusDatasourceEditor';
|
|
|
30
30
|
},
|
|
31
31
|
healthCheck: healthCheck({
|
|
32
32
|
datasourceUrl,
|
|
33
|
-
headers: specHeaders
|
|
33
|
+
headers: specHeaders,
|
|
34
|
+
queryParams
|
|
34
35
|
}),
|
|
35
36
|
instantQuery: (params, headers, abortSignal)=>instantQuery(params, {
|
|
36
37
|
datasourceUrl,
|
|
37
38
|
headers: headers ?? specHeaders,
|
|
38
|
-
abortSignal
|
|
39
|
+
abortSignal,
|
|
40
|
+
queryParams
|
|
39
41
|
}),
|
|
40
42
|
rangeQuery: (params, headers, abortSignal)=>rangeQuery(params, {
|
|
41
43
|
datasourceUrl,
|
|
42
44
|
headers: headers ?? specHeaders,
|
|
43
|
-
abortSignal
|
|
45
|
+
abortSignal,
|
|
46
|
+
queryParams
|
|
44
47
|
}),
|
|
45
48
|
labelNames: (params, headers, abortSignal)=>labelNames(params, {
|
|
46
49
|
datasourceUrl,
|
|
47
50
|
headers: headers ?? specHeaders,
|
|
48
|
-
abortSignal
|
|
51
|
+
abortSignal,
|
|
52
|
+
queryParams
|
|
49
53
|
}),
|
|
50
54
|
labelValues: (params, headers, abortSignal)=>labelValues(params, {
|
|
51
55
|
datasourceUrl,
|
|
52
56
|
headers: headers ?? specHeaders,
|
|
53
|
-
abortSignal
|
|
57
|
+
abortSignal,
|
|
58
|
+
queryParams
|
|
54
59
|
}),
|
|
55
60
|
metricMetadata: (params, headers, abortSignal)=>metricMetadata(params, {
|
|
56
61
|
datasourceUrl,
|
|
57
62
|
headers: headers ?? specHeaders,
|
|
58
|
-
abortSignal
|
|
63
|
+
abortSignal,
|
|
64
|
+
queryParams
|
|
59
65
|
}),
|
|
60
66
|
series: (params, headers, abortSignal)=>series(params, {
|
|
61
67
|
datasourceUrl,
|
|
62
68
|
headers: headers ?? specHeaders,
|
|
63
|
-
abortSignal
|
|
69
|
+
abortSignal,
|
|
70
|
+
queryParams
|
|
64
71
|
}),
|
|
65
72
|
parseQuery: (params, headers, abortSignal)=>parseQuery(params, {
|
|
66
73
|
datasourceUrl,
|
|
67
74
|
headers: headers ?? specHeaders,
|
|
68
|
-
abortSignal
|
|
75
|
+
abortSignal,
|
|
76
|
+
queryParams
|
|
69
77
|
})
|
|
70
78
|
};
|
|
71
79
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/plugins/prometheus-datasource.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { BuiltinVariableDefinition } from '@perses-dev/core';\nimport { DatasourcePlugin } from '@perses-dev/plugin-system';\nimport {\n healthCheck,\n instantQuery,\n rangeQuery,\n labelNames,\n labelValues,\n PrometheusClient,\n metricMetadata,\n series,\n parseQuery,\n} from '../model';\nimport { PrometheusDatasourceSpec } from './types';\nimport { PrometheusDatasourceEditor } from './PrometheusDatasourceEditor';\n\n/**\n * Creates a PrometheusClient for a specific datasource spec.\n */\nconst createClient: DatasourcePlugin<PrometheusDatasourceSpec, PrometheusClient>['createClient'] = (spec, options) => {\n const { directUrl, proxy } = spec;\n const { proxyUrl } = options;\n\n // Use the direct URL if specified, but fallback to the proxyUrl by default if not specified\n const datasourceUrl = directUrl ?? proxyUrl;\n if (datasourceUrl === undefined) {\n throw new Error('No URL specified for Prometheus client. You can use directUrl in the spec to configure it.');\n }\n\n const specHeaders = proxy?.spec.headers;\n\n // Could think about this becoming a class, although it definitely doesn't have to be\n return {\n options: {\n datasourceUrl,\n },\n healthCheck: healthCheck({ datasourceUrl, headers: specHeaders }),\n instantQuery: (params, headers, abortSignal) =>\n instantQuery(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n rangeQuery: (params, headers, abortSignal) =>\n rangeQuery(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n labelNames: (params, headers, abortSignal) =>\n labelNames(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n labelValues: (params, headers, abortSignal) =>\n labelValues(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n metricMetadata: (params, headers, abortSignal) =>\n metricMetadata(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n series: (params, headers, abortSignal) =>\n series(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n parseQuery: (params, headers, abortSignal) =>\n parseQuery(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal }),\n };\n};\n\nconst getBuiltinVariableDefinitions: () => BuiltinVariableDefinition[] = () => {\n return [\n {\n kind: 'BuiltinVariable',\n spec: {\n name: '__interval',\n value: () => '$__interval', // will be overriden when time series query is called\n source: 'Prometheus',\n display: {\n name: '__interval',\n description:\n 'For dynamic queries that adapt across different time ranges, use $__interval instead of hardcoded intervals. It represents the actual spacing between data points: it’s calculated based on the current time range and the panel pixel width (taking the \"Min step\" as a lower bound).',\n hidden: true,\n },\n },\n },\n {\n kind: 'BuiltinVariable',\n spec: {\n name: '__interval_ms',\n value: () => '$__interval_ms', // will be overriden when time series query is called\n source: 'Prometheus',\n display: {\n name: '__interval_ms',\n description: 'Same as $__interval but in milliseconds.',\n hidden: true,\n },\n },\n },\n {\n kind: 'BuiltinVariable',\n spec: {\n name: '__rate_interval',\n value: () => '$__rate_interval', // will be overriden when time series query is called\n source: 'Prometheus',\n display: {\n name: '__rate_interval',\n description:\n 'Use this one rather than $__interval as the range parameter of functions like rate, increase, etc. With such function it is advised to choose a range that is at least 4x the scrape interval (this is to allow for various races, and to be resilient to a failed scrape). $__rate_interval provides that, as it is defined as `max($__interval + Min Step, 4 * Min Step)`, where Min Step value should represent the scrape interval of the metrics.',\n hidden: true,\n },\n },\n },\n ] as BuiltinVariableDefinition[];\n};\n\nexport const PrometheusDatasource: DatasourcePlugin<PrometheusDatasourceSpec, PrometheusClient> = {\n createClient,\n getBuiltinVariableDefinitions,\n OptionsEditorComponent: PrometheusDatasourceEditor,\n createInitialOptions: () => ({ directUrl: '' }),\n};\n"],"names":["healthCheck","instantQuery","rangeQuery","labelNames","labelValues","metricMetadata","series","parseQuery","PrometheusDatasourceEditor","createClient","spec","options","directUrl","proxy","proxyUrl","datasourceUrl","undefined","Error","specHeaders","headers","params","abortSignal","getBuiltinVariableDefinitions","kind","name","value","source","display","description","hidden","PrometheusDatasource","OptionsEditorComponent","createInitialOptions"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAIjC,SACEA,WAAW,EACXC,YAAY,EACZC,UAAU,EACVC,UAAU,EACVC,WAAW,EAEXC,cAAc,EACdC,MAAM,EACNC,UAAU,QACL,WAAW;AAElB,SAASC,0BAA0B,QAAQ,+BAA+B;AAE1E;;CAEC,GACD,MAAMC,eAA6F,CAACC,MAAMC;IACxG,MAAM,EAAEC,SAAS,EAAEC,KAAK,EAAE,
|
|
1
|
+
{"version":3,"sources":["../../../src/plugins/prometheus-datasource.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { BuiltinVariableDefinition } from '@perses-dev/core';\nimport { DatasourcePlugin } from '@perses-dev/plugin-system';\nimport {\n healthCheck,\n instantQuery,\n rangeQuery,\n labelNames,\n labelValues,\n PrometheusClient,\n metricMetadata,\n series,\n parseQuery,\n} from '../model';\nimport { PrometheusDatasourceSpec } from './types';\nimport { PrometheusDatasourceEditor } from './PrometheusDatasourceEditor';\n\n/**\n * Creates a PrometheusClient for a specific datasource spec.\n */\nconst createClient: DatasourcePlugin<PrometheusDatasourceSpec, PrometheusClient>['createClient'] = (spec, options) => {\n const { directUrl, proxy, queryParams } = spec;\n const { proxyUrl } = options;\n\n // Use the direct URL if specified, but fallback to the proxyUrl by default if not specified\n const datasourceUrl = directUrl ?? proxyUrl;\n if (datasourceUrl === undefined) {\n throw new Error('No URL specified for Prometheus client. You can use directUrl in the spec to configure it.');\n }\n\n const specHeaders = proxy?.spec.headers;\n\n // Could think about this becoming a class, although it definitely doesn't have to be\n return {\n options: {\n datasourceUrl,\n },\n healthCheck: healthCheck({ datasourceUrl, headers: specHeaders, queryParams }),\n instantQuery: (params, headers, abortSignal) =>\n instantQuery(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n rangeQuery: (params, headers, abortSignal) =>\n rangeQuery(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n labelNames: (params, headers, abortSignal) =>\n labelNames(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n labelValues: (params, headers, abortSignal) =>\n labelValues(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n metricMetadata: (params, headers, abortSignal) =>\n metricMetadata(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n series: (params, headers, abortSignal) =>\n series(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n parseQuery: (params, headers, abortSignal) =>\n parseQuery(params, { datasourceUrl, headers: headers ?? specHeaders, abortSignal, queryParams }),\n };\n};\n\nconst getBuiltinVariableDefinitions: () => BuiltinVariableDefinition[] = () => {\n return [\n {\n kind: 'BuiltinVariable',\n spec: {\n name: '__interval',\n value: () => '$__interval', // will be overriden when time series query is called\n source: 'Prometheus',\n display: {\n name: '__interval',\n description:\n 'For dynamic queries that adapt across different time ranges, use $__interval instead of hardcoded intervals. It represents the actual spacing between data points: it’s calculated based on the current time range and the panel pixel width (taking the \"Min step\" as a lower bound).',\n hidden: true,\n },\n },\n },\n {\n kind: 'BuiltinVariable',\n spec: {\n name: '__interval_ms',\n value: () => '$__interval_ms', // will be overriden when time series query is called\n source: 'Prometheus',\n display: {\n name: '__interval_ms',\n description: 'Same as $__interval but in milliseconds.',\n hidden: true,\n },\n },\n },\n {\n kind: 'BuiltinVariable',\n spec: {\n name: '__rate_interval',\n value: () => '$__rate_interval', // will be overriden when time series query is called\n source: 'Prometheus',\n display: {\n name: '__rate_interval',\n description:\n 'Use this one rather than $__interval as the range parameter of functions like rate, increase, etc. With such function it is advised to choose a range that is at least 4x the scrape interval (this is to allow for various races, and to be resilient to a failed scrape). $__rate_interval provides that, as it is defined as `max($__interval + Min Step, 4 * Min Step)`, where Min Step value should represent the scrape interval of the metrics.',\n hidden: true,\n },\n },\n },\n ] as BuiltinVariableDefinition[];\n};\n\nexport const PrometheusDatasource: DatasourcePlugin<PrometheusDatasourceSpec, PrometheusClient> = {\n createClient,\n getBuiltinVariableDefinitions,\n OptionsEditorComponent: PrometheusDatasourceEditor,\n createInitialOptions: () => ({ directUrl: '' }),\n};\n"],"names":["healthCheck","instantQuery","rangeQuery","labelNames","labelValues","metricMetadata","series","parseQuery","PrometheusDatasourceEditor","createClient","spec","options","directUrl","proxy","queryParams","proxyUrl","datasourceUrl","undefined","Error","specHeaders","headers","params","abortSignal","getBuiltinVariableDefinitions","kind","name","value","source","display","description","hidden","PrometheusDatasource","OptionsEditorComponent","createInitialOptions"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAIjC,SACEA,WAAW,EACXC,YAAY,EACZC,UAAU,EACVC,UAAU,EACVC,WAAW,EAEXC,cAAc,EACdC,MAAM,EACNC,UAAU,QACL,WAAW;AAElB,SAASC,0BAA0B,QAAQ,+BAA+B;AAE1E;;CAEC,GACD,MAAMC,eAA6F,CAACC,MAAMC;IACxG,MAAM,EAAEC,SAAS,EAAEC,KAAK,EAAEC,WAAW,EAAE,GAAGJ;IAC1C,MAAM,EAAEK,QAAQ,EAAE,GAAGJ;IAErB,4FAA4F;IAC5F,MAAMK,gBAAgBJ,aAAaG;IACnC,IAAIC,kBAAkBC,WAAW;QAC/B,MAAM,IAAIC,MAAM;IAClB;IAEA,MAAMC,cAAcN,OAAOH,KAAKU;IAEhC,qFAAqF;IACrF,OAAO;QACLT,SAAS;YACPK;QACF;QACAhB,aAAaA,YAAY;YAAEgB;YAAeI,SAASD;YAAaL;QAAY;QAC5Eb,cAAc,CAACoB,QAAQD,SAASE,cAC9BrB,aAAaoB,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;QAClGZ,YAAY,CAACmB,QAAQD,SAASE,cAC5BpB,WAAWmB,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;QAChGX,YAAY,CAACkB,QAAQD,SAASE,cAC5BnB,WAAWkB,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;QAChGV,aAAa,CAACiB,QAAQD,SAASE,cAC7BlB,YAAYiB,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;QACjGT,gBAAgB,CAACgB,QAAQD,SAASE,cAChCjB,eAAegB,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;QACpGR,QAAQ,CAACe,QAAQD,SAASE,cACxBhB,OAAOe,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;QAC5FP,YAAY,CAACc,QAAQD,SAASE,cAC5Bf,WAAWc,QAAQ;gBAAEL;gBAAeI,SAASA,WAAWD;gBAAaG;gBAAaR;YAAY;IAClG;AACF;AAEA,MAAMS,gCAAmE;IACvE,OAAO;QACL;YACEC,MAAM;YACNd,MAAM;gBACJe,MAAM;gBACNC,OAAO,IAAM;gBACbC,QAAQ;gBACRC,SAAS;oBACPH,MAAM;oBACNI,aACE;oBACFC,QAAQ;gBACV;YACF;QACF;QACA;YACEN,MAAM;YACNd,MAAM;gBACJe,MAAM;gBACNC,OAAO,IAAM;gBACbC,QAAQ;gBACRC,SAAS;oBACPH,MAAM;oBACNI,aAAa;oBACbC,QAAQ;gBACV;YACF;QACF;QACA;YACEN,MAAM;YACNd,MAAM;gBACJe,MAAM;gBACNC,OAAO,IAAM;gBACbC,QAAQ;gBACRC,SAAS;oBACPH,MAAM;oBACNI,aACE;oBACFC,QAAQ;gBACV;YACF;QACF;KACD;AACH;AAEA,OAAO,MAAMC,uBAAqF;IAChGtB;IACAc;IACAS,wBAAwBxB;IACxByB,sBAAsB,IAAO,CAAA;YAAErB,WAAW;QAAG,CAAA;AAC/C,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrometheusTimeSeriesQueryEditor.d.ts","sourceRoot":"","sources":["../../../../src/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PrometheusTimeSeriesQueryEditor.d.ts","sourceRoot":"","sources":["../../../../src/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAAE,YAAY,EAAuB,MAAM,OAAO,CAAC;AAgB1D,OAAO,EACL,oCAAoC,EAIrC,MAAM,sBAAsB,CAAC;AAC9B;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,oCAAoC,GAAG,YAAY,CAmIzG"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
2
|
// Copyright 2023 The Perses Authors
|
|
2
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -10,12 +11,13 @@
|
|
|
10
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
12
|
// See the License for the specific language governing permissions and
|
|
12
13
|
// limitations under the License.
|
|
13
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
import { produce } from 'immer';
|
|
15
|
-
import { DatasourceSelect, useDatasource, useDatasourceClient, useDatasourceSelectValueToSelector } from '@perses-dev/plugin-system';
|
|
15
|
+
import { DatasourceSelect, replaceVariables, useAllVariableValues, useDatasource, useDatasourceClient, useDatasourceSelectValueToSelector, useSuggestedStepMs, useTimeRange } from '@perses-dev/plugin-system';
|
|
16
16
|
import { useId } from '@perses-dev/components';
|
|
17
17
|
import { FormControl, Stack, TextField } from '@mui/material';
|
|
18
|
-
import {
|
|
18
|
+
import { useContext, useMemo } from 'react';
|
|
19
|
+
import { PanelEditorContext } from '@perses-dev/dashboards';
|
|
20
|
+
import { DEFAULT_PROM, getDurationStringSeconds, getPrometheusTimeRange, getRangeStep, isDefaultPromSelector, isPrometheusDatasourceSelector, PROM_DATASOURCE_KIND } from '../../model';
|
|
19
21
|
import { DEFAULT_SCRAPE_INTERVAL } from '../types';
|
|
20
22
|
import { PromQLEditor } from '../../components';
|
|
21
23
|
import { useQueryState, useFormatState, useMinStepState } from './query-editor-model';
|
|
@@ -47,6 +49,38 @@ import { useQueryState, useFormatState, useMinStepState } from './query-editor-m
|
|
|
47
49
|
}
|
|
48
50
|
throw new Error('Got unexpected non-Prometheus datasource selector');
|
|
49
51
|
};
|
|
52
|
+
const variableState = useAllVariableValues();
|
|
53
|
+
const { absoluteTimeRange } = useTimeRange();
|
|
54
|
+
const panelEditorContext = useContext(PanelEditorContext);
|
|
55
|
+
const suggestedStepMs = useSuggestedStepMs(panelEditorContext?.preview.previewPanelWidth);
|
|
56
|
+
const minStepMs = useMemo(()=>{
|
|
57
|
+
/* Try catch is necessary, because when the minStep value is being typed, it will be valid when the duration unit is added. Example: 2m = 2 + m */ try {
|
|
58
|
+
const durationsSeconds = getDurationStringSeconds(replaceVariables(minStepPlaceholder, variableState));
|
|
59
|
+
return durationsSeconds !== undefined ? durationsSeconds * 1000 : undefined;
|
|
60
|
+
} catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}, [
|
|
64
|
+
variableState,
|
|
65
|
+
minStepPlaceholder
|
|
66
|
+
]);
|
|
67
|
+
const intervalMs = useMemo(()=>{
|
|
68
|
+
const minStepSeconds = (minStepMs ?? 0) / 1000;
|
|
69
|
+
return getRangeStep(getPrometheusTimeRange(absoluteTimeRange), minStepSeconds, undefined, suggestedStepMs) * 1000;
|
|
70
|
+
}, [
|
|
71
|
+
absoluteTimeRange,
|
|
72
|
+
minStepMs,
|
|
73
|
+
suggestedStepMs
|
|
74
|
+
]);
|
|
75
|
+
const treeViewMetadata = useMemo(()=>{
|
|
76
|
+
return minStepMs && intervalMs ? {
|
|
77
|
+
minStepMs,
|
|
78
|
+
intervalMs
|
|
79
|
+
} : undefined;
|
|
80
|
+
}, [
|
|
81
|
+
minStepMs,
|
|
82
|
+
intervalMs
|
|
83
|
+
]);
|
|
50
84
|
return /*#__PURE__*/ _jsxs(Stack, {
|
|
51
85
|
spacing: 2,
|
|
52
86
|
children: [
|
|
@@ -73,7 +107,8 @@ import { useQueryState, useFormatState, useMinStepState } from './query-editor-m
|
|
|
73
107
|
datasource: selectedDatasource,
|
|
74
108
|
onChange: handleQueryChange,
|
|
75
109
|
onBlur: handleQueryBlur,
|
|
76
|
-
isReadOnly: isReadonly
|
|
110
|
+
isReadOnly: isReadonly,
|
|
111
|
+
treeViewMetadata: treeViewMetadata
|
|
77
112
|
}),
|
|
78
113
|
/*#__PURE__*/ _jsxs(Stack, {
|
|
79
114
|
direction: "row",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { produce } from 'immer';\nimport {\n DatasourceSelect,\n DatasourceSelectProps,\n useDatasource,\n useDatasourceClient,\n useDatasourceSelectValueToSelector,\n} from '@perses-dev/plugin-system';\nimport { useId } from '@perses-dev/components';\nimport { FormControl, Stack, TextField } from '@mui/material';\nimport { ReactElement } from 'react';\nimport {\n DEFAULT_PROM,\n DurationString,\n isDefaultPromSelector,\n isPrometheusDatasourceSelector,\n PROM_DATASOURCE_KIND,\n PrometheusClient,\n PrometheusDatasourceSelector,\n} from '../../model';\nimport { DEFAULT_SCRAPE_INTERVAL, PrometheusDatasourceSpec } from '../types';\nimport { PromQLEditor } from '../../components';\nimport {\n PrometheusTimeSeriesQueryEditorProps,\n useQueryState,\n useFormatState,\n useMinStepState,\n} from './query-editor-model';\n\n/**\n * The options editor component for editing a PrometheusTimeSeriesQuery's spec.\n */\nexport function PrometheusTimeSeriesQueryEditor(props: PrometheusTimeSeriesQueryEditorProps): ReactElement {\n const {\n onChange,\n value,\n value: { query, datasource },\n isReadonly,\n } = props;\n\n const datasourceSelectValue = datasource ?? DEFAULT_PROM;\n\n const datasourceSelectLabelID = useId('prom-datasource-label'); // for panels with multiple queries, this component is rendered multiple times on the same page\n\n const selectedDatasource = useDatasourceSelectValueToSelector(\n datasourceSelectValue,\n PROM_DATASOURCE_KIND\n ) as PrometheusDatasourceSelector;\n\n const { data: client } = useDatasourceClient<PrometheusClient>(selectedDatasource);\n const promURL = client?.options.datasourceUrl;\n const { data: datasourceResource } = useDatasource(selectedDatasource);\n\n const { handleQueryChange, handleQueryBlur } = useQueryState(props);\n const { format, handleFormatChange, handleFormatBlur } = useFormatState(props);\n const { minStep, handleMinStepChange, handleMinStepBlur } = useMinStepState(props);\n const minStepPlaceholder =\n minStep ??\n (datasourceResource && (datasourceResource?.plugin.spec as PrometheusDatasourceSpec).scrapeInterval) ??\n DEFAULT_SCRAPE_INTERVAL;\n\n const handleDatasourceChange: DatasourceSelectProps['onChange'] = (next) => {\n if (isPrometheusDatasourceSelector(next)) {\n /* Good to know: The usage of onchange here causes an immediate spec update which eventually updates the panel\n This was probably intentional to allow for quick switching between datasources.\n Could have been triggered only with Run Query button as well.\n */\n onChange(\n produce(value, (draft) => {\n // If they're using the default, just omit the datasource prop (i.e. set to undefined)\n const nextDatasource = isDefaultPromSelector(next) ? undefined : next;\n draft.datasource = nextDatasource;\n })\n );\n return;\n }\n\n throw new Error('Got unexpected non-Prometheus datasource selector');\n };\n\n return (\n <Stack spacing={2}>\n <FormControl margin=\"dense\" fullWidth={false}>\n <DatasourceSelect\n datasourcePluginKind={PROM_DATASOURCE_KIND}\n value={datasourceSelectValue}\n onChange={handleDatasourceChange}\n labelId={datasourceSelectLabelID}\n label=\"Prometheus Datasource\"\n notched\n readOnly={isReadonly}\n />\n </FormControl>\n <PromQLEditor\n completeConfig={{ remote: { url: promURL } }}\n value={query} // here we are passing `value.query` and not `query` from useQueryState in order to get updates only on onBlur events\n datasource={selectedDatasource}\n onChange={handleQueryChange}\n onBlur={handleQueryBlur}\n isReadOnly={isReadonly}\n />\n <Stack direction=\"row\" spacing={2}>\n <TextField\n fullWidth\n label=\"Legend\"\n placeholder=\"Example: '{{instance}}' will generate series names like 'webserver-123', 'webserver-456'...\"\n helperText=\"Text to be displayed in the legend and the tooltip. Use {{label_name}} to interpolate label values.\"\n value={format ?? ''}\n onChange={(e) => handleFormatChange(e.target.value)}\n onBlur={handleFormatBlur}\n slotProps={{\n inputLabel: { shrink: isReadonly ? true : undefined },\n input: { readOnly: isReadonly },\n }}\n />\n <TextField\n label=\"Min Step\"\n placeholder={minStepPlaceholder}\n helperText=\"Lower bound for the step. If not provided, the scrape interval of the datasource is used.\"\n value={minStep ?? ''}\n onChange={(e) => handleMinStepChange(e.target.value ? (e.target.value as DurationString) : undefined)}\n onBlur={handleMinStepBlur}\n sx={{ width: '250px' }}\n slotProps={{\n inputLabel: { shrink: isReadonly ? true : undefined },\n input: { readOnly: isReadonly },\n }}\n />\n </Stack>\n </Stack>\n );\n}\n"],"names":["produce","DatasourceSelect","useDatasource","useDatasourceClient","useDatasourceSelectValueToSelector","useId","FormControl","Stack","TextField","DEFAULT_PROM","isDefaultPromSelector","isPrometheusDatasourceSelector","PROM_DATASOURCE_KIND","DEFAULT_SCRAPE_INTERVAL","PromQLEditor","useQueryState","useFormatState","useMinStepState","PrometheusTimeSeriesQueryEditor","props","onChange","value","query","datasource","isReadonly","datasourceSelectValue","datasourceSelectLabelID","selectedDatasource","data","client","promURL","options","datasourceUrl","datasourceResource","handleQueryChange","handleQueryBlur","format","handleFormatChange","handleFormatBlur","minStep","handleMinStepChange","handleMinStepBlur","minStepPlaceholder","plugin","spec","scrapeInterval","handleDatasourceChange","next","draft","nextDatasource","undefined","Error","spacing","margin","fullWidth","datasourcePluginKind","labelId","label","notched","readOnly","completeConfig","remote","url","onBlur","isReadOnly","direction","placeholder","helperText","e","target","slotProps","inputLabel","shrink","input","sx","width"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { produce } from 'immer';\nimport {\n DatasourceSelect,\n DatasourceSelectProps,\n replaceVariables,\n useAllVariableValues,\n useDatasource,\n useDatasourceClient,\n useDatasourceSelectValueToSelector,\n useSuggestedStepMs,\n useTimeRange,\n} from '@perses-dev/plugin-system';\nimport { useId } from '@perses-dev/components';\nimport { FormControl, Stack, TextField } from '@mui/material';\nimport { ReactElement, useContext, useMemo } from 'react';\nimport { PanelEditorContext } from '@perses-dev/dashboards';\nimport {\n DEFAULT_PROM,\n DurationString,\n getDurationStringSeconds,\n getPrometheusTimeRange,\n getRangeStep,\n isDefaultPromSelector,\n isPrometheusDatasourceSelector,\n PROM_DATASOURCE_KIND,\n PrometheusClient,\n PrometheusDatasourceSelector,\n} from '../../model';\nimport { DEFAULT_SCRAPE_INTERVAL, PrometheusDatasourceSpec } from '../types';\nimport { PromQLEditor } from '../../components';\nimport {\n PrometheusTimeSeriesQueryEditorProps,\n useQueryState,\n useFormatState,\n useMinStepState,\n} from './query-editor-model';\n/**\n * The options editor component for editing a PrometheusTimeSeriesQuery's spec.\n */\nexport function PrometheusTimeSeriesQueryEditor(props: PrometheusTimeSeriesQueryEditorProps): ReactElement {\n const {\n onChange,\n value,\n value: { query, datasource },\n isReadonly,\n } = props;\n\n const datasourceSelectValue = datasource ?? DEFAULT_PROM;\n\n const datasourceSelectLabelID = useId('prom-datasource-label'); // for panels with multiple queries, this component is rendered multiple times on the same page\n\n const selectedDatasource = useDatasourceSelectValueToSelector(\n datasourceSelectValue,\n PROM_DATASOURCE_KIND\n ) as PrometheusDatasourceSelector;\n\n const { data: client } = useDatasourceClient<PrometheusClient>(selectedDatasource);\n const promURL = client?.options.datasourceUrl;\n const { data: datasourceResource } = useDatasource(selectedDatasource);\n\n const { handleQueryChange, handleQueryBlur } = useQueryState(props);\n const { format, handleFormatChange, handleFormatBlur } = useFormatState(props);\n const { minStep, handleMinStepChange, handleMinStepBlur } = useMinStepState(props);\n const minStepPlaceholder =\n minStep ??\n (datasourceResource && (datasourceResource?.plugin.spec as PrometheusDatasourceSpec).scrapeInterval) ??\n DEFAULT_SCRAPE_INTERVAL;\n\n const handleDatasourceChange: DatasourceSelectProps['onChange'] = (next) => {\n if (isPrometheusDatasourceSelector(next)) {\n /* Good to know: The usage of onchange here causes an immediate spec update which eventually updates the panel\n This was probably intentional to allow for quick switching between datasources.\n Could have been triggered only with Run Query button as well.\n */\n onChange(\n produce(value, (draft) => {\n // If they're using the default, just omit the datasource prop (i.e. set to undefined)\n const nextDatasource = isDefaultPromSelector(next) ? undefined : next;\n draft.datasource = nextDatasource;\n })\n );\n return;\n }\n\n throw new Error('Got unexpected non-Prometheus datasource selector');\n };\n\n const variableState = useAllVariableValues();\n const { absoluteTimeRange } = useTimeRange();\n const panelEditorContext = useContext(PanelEditorContext);\n const suggestedStepMs = useSuggestedStepMs(panelEditorContext?.preview.previewPanelWidth);\n\n const minStepMs = useMemo(() => {\n /* Try catch is necessary, because when the minStep value is being typed, it will be valid when the duration unit is added. Example: 2m = 2 + m */\n try {\n const durationsSeconds = getDurationStringSeconds(\n replaceVariables(minStepPlaceholder, variableState) as DurationString\n );\n return durationsSeconds !== undefined ? durationsSeconds * 1000 : undefined;\n } catch {\n return undefined;\n }\n }, [variableState, minStepPlaceholder]);\n\n const intervalMs = useMemo(() => {\n const minStepSeconds = (minStepMs ?? 0) / 1000;\n return getRangeStep(getPrometheusTimeRange(absoluteTimeRange), minStepSeconds, undefined, suggestedStepMs) * 1000;\n }, [absoluteTimeRange, minStepMs, suggestedStepMs]);\n\n const treeViewMetadata = useMemo(() => {\n return minStepMs && intervalMs\n ? {\n minStepMs,\n intervalMs,\n }\n : undefined;\n }, [minStepMs, intervalMs]);\n\n return (\n <Stack spacing={2}>\n <FormControl margin=\"dense\" fullWidth={false}>\n <DatasourceSelect\n datasourcePluginKind={PROM_DATASOURCE_KIND}\n value={datasourceSelectValue}\n onChange={handleDatasourceChange}\n labelId={datasourceSelectLabelID}\n label=\"Prometheus Datasource\"\n notched\n readOnly={isReadonly}\n />\n </FormControl>\n <PromQLEditor\n completeConfig={{ remote: { url: promURL } }}\n value={query} // here we are passing `value.query` and not `query` from useQueryState in order to get updates only on onBlur events\n datasource={selectedDatasource}\n onChange={handleQueryChange}\n onBlur={handleQueryBlur}\n isReadOnly={isReadonly}\n treeViewMetadata={treeViewMetadata}\n />\n <Stack direction=\"row\" spacing={2}>\n <TextField\n fullWidth\n label=\"Legend\"\n placeholder=\"Example: '{{instance}}' will generate series names like 'webserver-123', 'webserver-456'...\"\n helperText=\"Text to be displayed in the legend and the tooltip. Use {{label_name}} to interpolate label values.\"\n value={format ?? ''}\n onChange={(e) => handleFormatChange(e.target.value)}\n onBlur={handleFormatBlur}\n slotProps={{\n inputLabel: { shrink: isReadonly ? true : undefined },\n input: { readOnly: isReadonly },\n }}\n />\n <TextField\n label=\"Min Step\"\n placeholder={minStepPlaceholder}\n helperText=\"Lower bound for the step. If not provided, the scrape interval of the datasource is used.\"\n value={minStep ?? ''}\n onChange={(e) => handleMinStepChange(e.target.value ? (e.target.value as DurationString) : undefined)}\n onBlur={handleMinStepBlur}\n sx={{ width: '250px' }}\n slotProps={{\n inputLabel: { shrink: isReadonly ? true : undefined },\n input: { readOnly: isReadonly },\n }}\n />\n </Stack>\n </Stack>\n );\n}\n"],"names":["produce","DatasourceSelect","replaceVariables","useAllVariableValues","useDatasource","useDatasourceClient","useDatasourceSelectValueToSelector","useSuggestedStepMs","useTimeRange","useId","FormControl","Stack","TextField","useContext","useMemo","PanelEditorContext","DEFAULT_PROM","getDurationStringSeconds","getPrometheusTimeRange","getRangeStep","isDefaultPromSelector","isPrometheusDatasourceSelector","PROM_DATASOURCE_KIND","DEFAULT_SCRAPE_INTERVAL","PromQLEditor","useQueryState","useFormatState","useMinStepState","PrometheusTimeSeriesQueryEditor","props","onChange","value","query","datasource","isReadonly","datasourceSelectValue","datasourceSelectLabelID","selectedDatasource","data","client","promURL","options","datasourceUrl","datasourceResource","handleQueryChange","handleQueryBlur","format","handleFormatChange","handleFormatBlur","minStep","handleMinStepChange","handleMinStepBlur","minStepPlaceholder","plugin","spec","scrapeInterval","handleDatasourceChange","next","draft","nextDatasource","undefined","Error","variableState","absoluteTimeRange","panelEditorContext","suggestedStepMs","preview","previewPanelWidth","minStepMs","durationsSeconds","intervalMs","minStepSeconds","treeViewMetadata","spacing","margin","fullWidth","datasourcePluginKind","labelId","label","notched","readOnly","completeConfig","remote","url","onBlur","isReadOnly","direction","placeholder","helperText","e","target","slotProps","inputLabel","shrink","input","sx","width"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-time-series-data.d.ts","sourceRoot":"","sources":["../../../../src/plugins/prometheus-time-series-query/get-time-series-data.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAqD,MAAM,2BAA2B,CAAC;AAiBrH,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAG1E,eAAO,MAAM,iBAAiB,EAAE,qBAAqB,CAAC,6BAA6B,CAAC,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"get-time-series-data.d.ts","sourceRoot":"","sources":["../../../../src/plugins/prometheus-time-series-query/get-time-series-data.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAqD,MAAM,2BAA2B,CAAC;AAiBrH,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAG1E,eAAO,MAAM,iBAAiB,EAAE,qBAAqB,CAAC,6BAA6B,CAAC,CAAC,mBAAmB,CAqIvG,CAAC"}
|