type encoderOption … type EncoderOption … // WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder // to include _created lines (See // https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1). // Created timestamps can improve the accuracy of series reset detection, but // come with a bandwidth cost. // // At the time of writing, created timestamp ingestion is still experimental in // Prometheus and need to be enabled with the feature-flag // `--feature-flag=created-timestamp-zero-ingestion`, and breaking changes are // still possible. Therefore, it is recommended to use this feature with caution. func WithCreatedLines() EncoderOption { … } // WithUnit is an EncoderOption enabling a set unit to be written to the output // and to be added to the metric name, if it's not there already, as a suffix. // Without opting in this way, the unit will not be added to the metric name and, // on top of that, the unit will not be passed onto the output, even if it // were declared in the *dto.MetricFamily struct, i.e. even if in.Unit !=nil. func WithUnit() EncoderOption { … } // MetricFamilyToOpenMetrics converts a MetricFamily proto message into the // OpenMetrics text format and writes the resulting lines to 'out'. It returns // the number of bytes written and any error encountered. The output will have // the same order as the input, no further sorting is performed. Furthermore, // this function assumes the input is already sanitized and does not perform any // sanity checks. If the input contains duplicate metrics or invalid metric or // label names, the conversion will result in invalid text format output. // // If metric names conform to the legacy validation pattern, they will be placed // outside the brackets in the traditional way, like `foo{}`. If the metric name // fails the legacy validation check, it will be placed quoted inside the // brackets: `{"foo"}`. As stated above, the input is assumed to be santized and // no error will be thrown in this case. // // Similar to metric names, if label names conform to the legacy validation // pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label // name fails the legacy validation check, it will be quoted: // `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and // no error will be thrown in this case. // // This function fulfills the type 'expfmt.encoder'. // // Note that OpenMetrics requires a final `# EOF` line. Since this function acts // on individual metric families, it is the responsibility of the caller to // append this line to 'out' once all metric families have been written. // Conveniently, this can be done by calling FinalizeOpenMetrics. // // The output should be fully OpenMetrics compliant. However, there are a few // missing features and peculiarities to avoid complications when switching from // Prometheus to OpenMetrics or vice versa: // // - Counters are expected to have the `_total` suffix in their metric name. In // the output, the suffix will be truncated from the `# TYPE`, `# HELP` and `# UNIT` // lines. A counter with a missing `_total` suffix is not an error. However, // its type will be set to `unknown` in that case to avoid invalid OpenMetrics // output. // // - According to the OM specs, the `# UNIT` line is optional, but if populated, // the unit has to be present in the metric name as its suffix: // (see https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#unit). // However, in order to accommodate any potential scenario where such a change in the // metric name is not desirable, the users are here given the choice of either explicitly // opt in, in case they wish for the unit to be included in the output AND in the metric name // as a suffix (see the description of the WithUnit function above), // or not to opt in, in case they don't want for any of that to happen. // // - No support for the following (optional) features: info type, // stateset type, gaugehistogram type. // // - The size of exemplar labels is not checked (i.e. it's possible to create // exemplars that are larger than allowed by the OpenMetrics specification). // // - The value of Counters is not checked. (OpenMetrics doesn't allow counters // with a `NaN` value.) func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...EncoderOption) (written int, err error) { … } // FinalizeOpenMetrics writes the final `# EOF\n` line required by OpenMetrics. func FinalizeOpenMetrics(w io.Writer) (written int, err error) { … } // writeOpenMetricsSample writes a single sample in OpenMetrics text format to // w, given the metric name, the metric proto message itself, optionally an // additional label name with a float64 value (use empty string as label name if // not required), the value (optionally as float64 or uint64, determined by // useIntValue), and optionally an exemplar (use nil if not required). The // function returns the number of bytes written and any error encountered. func writeOpenMetricsSample( w enhancedWriter, name, suffix string, metric *dto.Metric, additionalLabelName string, additionalLabelValue float64, floatValue float64, intValue uint64, useIntValue bool, exemplar *dto.Exemplar, ) (int, error) { … } // writeOpenMetricsNameAndLabelPairs works like writeOpenMetricsSample but // formats the float in OpenMetrics style. func writeOpenMetricsNameAndLabelPairs( w enhancedWriter, name string, in []*dto.LabelPair, additionalLabelName string, additionalLabelValue float64, ) (int, error) { … } // writeOpenMetricsCreated writes the created timestamp for a single time series // following OpenMetrics text format to w, given the metric name, the metric proto // message itself, optionally a suffix to be removed, e.g. '_total' for counters, // an additional label name with a float64 value (use empty string as label name if // not required) and the timestamp that represents the created timestamp. // The function returns the number of bytes written and any error encountered. func writeOpenMetricsCreated(w enhancedWriter, name, suffixToTrim string, metric *dto.Metric, additionalLabelName string, additionalLabelValue float64, createdTimestamp *timestamppb.Timestamp, ) (int, error) { … } // writeExemplar writes the provided exemplar in OpenMetrics format to w. The // function returns the number of bytes written and any error encountered. func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { … } // writeOpenMetricsFloat works like writeFloat but appends ".0" if the resulting // number would otherwise contain neither a "." nor an "e". func writeOpenMetricsFloat(w enhancedWriter, f float64) (int, error) { … } // writeUint is like writeInt just for uint64. func writeUint(w enhancedWriter, u uint64) (int, error) { … }