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
This commit is contained in:
ismail simsek
2025-05-23 16:18:08 +03:00
committed by GitHub
parent fa98a96e5d
commit b1636c3f9d
@@ -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