| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9e3eb6c commit 3586355
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -345,10 +345,10 @@ def choose_encoder(accept_header: str) -> Tuple[Callable[[CollectorRegistry], by | |||
| 345 | 345 | # Only return an escaping header if we have a good version and | |
| 346 | 346 | # mimetype. | |
| 347 | 347 | if not version: | |
| 348 | - return (partial(openmetrics.generate_latest, escaping=openmetrics.UNDERSCORES), openmetrics.CONTENT_TYPE_LATEST) | ||
| 348 | + return (partial(openmetrics.generate_latest, escaping=openmetrics.UNDERSCORES, version="1.0.0"), openmetrics.CONTENT_TYPE_LATEST) | ||
| 349 | 349 | if version and Version(version) >= Version('1.0.0'): | |
| 350 | - return (partial(openmetrics.generate_latest, escaping=escaping), | ||
| 351 | - openmetrics.CONTENT_TYPE_LATEST + '; escaping=' + str(escaping)) | ||
| 350 | + return (partial(openmetrics.generate_latest, escaping=escaping, version=version), | ||
| 351 | + f'application/openmetrics-text; version={version}; charset=utf-8; escaping=' + str(escaping)) | ||
| 352 | 352 | elif accepted.split(';')[0].strip() == 'text/plain': | |
| 353 | 353 | toks = accepted.split(';') | |
| 354 | 354 | version = _get_version(toks) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,13 +4,17 @@ | |||
| 4 | 4 | from sys import maxunicode | |
| 5 | 5 | from typing import Callable | |
| 6 | 6 | ||
| 7 | + from packaging.version import Version | ||
| 8 | + | ||
| 7 | 9 | from ..utils import floatToGoString | |
| 8 | 10 | from ..validation import ( | |
| 9 | 11 | _is_valid_legacy_labelname, _is_valid_legacy_metric_name, | |
| 10 | 12 | ) | |
| 11 | 13 | ||
| 12 | 14 | CONTENT_TYPE_LATEST = 'application/openmetrics-text; version=1.0.0; charset=utf-8' | |
| 13 | - """Content type of the latest OpenMetrics text format""" | ||
| 15 | + """Content type of the latest OpenMetrics 1.0 text format""" | ||
| 16 | + CONTENT_TYPE_LATEST_2_0 = 'application/openmetrics-text; version=2.0.0; charset=utf-8' | ||
| 17 | + """Content type of the OpenMetrics 2.0 text format""" | ||
| 14 | 18 | ESCAPING_HEADER_TAG = 'escaping' | |
| 15 | 19 | ||
| 16 | 20 | ||
@@ -53,7 +57,7 @@ def _compose_exemplar_string(metric, sample, exemplar): | |||
| 53 | 57 | return exemplarstr | |
| 54 | 58 | ||
| 55 | 59 | ||
| 56 | - def generate_latest(registry, escaping=UNDERSCORES): | ||
| 60 | + def generate_latest(registry, escaping=UNDERSCORES, version="1.0.0"): | ||
| 57 | 61 | '''Returns the metrics from the registry in latest text format as a string.''' | |
| 58 | 62 | output = [] | |
| 59 | 63 | for metric in registry.collect(): | |
@@ -89,6 +93,10 @@ def generate_latest(registry, escaping=UNDERSCORES): | |||
| 89 | 93 | if s.timestamp is not None: | |
| 90 | 94 | timestamp = f' {s.timestamp}' | |
| 91 | 95 | ||
| 96 | + # Skip native histogram samples entirely if version < 2.0.0 | ||
| 97 | + if s.native_histogram and Version(version) < Version('2.0.0'): | ||
| 98 | + continue | ||
| 99 | + | ||
| 92 | 100 | native_histogram = '' | |
| 93 | 101 | negative_spans = '' | |
| 94 | 102 | negative_deltas = '' | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -83,7 +83,7 @@ def test_summary(self) -> None: | |||
| 83 | 83 | ss_sum{a="c",b="d"} 17.0 | |
| 84 | 84 | ss_created{a="c",b="d"} 123.456 | |
| 85 | 85 | # EOF | |
| 86 | - """, generate_latest(self.registry)) | ||
| 86 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 87 | 87 | ||
| 88 | 88 | def test_histogram(self) -> None: | |
| 89 | 89 | s = Histogram('hh', 'A histogram', registry=self.registry) | |
@@ -109,7 +109,7 @@ def test_histogram(self) -> None: | |||
| 109 | 109 | hh_sum 0.05 | |
| 110 | 110 | hh_created 123.456 | |
| 111 | 111 | # EOF | |
| 112 | - """, generate_latest(self.registry)) | ||
| 112 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 113 | 113 | ||
| 114 | 114 | ||
| 115 | 115 | def test_native_histogram(self) -> None: | |
@@ -120,7 +120,7 @@ def test_native_histogram(self) -> None: | |||
| 120 | 120 | # TYPE nh histogram | |
| 121 | 121 | nh {count:24,sum:100,schema:0,zero_threshold:0.001,zero_count:4,negative_spans:[0:2,1:2],negative_deltas:[2,1,-2,3],positive_spans:[0:2,1:2],positive_deltas:[2,1,-3,3]} | |
| 122 | 122 | # EOF | |
| 123 | - """, generate_latest(self.registry)) | ||
| 123 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 124 | 124 | ||
| 125 | 125 | def test_nh_histogram_with_exemplars(self) -> None: | |
| 126 | 126 | hfm = HistogramMetricFamily("nh", "nh") | |
@@ -130,7 +130,7 @@ def test_nh_histogram_with_exemplars(self) -> None: | |||
| 130 | 130 | # TYPE nh histogram | |
| 131 | 131 | nh {count:24,sum:100,schema:0,zero_threshold:0.001,zero_count:4,negative_spans:[0:2,1:2],negative_deltas:[2,1,-2,3],positive_spans:[0:2,1:2],positive_deltas:[2,1,-3,3]} # {trace_id="KOO5S4vxi0o"} 0.67 # {trace_id="oHg5SJYRHA0"} 9.8 1520879607.789 | |
| 132 | 132 | # EOF | |
| 133 | - """, generate_latest(self.registry)) | ||
| 133 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 134 | 134 | ||
| 135 | 135 | def test_nh_no_observation(self) -> None: | |
| 136 | 136 | hfm = HistogramMetricFamily("nhnoobs", "nhnoobs") | |
@@ -140,7 +140,7 @@ def test_nh_no_observation(self) -> None: | |||
| 140 | 140 | # TYPE nhnoobs histogram | |
| 141 | 141 | nhnoobs {count:0,sum:0,schema:3,zero_threshold:2.938735877055719e-39,zero_count:0} | |
| 142 | 142 | # EOF | |
| 143 | - """, generate_latest(self.registry)) | ||
| 143 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 144 | 144 | ||
| 145 | 145 | ||
| 146 | 146 | def test_nh_longer_spans(self) -> None: | |
@@ -151,7 +151,7 @@ def test_nh_longer_spans(self) -> None: | |||
| 151 | 151 | # TYPE nhsp histogram | |
| 152 | 152 | nhsp {count:4,sum:6,schema:3,zero_threshold:2.938735877055719e-39,zero_count:1,positive_spans:[0:1,7:1,4:1],positive_deltas:[1,0,0]} | |
| 153 | 153 | # EOF | |
| 154 | - """, generate_latest(self.registry)) | ||
| 154 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 155 | 155 | ||
| 156 | 156 | def test_native_histogram_utf8(self) -> None: | |
| 157 | 157 | hfm = HistogramMetricFamily("native{histogram", "Is a basic example of a native histogram") | |
@@ -161,7 +161,7 @@ def test_native_histogram_utf8(self) -> None: | |||
| 161 | 161 | # TYPE "native{histogram" histogram | |
| 162 | 162 | {"native{histogram"} {count:24,sum:100,schema:0,zero_threshold:0.001,zero_count:4,negative_spans:[0:2,1:2],negative_deltas:[2,1,-2,3],positive_spans:[0:2,1:2],positive_deltas:[2,1,-3,3]} | |
| 163 | 163 | # EOF | |
| 164 | - """, generate_latest(self.registry, ALLOWUTF8)) | ||
| 164 | + """, generate_latest(self.registry, ALLOWUTF8, version="2.0.0")) | ||
| 165 | 165 | ||
| 166 | 166 | def test_native_histogram_utf8_stress(self) -> None: | |
| 167 | 167 | hfm = HistogramMetricFamily("native{histogram", "Is a basic example of a native histogram") | |
@@ -171,7 +171,7 @@ def test_native_histogram_utf8_stress(self) -> None: | |||
| 171 | 171 | # TYPE "native{histogram" histogram | |
| 172 | 172 | {"native{histogram", "xx{} # {}"=" EOF # {}}}"} {count:24,sum:100,schema:0,zero_threshold:0.001,zero_count:4,negative_spans:[0:2,1:2],negative_deltas:[2,1,-2,3],positive_spans:[0:2,1:2],positive_deltas:[2,1,-3,3]} | |
| 173 | 173 | # EOF | |
| 174 | - """, generate_latest(self.registry, ALLOWUTF8)) | ||
| 174 | + """, generate_latest(self.registry, ALLOWUTF8, version="2.0.0")) | ||
| 175 | 175 | ||
| 176 | 176 | def test_native_histogram_with_labels(self) -> None: | |
| 177 | 177 | hfm = HistogramMetricFamily("hist_w_labels", "Is a basic example of a native histogram with labels") | |
@@ -181,7 +181,7 @@ def test_native_histogram_with_labels(self) -> None: | |||
| 181 | 181 | # TYPE hist_w_labels histogram | |
| 182 | 182 | hist_w_labels{baz="qux",foo="bar"} {count:24,sum:100,schema:0,zero_threshold:0.001,zero_count:4,negative_spans:[0:2,1:2],negative_deltas:[2,1,-2,3],positive_spans:[0:2,1:2],positive_deltas:[2,1,-3,3]} | |
| 183 | 183 | # EOF | |
| 184 | - """, generate_latest(self.registry)) | ||
| 184 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 185 | 185 | ||
| 186 | 186 | def test_native_histogram_with_labels_utf8(self) -> None: | |
| 187 | 187 | hfm = HistogramMetricFamily("hist.w.labels", "Is a basic example of a native histogram with labels") | |
@@ -191,7 +191,7 @@ def test_native_histogram_with_labels_utf8(self) -> None: | |||
| 191 | 191 | # TYPE "hist.w.labels" histogram | |
| 192 | 192 | {"hist.w.labels", baz="qux",foo="bar"} {count:24,sum:100,schema:0,zero_threshold:0.001,zero_count:4,negative_spans:[0:2,1:2],negative_deltas:[2,1,-2,3],positive_spans:[0:2,1:2],positive_deltas:[2,1,-3,3]} | |
| 193 | 193 | # EOF | |
| 194 | - """, generate_latest(self.registry, ALLOWUTF8)) | ||
| 194 | + """, generate_latest(self.registry, ALLOWUTF8, version="2.0.0")) | ||
| 195 | 195 | ||
| 196 | 196 | def test_native_histogram_with_classic_histogram(self) -> None: | |
| 197 | 197 | hfm = HistogramMetricFamily("hist_w_classic", "Is a basic example of a native histogram coexisting with a classic histogram") | |
@@ -209,7 +209,7 @@ def test_native_histogram_with_classic_histogram(self) -> None: | |||
| 209 | 209 | hist_w_classic_count{foo="bar"} 24.0 | |
| 210 | 210 | hist_w_classic_sum{foo="bar"} 100.0 | |
| 211 | 211 | # EOF | |
| 212 | - """, generate_latest(self.registry)) | ||
| 212 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 213 | 213 | ||
| 214 | 214 | def test_native_plus_classic_histogram_two_labelsets(self) -> None: | |
| 215 | 215 | hfm = HistogramMetricFamily("hist_w_classic_two_sets", "Is an example of a native histogram plus a classic histogram with two label sets") | |
@@ -237,7 +237,33 @@ def test_native_plus_classic_histogram_two_labelsets(self) -> None: | |||
| 237 | 237 | hist_w_classic_two_sets_count{foo="baz"} 24.0 | |
| 238 | 238 | hist_w_classic_two_sets_sum{foo="baz"} 100.0 | |
| 239 | 239 | # EOF | |
| 240 | - """, generate_latest(self.registry)) | ||
| 240 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 241 | + | ||
| 242 | + def test_native_plus_classic_histogram_two_labelsets_OM_1(self) -> None: | ||
| 243 | + hfm = HistogramMetricFamily("hist_w_classic_two_sets", "Is an example of a native histogram plus a classic histogram with two label sets in OM 1.0.0") | ||
| 244 | + hfm.add_sample("hist_w_classic_two_sets", {"foo": "bar"}, 0, None, None, NativeHistogram(24, 100, 0, 0.001, 4, (BucketSpan(0, 2), BucketSpan(1, 2)), (BucketSpan(0, 2), BucketSpan(1, 2)), (2, 1, -3, 3), (2, 1, -2, 3))) | ||
| 245 | + hfm.add_sample("hist_w_classic_two_sets_bucket", {"foo": "bar", "le": "0.001"}, 4.0, None, None, None) | ||
| 246 | + hfm.add_sample("hist_w_classic_two_sets_bucket", {"foo": "bar", "le": "+Inf"}, 24.0, None, None, None) | ||
| 247 | + hfm.add_sample("hist_w_classic_two_sets_count", {"foo": "bar"}, 24.0, None, None, None) | ||
| 248 | + hfm.add_sample("hist_w_classic_two_sets_sum", {"foo": "bar"}, 100.0, None, None, None) | ||
| 249 | + hfm.add_sample("hist_w_classic_two_sets", {"foo": "baz"}, 0, None, None, NativeHistogram(24, 100, 0, 0.001, 4, (BucketSpan(0, 2), BucketSpan(1, 2)), (BucketSpan(0, 2), BucketSpan(1, 2)), (2, 1, -3, 3), (2, 1, -2, 3))) | ||
| 250 | + hfm.add_sample("hist_w_classic_two_sets_bucket", {"foo": "baz", "le": "0.001"}, 4.0, None, None, None) | ||
| 251 | + hfm.add_sample("hist_w_classic_two_sets_bucket", {"foo": "baz", "le": "+Inf"}, 24.0, None, None, None) | ||
| 252 | + hfm.add_sample("hist_w_classic_two_sets_count", {"foo": "baz"}, 24.0, None, None, None) | ||
| 253 | + hfm.add_sample("hist_w_classic_two_sets_sum", {"foo": "baz"}, 100.0, None, None, None) | ||
| 254 | + self.custom_collector(hfm) | ||
| 255 | + self.assertEqual(b"""# HELP hist_w_classic_two_sets Is an example of a native histogram plus a classic histogram with two label sets in OM 1.0.0 | ||
| 256 | + # TYPE hist_w_classic_two_sets histogram | ||
| 257 | + hist_w_classic_two_sets_bucket{foo="bar",le="0.001"} 4.0 | ||
| 258 | + hist_w_classic_two_sets_bucket{foo="bar",le="+Inf"} 24.0 | ||
| 259 | + hist_w_classic_two_sets_count{foo="bar"} 24.0 | ||
| 260 | + hist_w_classic_two_sets_sum{foo="bar"} 100.0 | ||
| 261 | + hist_w_classic_two_sets_bucket{foo="baz",le="0.001"} 4.0 | ||
| 262 | + hist_w_classic_two_sets_bucket{foo="baz",le="+Inf"} 24.0 | ||
| 263 | + hist_w_classic_two_sets_count{foo="baz"} 24.0 | ||
| 264 | + hist_w_classic_two_sets_sum{foo="baz"} 100.0 | ||
| 265 | + # EOF | ||
| 266 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 241 | 267 | ||
| 242 | 268 | def test_histogram_negative_buckets(self) -> None: | |
| 243 | 269 | s = Histogram('hh', 'A histogram', buckets=[-1, -0.5, 0, 0.5, 1], registry=self.registry) | |
@@ -253,7 +279,7 @@ def test_histogram_negative_buckets(self) -> None: | |||
| 253 | 279 | hh_count 1.0 | |
| 254 | 280 | hh_created 123.456 | |
| 255 | 281 | # EOF | |
| 256 | - """, generate_latest(self.registry)) | ||
| 282 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 257 | 283 | ||
| 258 | 284 | def test_histogram_exemplar(self) -> None: | |
| 259 | 285 | s = Histogram('hh', 'A histogram', buckets=[1, 2, 3, 4], registry=self.registry) | |
@@ -273,7 +299,7 @@ def test_histogram_exemplar(self) -> None: | |||
| 273 | 299 | hh_sum 8.0 | |
| 274 | 300 | hh_created 123.456 | |
| 275 | 301 | # EOF | |
| 276 | - """, generate_latest(self.registry)) | ||
| 302 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 277 | 303 | ||
| 278 | 304 | def test_counter_exemplar(self) -> None: | |
| 279 | 305 | c = Counter('cc', 'A counter', registry=self.registry) | |
@@ -283,7 +309,7 @@ def test_counter_exemplar(self) -> None: | |||
| 283 | 309 | cc_total 1.0 # {a="b"} 1.0 123.456 | |
| 284 | 310 | cc_created 123.456 | |
| 285 | 311 | # EOF | |
| 286 | - """, generate_latest(self.registry)) | ||
| 312 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 287 | 313 | ||
| 288 | 314 | def test_untyped_exemplar(self) -> None: | |
| 289 | 315 | class MyCollector: | |
@@ -331,7 +357,7 @@ def test_gaugehistogram(self) -> None: | |||
| 331 | 357 | gh_gcount 5.0 | |
| 332 | 358 | gh_gsum 7.0 | |
| 333 | 359 | # EOF | |
| 334 | - """, generate_latest(self.registry)) | ||
| 360 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 335 | 361 | ||
| 336 | 362 | def test_gaugehistogram_negative_buckets(self) -> None: | |
| 337 | 363 | self.custom_collector( | |
@@ -343,7 +369,7 @@ def test_gaugehistogram_negative_buckets(self) -> None: | |||
| 343 | 369 | gh_gcount 5.0 | |
| 344 | 370 | gh_gsum -7.0 | |
| 345 | 371 | # EOF | |
| 346 | - """, generate_latest(self.registry)) | ||
| 372 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 347 | 373 | ||
| 348 | 374 | def test_info(self) -> None: | |
| 349 | 375 | i = Info('ii', 'A info', ['a', 'b'], registry=self.registry) | |
@@ -352,7 +378,7 @@ def test_info(self) -> None: | |||
| 352 | 378 | # TYPE ii info | |
| 353 | 379 | ii_info{a="c",b="d",foo="bar"} 1.0 | |
| 354 | 380 | # EOF | |
| 355 | - """, generate_latest(self.registry)) | ||
| 381 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 356 | 382 | ||
| 357 | 383 | def test_enum(self) -> None: | |
| 358 | 384 | i = Enum('ee', 'An enum', ['a', 'b'], registry=self.registry, states=['foo', 'bar']) | |
@@ -362,7 +388,7 @@ def test_enum(self) -> None: | |||
| 362 | 388 | ee{a="c",b="d",ee="foo"} 0.0 | |
| 363 | 389 | ee{a="c",b="d",ee="bar"} 1.0 | |
| 364 | 390 | # EOF | |
| 365 | - """, generate_latest(self.registry)) | ||
| 391 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 366 | 392 | ||
| 367 | 393 | def test_unicode(self) -> None: | |
| 368 | 394 | c = Counter('cc', '\u4500', ['l'], registry=self.registry) | |
@@ -372,7 +398,7 @@ def test_unicode(self) -> None: | |||
| 372 | 398 | cc_total{l="\xe4\x94\x80"} 1.0 | |
| 373 | 399 | cc_created{l="\xe4\x94\x80"} 123.456 | |
| 374 | 400 | # EOF | |
| 375 | - """, generate_latest(self.registry)) | ||
| 401 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 376 | 402 | ||
| 377 | 403 | def test_escaping(self) -> None: | |
| 378 | 404 | c = Counter('cc', 'A\ncount\\er\"', ['a'], registry=self.registry) | |
@@ -382,7 +408,7 @@ def test_escaping(self) -> None: | |||
| 382 | 408 | cc_total{a="\\\\x\\n\\""} 1.0 | |
| 383 | 409 | cc_created{a="\\\\x\\n\\""} 123.456 | |
| 384 | 410 | # EOF | |
| 385 | - """, generate_latest(self.registry)) | ||
| 411 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 386 | 412 | ||
| 387 | 413 | def test_nonnumber(self) -> None: | |
| 388 | 414 | class MyNumber: | |
@@ -424,7 +450,25 @@ def collect(self): | |||
| 424 | 450 | ts{foo="e"} 0.0 123.000456000 | |
| 425 | 451 | ts{foo="f"} 0.0 123.000000456 | |
| 426 | 452 | # EOF | |
| 427 | - """, generate_latest(self.registry)) | ||
| 453 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 454 | + | ||
| 455 | + def test_native_histogram_version_comparison(self) -> None: | ||
| 456 | + hfm = HistogramMetricFamily("nh_version", "nh version test") | ||
| 457 | + hfm.add_sample("nh_version", {}, 0, None, None, NativeHistogram(5, 10, 0, 0.01, 2, (BucketSpan(0, 1),), (BucketSpan(0, 1),), (3,), (4,))) | ||
| 458 | + self.custom_collector(hfm) | ||
| 459 | + | ||
| 460 | + # Version 1.0.0 should omit native histogram samples entirely | ||
| 461 | + self.assertEqual(b"""# HELP nh_version nh version test | ||
| 462 | + # TYPE nh_version histogram | ||
| 463 | + # EOF | ||
| 464 | + """, generate_latest(self.registry, version="1.0.0")) | ||
| 465 | + | ||
| 466 | + # Version 2.0.0 should emit native histogram format | ||
| 467 | + self.assertEqual(b"""# HELP nh_version nh version test | ||
| 468 | + # TYPE nh_version histogram | ||
| 469 | + nh_version {count:5,sum:10,schema:0,zero_threshold:0.01,zero_count:2,negative_spans:[0:1],negative_deltas:[4],positive_spans:[0:1],positive_deltas:[3]} | ||
| 470 | + # EOF | ||
| 471 | + """, generate_latest(self.registry, version="2.0.0")) | ||
| 428 | 472 | ||
| 429 | 473 | ||
| 430 | 474 | @pytest.mark.parametrize("scenario", [ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments