From 7bcca77340cf4b20556b5edc0c6c235bf4b6e82a Mon Sep 17 00:00:00 2001 From: Augustin Husson Date: Fri, 24 Sep 2021 07:52:50 +0200 Subject: [PATCH] provide a way to override the apiPrefix in codemirror prom client + cleanup readme (#9384) Signed-off-by: Augustin Husson --- web/ui/module/codemirror-promql/README.md | 29 ++++++----------- .../src/client/prometheus.ts | 32 +++++++++++++------ 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/web/ui/module/codemirror-promql/README.md b/web/ui/module/codemirror-promql/README.md index 63a50bc27..b717b2d14 100644 --- a/web/ui/module/codemirror-promql/README.md +++ b/web/ui/module/codemirror-promql/README.md @@ -172,6 +172,16 @@ You can change it to use the HTTP method `GET` if you prefer. const promQL = new PromQLExtension().setComplete({ remote: { httpMethod: 'GET' } }) ``` +###### Override the API Prefix + +The default Prometheus Client, when building the query to get data from Prometheus, is using an API prefix which is by default `/api/v1`. + +You can override this value like this: + +```typescript +const promql = new PromQLExtension().setComplete({ remote: { apiPrefix: '/my/api/prefix' } }) +``` + ###### Cache The default client has an embedded cache that is used to store the different metrics and labels retrieved from a remote @@ -232,7 +242,6 @@ Note: In case this parameter is provided, then the rest of the configuration is ### Example -* The development [app](./src/app) can give you an example of how to use it with no TS Framework. * [ReactJS example](https://github.com/prometheus/prometheus/blob/431ea75a11ca165dad9dd5d629b3cf975f4c186b/web/ui/react-app/src/pages/graph/CMExpressionInput.tsx) * [Angular example](https://github.com/perses/perses/blob/28b3bdac88b0ed7a4602f9c91106442eafcb6c34/internal/api/front/perses/src/app/project/prometheusrule/promql-editor/promql-editor.component.ts) @@ -242,24 +251,6 @@ Any contribution or suggestion would be really appreciated. Feel free to [file an issue](https://github.com/prometheus-community/codemirror-promql/issues) or [send a pull request](https://github.com/prometheus-community/codemirror-promql/pulls). -## Development - -In case you want to contribute and change the code by yourself, run the following commands: - -To install all dependencies: - -``` -npm install -``` - -To start the web server: - -``` -npm start -``` - -This should create a tab in your browser with the development app that contains CodeMirror Next with the PromQL plugin. - ## License [MIT](./LICENSE) diff --git a/web/ui/module/codemirror-promql/src/client/prometheus.ts b/web/ui/module/codemirror-promql/src/client/prometheus.ts index ad9be14a5..2a03ec628 100644 --- a/web/ui/module/codemirror-promql/src/client/prometheus.ts +++ b/web/ui/module/codemirror-promql/src/client/prometheus.ts @@ -16,12 +16,6 @@ import { Matcher } from '../types'; import { labelMatchersToString } from '../parser'; import LRUCache from 'lru-cache'; -const apiPrefix = '/api/v1'; -const labelsEndpoint = apiPrefix + '/labels'; -const labelValuesEndpoint = apiPrefix + '/label/:name/values'; -const seriesEndpoint = apiPrefix + '/series'; -const metricMetadataEndpoint = apiPrefix + '/metadata'; - export interface MetricMetadata { type: string; help: string; @@ -61,6 +55,7 @@ export interface PrometheusConfig { // cache will allow user to change the configuration of the cached Prometheus client (which is used by default) cache?: CacheConfig; httpMethod?: 'POST' | 'GET'; + apiPrefix?: string; } interface APIResponse { @@ -83,6 +78,7 @@ export class HTTPPrometheusClient implements PrometheusClient { // eslint-disable-next-line @typescript-eslint/no-explicit-any private readonly errorHandler?: (error: any) => void; private readonly httpMethod: 'POST' | 'GET' = 'POST'; + private readonly apiPrefix: string = '/api/v1'; // For some reason, just assigning via "= fetch" here does not end up executing fetch correctly // when calling it, thus the indirection via another function wrapper. private readonly fetchFn: FetchFn = (input: RequestInfo, init?: RequestInit): Promise => fetch(input, init); @@ -99,6 +95,9 @@ export class HTTPPrometheusClient implements PrometheusClient { if (config.httpMethod) { this.httpMethod = config.httpMethod; } + if (config.apiPrefix) { + this.apiPrefix = config.apiPrefix; + } } labelNames(metricName?: string): Promise { @@ -106,7 +105,7 @@ export class HTTPPrometheusClient implements PrometheusClient { const start = new Date(end.getTime() - this.lookbackInterval); if (metricName === undefined || metricName === '') { const request = this.buildRequest( - labelsEndpoint, + this.labelsEndpoint(), new URLSearchParams({ start: start.toISOString(), end: end.toISOString(), @@ -150,7 +149,7 @@ export class HTTPPrometheusClient implements PrometheusClient { end: end.toISOString(), }); // See https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values - return this.fetchAPI(`${labelValuesEndpoint.replace(/:name/gi, labelName)}?${params}`).catch((error) => { + return this.fetchAPI(`${this.labelValuesEndpoint().replace(/:name/gi, labelName)}?${params}`).catch((error) => { if (this.errorHandler) { this.errorHandler(error); } @@ -175,7 +174,7 @@ export class HTTPPrometheusClient implements PrometheusClient { } metricMetadata(): Promise> { - return this.fetchAPI>(metricMetadataEndpoint).catch((error) => { + return this.fetchAPI>(this.metricMetadataEndpoint()).catch((error) => { if (this.errorHandler) { this.errorHandler(error); } @@ -187,7 +186,7 @@ export class HTTPPrometheusClient implements PrometheusClient { const end = new Date(); const start = new Date(end.getTime() - this.lookbackInterval); const request = this.buildRequest( - seriesEndpoint, + this.seriesEndpoint(), new URLSearchParams({ start: start.toISOString(), end: end.toISOString(), @@ -239,6 +238,19 @@ export class HTTPPrometheusClient implements PrometheusClient { } return { uri, body }; } + + private labelsEndpoint(): string { + return `${this.apiPrefix}/labels`; + } + private labelValuesEndpoint(): string { + return `${this.apiPrefix}/label/:name/values`; + } + private seriesEndpoint(): string { + return `${this.apiPrefix}/series`; + } + private metricMetadataEndpoint(): string { + return `${this.apiPrefix}/metadata`; + } } class Cache {