provide a way to override the apiPrefix in codemirror prom client + cleanup readme (#9384)

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>
This commit is contained in:
Augustin Husson 2021-09-24 07:52:50 +02:00 committed by GitHub
parent acee8c8a88
commit 7bcca77340
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 29 deletions

View file

@ -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' } }) 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 ###### Cache
The default client has an embedded cache that is used to store the different metrics and labels retrieved from a remote 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 ### 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) * [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) * [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) 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). 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 ## License
[MIT](./LICENSE) [MIT](./LICENSE)

View file

@ -16,12 +16,6 @@ import { Matcher } from '../types';
import { labelMatchersToString } from '../parser'; import { labelMatchersToString } from '../parser';
import LRUCache from 'lru-cache'; 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 { export interface MetricMetadata {
type: string; type: string;
help: 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 will allow user to change the configuration of the cached Prometheus client (which is used by default)
cache?: CacheConfig; cache?: CacheConfig;
httpMethod?: 'POST' | 'GET'; httpMethod?: 'POST' | 'GET';
apiPrefix?: string;
} }
interface APIResponse<T> { interface APIResponse<T> {
@ -83,6 +78,7 @@ export class HTTPPrometheusClient implements PrometheusClient {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
private readonly errorHandler?: (error: any) => void; private readonly errorHandler?: (error: any) => void;
private readonly httpMethod: 'POST' | 'GET' = 'POST'; 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 // 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. // when calling it, thus the indirection via another function wrapper.
private readonly fetchFn: FetchFn = (input: RequestInfo, init?: RequestInit): Promise<Response> => fetch(input, init); private readonly fetchFn: FetchFn = (input: RequestInfo, init?: RequestInit): Promise<Response> => fetch(input, init);
@ -99,6 +95,9 @@ export class HTTPPrometheusClient implements PrometheusClient {
if (config.httpMethod) { if (config.httpMethod) {
this.httpMethod = config.httpMethod; this.httpMethod = config.httpMethod;
} }
if (config.apiPrefix) {
this.apiPrefix = config.apiPrefix;
}
} }
labelNames(metricName?: string): Promise<string[]> { labelNames(metricName?: string): Promise<string[]> {
@ -106,7 +105,7 @@ export class HTTPPrometheusClient implements PrometheusClient {
const start = new Date(end.getTime() - this.lookbackInterval); const start = new Date(end.getTime() - this.lookbackInterval);
if (metricName === undefined || metricName === '') { if (metricName === undefined || metricName === '') {
const request = this.buildRequest( const request = this.buildRequest(
labelsEndpoint, this.labelsEndpoint(),
new URLSearchParams({ new URLSearchParams({
start: start.toISOString(), start: start.toISOString(),
end: end.toISOString(), end: end.toISOString(),
@ -150,7 +149,7 @@ export class HTTPPrometheusClient implements PrometheusClient {
end: end.toISOString(), end: end.toISOString(),
}); });
// See https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values // See https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values
return this.fetchAPI<string[]>(`${labelValuesEndpoint.replace(/:name/gi, labelName)}?${params}`).catch((error) => { return this.fetchAPI<string[]>(`${this.labelValuesEndpoint().replace(/:name/gi, labelName)}?${params}`).catch((error) => {
if (this.errorHandler) { if (this.errorHandler) {
this.errorHandler(error); this.errorHandler(error);
} }
@ -175,7 +174,7 @@ export class HTTPPrometheusClient implements PrometheusClient {
} }
metricMetadata(): Promise<Record<string, MetricMetadata[]>> { metricMetadata(): Promise<Record<string, MetricMetadata[]>> {
return this.fetchAPI<Record<string, MetricMetadata[]>>(metricMetadataEndpoint).catch((error) => { return this.fetchAPI<Record<string, MetricMetadata[]>>(this.metricMetadataEndpoint()).catch((error) => {
if (this.errorHandler) { if (this.errorHandler) {
this.errorHandler(error); this.errorHandler(error);
} }
@ -187,7 +186,7 @@ export class HTTPPrometheusClient implements PrometheusClient {
const end = new Date(); const end = new Date();
const start = new Date(end.getTime() - this.lookbackInterval); const start = new Date(end.getTime() - this.lookbackInterval);
const request = this.buildRequest( const request = this.buildRequest(
seriesEndpoint, this.seriesEndpoint(),
new URLSearchParams({ new URLSearchParams({
start: start.toISOString(), start: start.toISOString(),
end: end.toISOString(), end: end.toISOString(),
@ -239,6 +238,19 @@ export class HTTPPrometheusClient implements PrometheusClient {
} }
return { uri, body }; 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 { class Cache {