From b1636c3f9d3d60328a6ce0ec12dff3c621206996 Mon Sep 17 00:00:00 2001 From: ismail simsek Date: Fri, 23 May 2025 15:18:08 +0200 Subject: [PATCH] Docs: Add some jsdoc style comments to prometheus utf8 support for better clarity (#105862) * add some jsdoc style comments for better clarity * Update utf8_support.ts --- .../grafana-prometheus/src/utf8_support.ts | 71 +++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/packages/grafana-prometheus/src/utf8_support.ts b/packages/grafana-prometheus/src/utf8_support.ts index a9ce776364b..a6c19ff2750 100644 --- a/packages/grafana-prometheus/src/utf8_support.ts +++ b/packages/grafana-prometheus/src/utf8_support.ts @@ -1,3 +1,17 @@ +/** + * Ensures a string is compatible with Prometheus' UTF-8 handling rules. + * + * Prometheus has specific rules for handling UTF-8 strings in metric names and label values: + * - Legacy names (matching pattern [a-zA-Z_:][a-zA-Z0-9_:]*) are used as-is + * - Non-legacy names containing UTF-8 characters must be wrapped in double quotes + * + * @param value - The string to make UTF-8 compatible + * @returns The original string if it's empty or a valid legacy name, otherwise the string wrapped in double quotes + * + * @example + * utf8Support('metric_name') // returns 'metric_name' + * utf8Support('metric-📈') // returns '"metric-📈"' + */ export const utf8Support = (value: string) => { if (value === '') { return value; @@ -9,6 +23,22 @@ export const utf8Support = (value: string) => { return `"${value}"`; }; +/** + * Escapes a string to make it compatible with Prometheus UTF-8 support. + * + * This function converts non-legacy name characters to an escaped format: + * - Underscores are doubled as '__' + * - Valid legacy runes are preserved as-is + * - Invalid code points are replaced with '_FFFD_' + * - Other characters are converted to '_HEX_' format where HEX is the hexadecimal code point + * + * @param value - The string to escape + * @returns An escaped string prefixed with 'U__' that is compatible with Prometheus + * + * @example + * escapeForUtf8Support("my lovely_http.status:sum") // returns U__my_20_lovely__http_2e_status:sum + * escapeForUtf8Support("label with 😱") // returns U__label_20_with_20__1f631_ + */ export const escapeForUtf8Support = (value: string) => { const isLegacyLabel = isValidLegacyName(value); if (isLegacyLabel) { @@ -42,6 +72,16 @@ export const escapeForUtf8Support = (value: string) => { return escaped; }; +/** + * Checks if a string is a valid legacy (the standard) Prometheus metric or label name. + * + * Valid legacy (the standard) names match the pattern [a-zA-Z_:][a-zA-Z0-9_:]* which means: + * - First character must be a letter, underscore, or colon + * - Remaining characters can only be letters, numbers, underscores, or colons + * + * @param name - The string to check + * @returns true if the string is a valid legacy (the standard) name, false otherwise + */ export const isValidLegacyName = (name: string): boolean => { if (name.length === 0) { return false; @@ -57,9 +97,17 @@ export const isValidLegacyName = (name: string): boolean => { return true; }; -// const labelNamePriorToUtf8Support = /^[a-zA-Z_:][a-zA-Z0-9_:]*$/; -// instead of regex we use rune check (converted from prometheus code) -// https://github.com/prometheus/common/blob/main/model/metric.go#L426-L428 +/** + * Checks if a character is valid for a legacy (the standard) Prometheus metric or label name. + * + * This is an implementation of the Prometheus model rune validation logic, which + * determines if a character is allowed in a legacy metric or label name. + * https://github.com/prometheus/common/blob/v0.64.0/model/metric.go#L430-L432 + * + * @param char - The character to check + * @param index - The position of the character in the string + * @returns true if the character is valid at the given position, false otherwise + */ const isValidLegacyRune = (char: string, index: number): boolean => { const codePoint = char.codePointAt(0); if (codePoint === undefined) { @@ -75,11 +123,26 @@ const isValidLegacyRune = (char: string, index: number): boolean => { ); }; +/** + * Validates if a Unicode code point is valid for UTF-8 encoding. + * + * @param codePoint - The Unicode code point to validate + * @returns true if the code point is valid (between 0 and 0x10FFFF), false otherwise + */ const isValidCodePoint = (codePoint: number): boolean => { - // Validate the code point for UTF-8 compliance if needed. return codePoint >= 0 && codePoint <= 0x10ffff; }; +/** + * Wraps each key in a Prometheus filter string with UTF-8 support. + * + * This function processes a filter string (e.g. 'metric="value",name=~"pattern"') + * and applies UTF-8 support to each key while preserving the operators and values. + * It handles quoted values and comma separators correctly. + * + * @param filterStr - The filter string to process + * @returns A new filter string with UTF-8 support applied to the keys + */ export const wrapUtf8Filters = (filterStr: string): string => { const resultArray: string[] = []; const operatorRegex = /(=~|!=|!~|=)/; // NOTE: the order of the operators is important here