Chore: Improve prometheus language provider documentation (#108661)

* improve documentation

* fix

* betterer
This commit is contained in:
ismail simsek
2025-07-25 09:45:09 +00:00
committed by GitHub
parent c21617a446
commit fa8b631a87
4 changed files with 114 additions and 19 deletions
+2 -1
View File
@@ -453,7 +453,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"]
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"]
],
"packages/grafana-prometheus/src/language_utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
@@ -515,19 +515,6 @@ export default class PromQlLanguageProvider extends LanguageProvider implements
};
}
export interface PrometheusLanguageProviderInterface
extends PrometheusBaseLanguageProvider,
PrometheusLegacyLanguageProvider {
retrieveMetricsMetadata: () => PromMetricsMetadata;
retrieveHistogramMetrics: () => string[];
retrieveMetrics: () => string[];
retrieveLabelKeys: () => string[];
queryMetricsMetadata: (limit?: number) => Promise<PromMetricsMetadata>;
queryLabelKeys: (timeRange: TimeRange, match?: string, limit?: number) => Promise<string[]>;
queryLabelValues: (timeRange: TimeRange, labelKey: string, match?: string, limit?: number) => Promise<string[]>;
}
/**
* Modern implementation of the Prometheus language provider that abstracts API endpoint selection.
*
@@ -535,12 +522,73 @@ export interface PrometheusLanguageProviderInterface
* - Automatically selects the most efficient API endpoint based on Prometheus version and configuration
* - Supports both labels and series endpoints for backward compatibility
* - Handles match[] parameters for filtering time series data
* - Implements automatic request limiting (default: 40_000 series)
* - Implements automatic request limiting (default: 40,000 series if not configured otherwise)
* - Provides unified interface for both modern and legacy Prometheus versions
* - Provides caching mechanism based on time range, limit, and match parameters
*
* @see LabelsApiClient For modern Prometheus versions using the labels API
* @see SeriesApiClient For legacy Prometheus versions using the series API
*/
export interface PrometheusLanguageProviderInterface
extends PrometheusBaseLanguageProvider,
PrometheusLegacyLanguageProvider {
/**
* Initializes the language provider by fetching metrics, label keys, and metrics metadata using Resource Clients.
* All calls use the limit parameter from datasource configuration (default: 40,000 if not set).
*
* For backward compatibility, it calls _backwardCompatibleStart.
* Some places still rely on deprecated fields. Until we replace them, we need _backwardCompatibleStart method.
*/
start: (timeRange?: TimeRange) => Promise<any[]>;
/**
* Returns already cached metrics metadata including type and help information.
* If there is no cached metadata, it returns an empty object.
* To get fresh metadata, use queryMetricsMetadata instead.
*/
retrieveMetricsMetadata: () => PromMetricsMetadata;
/**
* Returns already cached list of histogram metrics (identified by '_bucket' suffix).
* If there are no cached histogram metrics, it returns an empty array.
*/
retrieveHistogramMetrics: () => string[];
/**
* Returns already cached list of all available metric names.
* If there are no cached metrics, it returns an empty array.
*/
retrieveMetrics: () => string[];
/**
* Returns already cached list of available label keys.
* If there are no cached label keys, it returns an empty array.
*/
retrieveLabelKeys: () => string[];
/**
* Fetches fresh metrics metadata from Prometheus with optional limit.
* Uses datasource's default limit if not specified.
*/
queryMetricsMetadata: (limit?: number) => Promise<PromMetricsMetadata>;
/**
* Queries Prometheus for label keys within time range, optionally filtered by match selector.
* Automatically selects labels or series endpoint based on datasource configuration.
* If no limit is provided, uses the datasource's default limit configuration.
* Use zero (0) to fetch all label keys, but this might return huge amounts of data.
*/
queryLabelKeys: (timeRange: TimeRange, match?: string, limit?: number) => Promise<string[]>;
/**
* Queries Prometheus for values of a specific label key, optionally filtered by match selector.
* Automatically selects labels or series endpoint based on datasource configuration.
* If no limit is provided, uses the datasource's default limit configuration.
* Use zero (0) to fetch all label values, but this might return huge amounts of data.
*/
queryLabelValues: (timeRange: TimeRange, labelKey: string, match?: string, limit?: number) => Promise<string[]>;
}
export class PrometheusLanguageProvider extends PromQlLanguageProvider implements PrometheusLanguageProviderInterface {
private _metricsMetadata?: PromMetricsMetadata;
private _resourceClient?: ResourceApiClient;
@@ -836,6 +836,11 @@ describe('BaseResourceClient', () => {
constructor() {
super(mockRequest, mockDatasource);
}
// Expose protected method for testing
public testGetEffectiveLimit(limit?: number): number {
return this.getEffectiveLimit(limit);
}
}
let client: TestBaseResourceClient;
@@ -845,6 +850,26 @@ describe('BaseResourceClient', () => {
client = new TestBaseResourceClient();
});
describe('getEffectiveLimit', () => {
it('should return the provided limit when a number is given', () => {
expect(client.testGetEffectiveLimit(1000)).toBe(1000);
expect(client.testGetEffectiveLimit(500)).toBe(500);
expect(client.testGetEffectiveLimit(100000)).toBe(100000);
});
it('should return 0 when limit is 0 (valid for unlimited)', () => {
expect(client.testGetEffectiveLimit(0)).toBe(0);
});
it('should return datasource seriesLimit when limit is undefined', () => {
expect(client.testGetEffectiveLimit(undefined)).toBe(DEFAULT_SERIES_LIMIT);
});
it('should return datasource seriesLimit when no limit is provided', () => {
expect(client.testGetEffectiveLimit()).toBe(DEFAULT_SERIES_LIMIT);
});
});
describe('querySeries', () => {
const mockTimeRange = {
from: dateTime(1681300292392),
@@ -43,8 +43,16 @@ export abstract class BaseResourceClient {
this.seriesLimit = this.datasource.seriesLimit;
}
/**
* Returns the effective limit to use for API requests.
* Uses the provided limit if specified, otherwise falls back to the datasource's configured series limit.
* When zero is provided, it returns zero (which means no limit in Prometheus API).
*
* @param {number} [limit] - Optional limit parameter from the API call
* @returns {number} The limit to use - either the provided limit or datasource's default series limit
*/
protected getEffectiveLimit(limit?: number): number {
return limit || this.seriesLimit;
return limit ?? this.seriesLimit;
}
protected async requestLabels(
@@ -93,10 +101,23 @@ export class LabelsApiClient extends BaseResourceClient implements ResourceApiCl
this.labelKeys = await this.queryLabelKeys(timeRange);
};
public queryMetrics = async (timeRange: TimeRange): Promise<{ metrics: string[]; histogramMetrics: string[] }> => {
this.metrics = await this.queryLabelValues(timeRange, METRIC_LABEL);
/**
* Fetches all available metrics from Prometheus using the labels values endpoint for __name__.
* Also processes and identifies histogram metrics (those ending with '_bucket').
* Results are cached and stored in the client instance for future use.
*
* @param {TimeRange} timeRange - Time range to search for metrics
* @param {number} [limit] - Optional maximum number of metrics to return, uses datasource default if not specified
* @returns {Promise<{metrics: string[], histogramMetrics: string[]}>} Object containing all metrics and filtered histogram metrics
*/
public queryMetrics = async (
timeRange: TimeRange,
limit?: number
): Promise<{ metrics: string[]; histogramMetrics: string[] }> => {
const effectiveLimit = this.getEffectiveLimit(limit);
this.metrics = await this.queryLabelValues(timeRange, METRIC_LABEL, undefined, effectiveLimit);
this.histogramMetrics = processHistogramMetrics(this.metrics);
this._cache.setLabelValues(timeRange, undefined, DEFAULT_SERIES_LIMIT, this.metrics);
this._cache.setLabelValues(timeRange, undefined, effectiveLimit, this.metrics);
return { metrics: this.metrics, histogramMetrics: this.histogramMetrics };
};