Repository: prometheus/prometheus
File: storage/remote/otlptranslator/prometheus/normalize_name.go (Go)

Code before:
	var metricName string
	if !allowUTF8 {
		// Regexp for metric name characters that should be replaced with _.
		invalidMetricCharRE := regexp.MustCompile(`[^a-zA-Z0-9:_]`)

		// Simple case (no full normalization, no units, etc.).
		metricName = strings.Join(strings.FieldsFunc(metric.Name(), func(r rune) bool {
			return invalidMetricCharRE.MatchString(string(r))
		}), "_")
	} else {
		metricName = metric.Name()
	}

	// Namespace?
	if namespace != "" {
		return namespace + "_" + metricName
	}

	// Metric name starts with a digit and utf8 not allowed? Prefix it with an underscore.
	if metricName != "" && unicode.IsDigit(rune(metricName[0])) && !allowUTF8 {
		metricName = "_" + metricName
	}

	return metricName
}

// Build a normalized name for the specified metric.
func normalizeName(metric pmetric.Metric, namespace string, allowUTF8 bool) string {
	var nameTokens []string
	var separators []string
	if !allowUTF8 {
		nonTokenMetricCharRE := regexp.MustCompile(`[^a-zA-Z0-9:]`)
		// Split metric name into "tokens" (of supported metric name runes).
		// Note that this has the side effect of replacing multiple consecutive underscores with a single underscore.
		// This is part of the OTel to Prometheus specification: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
		nameTokens = strings.FieldsFunc(
			metric.Name(),
			func(r rune) bool { return nonTokenMetricCharRE.MatchString(string(r)) },
		)
	} else {
		translationFunc := func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != ':' }
		// Split metric name into "tokens" (of supported metric name runes).
		nameTokens, separators = fieldsFunc(metric.Name(), translationFunc)
	}

	// Split unit at the '/' if any
	unitTokens := strings.SplitN(metric.Unit(), "/", 2)

	// Main unit
	// Append if not blank, doesn't contain '{}', and is not present in metric name already
	if len(unitTokens) > 0 {

Review comment (performance):
Noting in passing: this (pulling the initialization out to start of program) should also be done for the other two `regexp.MustCompile` in this file.  Check that relevant benchmarks exist, since they ought to be showing a performance hit. 

Code after:
	if !allowUTF8 {
		// Regexp for metric name characters that should be replaced with _.
		invalidMetricCharRE := regexp.MustCompile(`[^a-zA-Z0-9:_]`)

		// Simple case (no full normalization, no units, etc.).
		metricName = strings.Join(strings.FieldsFunc(metric.Name(), func(r rune) bool {
			return invalidMetricCharRE.MatchString(string(r))
		}), "_")
	} else {
		metricName = metric.Name()
	}

	// Namespace?
	if namespace != "" {
		return namespace + "_" + metricName
	}

	// Metric name starts with a digit and utf8 not allowed? Prefix it with an underscore.
	if metricName != "" && unicode.IsDigit(rune(metricName[0])) && !allowUTF8 {
		metricName = "_" + metricName
	}

	return metricName
}

var nonMetricNameCharRE = regexp.MustCompile(`[^a-zA-Z0-9:]`)

// Build a normalized name for the specified metric.
func normalizeName(metric pmetric.Metric, namespace string, allowUTF8 bool) string {
	var nameTokens []string
	var separators []string
	if !allowUTF8 {
		// Split metric name into "tokens" (of supported metric name runes).
		// Note that this has the side effect of replacing multiple consecutive underscores with a single underscore.
		// This is part of the OTel to Prometheus specification: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
		nameTokens = strings.FieldsFunc(
			metric.Name(),
			func(r rune) bool { return nonMetricNameCharRE.MatchString(string(r)) },
		)
	} else {
		translationFunc := func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != ':' }
		// Split metric name into "tokens" (of supported metric name runes).
		nameTokens, separators = fieldsFunc(metric.Name(), translationFunc)
	}

	// Split unit at the '/' if any
	unitTokens := strings.SplitN(metric.Unit(), "/", 2)

	// Main unit
	// Append if not blank, doesn't contain '{}', and is not present in metric name already
	if len(unitTokens) > 0 {