Skip to content

Commit 17b054f

Browse files
committed
[BUGFIX] Prometheus: Propagate headers to the @prometheus-io/codemirror-promql package
Signed-off-by: Mykhailo Semenchenko <[email protected]>
1 parent 5619ba6 commit 17b054f

File tree

6 files changed

+99
-4
lines changed

6 files changed

+99
-4
lines changed

prometheus/src/model/api-types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,5 @@ export interface ParseQueryRequestParameters {
139139
}
140140

141141
export type ParseQueryResponse = ApiResponse<ASTNode>;
142+
143+
export type FlagsResponse = ApiResponse<Record<string, string>>;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2025 The Perses Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
import { PrometheusClient as CodeMirrorPrometheusClient } from '@prometheus-io/codemirror-promql';
15+
import { LabelNamesRequestParameters, LabelValuesRequestParameters, SeriesRequestParameters } from './api-types';
16+
import { Matcher } from '@prometheus-io/codemirror-promql/dist/esm/types';
17+
import { PrometheusClient } from './prometheus-client';
18+
import { MetricMetadata } from '@prometheus-io/codemirror-promql/dist/esm/client/prometheus';
19+
20+
export const createCodeMirrorPromClient = (
21+
prometheusClient?: PrometheusClient
22+
): CodeMirrorPrometheusClient | undefined => {
23+
if (prometheusClient) {
24+
return {
25+
labelNames: async (metricNames: string | undefined) => {
26+
let params: LabelNamesRequestParameters = {};
27+
28+
if (metricNames) {
29+
params['match[]'] = metricNames.split(',');
30+
}
31+
const { data } = (await prometheusClient?.labelNames(params)) || {};
32+
return data || [];
33+
},
34+
labelValues: async (labelName: string, metricName?: string, matchers?: Matcher[]) => {
35+
let params: LabelValuesRequestParameters = {
36+
labelName,
37+
};
38+
if (metricName) {
39+
params['match[]'] = [
40+
`${metricName}{${matchers
41+
?.reduce((acc: Matcher[], curr: Matcher) => {
42+
if (!curr.matchesEmpty()) {
43+
acc.push(curr);
44+
}
45+
return acc;
46+
}, [])
47+
.map((m) => `${m.name}${m.type}"${m.value}"`)
48+
.join(',')}}`,
49+
];
50+
}
51+
52+
const { data } = (await prometheusClient?.labelValues(params)) || {};
53+
return data || [];
54+
},
55+
metricNames: async (prefix?: string) => {
56+
let params: LabelValuesRequestParameters = {
57+
labelName: '__name__',
58+
};
59+
const { data } = (await prometheusClient?.labelValues(params)) || {};
60+
return data || [];
61+
},
62+
metricMetadata: async (): Promise<Record<string, MetricMetadata[]>> => {
63+
const { data } = (await prometheusClient?.metricMetadata({})) || {};
64+
65+
return data || {};
66+
},
67+
series: async (metricName: string, matchers?: Matcher[], labelName?: string): Promise<Map<string, string>[]> => {
68+
const params: SeriesRequestParameters = {
69+
'match[]': [],
70+
};
71+
const { data } = (await prometheusClient?.series(params)) || {};
72+
return (data || []).map((item: any) => new Map(Object.entries(item.metric)));
73+
},
74+
flags: async () => {
75+
const { data } = (await prometheusClient?.flags()) || {};
76+
77+
return data || {};
78+
},
79+
};
80+
}
81+
};

prometheus/src/model/prometheus-client.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import { fetch, fetchJson, RequestHeaders } from '@perses-dev/core';
1515
import { DatasourceClient } from '@perses-dev/plugin-system';
1616
import {
17+
FlagsResponse,
1718
InstantQueryRequestParameters,
1819
InstantQueryResponse,
1920
LabelNamesRequestParameters,
@@ -45,6 +46,7 @@ export interface PrometheusClient extends DatasourceClient {
4546
metricMetadata(params: MetricMetadataRequestParameters, headers?: RequestHeaders): Promise<MetricMetadataResponse>;
4647
series(params: SeriesRequestParameters, headers?: RequestHeaders): Promise<SeriesResponse>;
4748
parseQuery(params: ParseQueryRequestParameters, headers?: RequestHeaders): Promise<ParseQueryResponse>;
49+
flags(headers?: RequestHeaders): Promise<FlagsResponse>;
4850
}
4951

5052
export interface QueryOptions {
@@ -149,6 +151,10 @@ export function parseQuery(
149151
return fetchWithPost<ParseQueryRequestParameters, ParseQueryResponse>(apiURI, params, queryOptions);
150152
}
151153

154+
export function flags(queryOptions: QueryOptions): Promise<FlagsResponse> {
155+
return fetchWithGet('/api/v1/status/flags', {}, queryOptions);
156+
}
157+
152158
function fetchWithGet<T extends RequestParams<T>, TResponse>(
153159
apiURI: string,
154160
params: T,

prometheus/src/plugins/prometheus-datasource.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
metricMetadata,
2424
series,
2525
parseQuery,
26+
flags,
2627
} from '../model';
2728
import { PrometheusDatasourceSpec } from './types';
2829
import { PrometheusDatasourceEditor } from './PrometheusDatasourceEditor';
@@ -55,6 +56,7 @@ const createClient: DatasourcePlugin<PrometheusDatasourceSpec, PrometheusClient>
5556
metricMetadata: (params, headers) => metricMetadata(params, { datasourceUrl, headers: headers ?? specHeaders }),
5657
series: (params, headers) => series(params, { datasourceUrl, headers: headers ?? specHeaders }),
5758
parseQuery: (params, headers) => parseQuery(params, { datasourceUrl, headers: headers ?? specHeaders }),
59+
flags: (headers) => flags({ datasourceUrl, headers: headers ?? specHeaders }),
5860
};
5961
};
6062

prometheus/src/plugins/prometheus-time-series-query/PrometheusTimeSeriesQueryEditor.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
useFormatState,
3232
useMinStepState,
3333
} from './query-editor-model';
34+
import { createCodeMirrorPromClient } from '../../model/prometheus-client.codemirror-adapter';
3435

3536
/**
3637
* The options editor component for editing a PrometheusTimeSeriesQuery's spec.
@@ -42,7 +43,7 @@ export function PrometheusTimeSeriesQueryEditor(props: PrometheusTimeSeriesQuery
4243
const datasourceSelectLabelID = `prom-datasource-label-${selectedDatasource.name || 'default'}`;
4344

4445
const { data: client } = useDatasourceClient<PrometheusClient>(selectedDatasource);
45-
const promURL = client?.options.datasourceUrl;
46+
const codeMirrorPromClient = createCodeMirrorPromClient(client);
4647
const { data: datasourceResource } = useDatasource(selectedDatasource);
4748

4849
const { handleQueryChange, handleQueryBlur } = useQueryState(props);
@@ -81,7 +82,9 @@ export function PrometheusTimeSeriesQueryEditor(props: PrometheusTimeSeriesQuery
8182
/>
8283
</FormControl>
8384
<PromQLEditor
84-
completeConfig={{ remote: { url: promURL } }}
85+
completeConfig={{
86+
remote: codeMirrorPromClient,
87+
}}
8588
value={value.query} // here we are passing `value.query` and not `query` from useQueryState in order to get updates only on onBlur events
8689
datasource={selectedDatasource}
8790
onChange={handleQueryChange}

prometheus/src/plugins/prometheus-variables.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
PrometheusLabelValuesVariableOptions,
3737
PrometheusPromQLVariableOptions,
3838
} from './types';
39+
import { createCodeMirrorPromClient } from '../model/prometheus-client.codemirror-adapter';
3940

4041
export function PrometheusLabelValuesVariableEditor(
4142
props: OptionsEditorProps<PrometheusLabelValuesVariableOptions>
@@ -146,7 +147,7 @@ export function PrometheusPromQLVariableEditor(
146147
const selectedDatasource = datasource ?? DEFAULT_PROM;
147148

148149
const { data: client } = useDatasourceClient<PrometheusClient>(selectedDatasource);
149-
const promURL = client?.options.datasourceUrl;
150+
const codeMirrorPromClient = createCodeMirrorPromClient(client);
150151

151152
const handleDatasourceChange: DatasourceSelectProps['onChange'] = (next) => {
152153
if (isPrometheusDatasourceSelector(next)) {
@@ -176,7 +177,7 @@ export function PrometheusPromQLVariableEditor(
176177
/>
177178
</FormControl>
178179
<PromQLEditor
179-
completeConfig={{ remote: { url: promURL } }}
180+
completeConfig={{ remote: codeMirrorPromClient }}
180181
value={value.expr}
181182
datasource={selectedDatasource}
182183
onBlur={(event) => {

0 commit comments

Comments
 (0)