├── .circleci └── config.yml ├── .editorconfig ├── .github └── ISSUE_TEMPLATE │ └── openmetrics-2-0-proposal.md ├── .gitignore ├── ADOPTERS.md ├── CONTRIBUTORS.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── MAINTAINERS.md ├── Makefile ├── OpenMetrics.md ├── README.md ├── TIMELINE.MD ├── legacy ├── markdown │ ├── metric_exposition_format.md │ └── protobuf_vs_text.md ├── meetings │ └── 2017-10-10--face-to-face.md └── protos │ ├── .gitignore │ ├── Makefile │ ├── bogdandrutu.proto │ ├── brian-brazil.proto │ ├── manolama.proto │ ├── prometheus.proto │ ├── sumeer.proto │ └── tomwilkie.proto ├── netlify.toml ├── proto └── openmetrics_data_model.proto ├── specification ├── OpenMetrics.md ├── OpenMetrics.txt ├── README.md ├── draft-richih-opsawg-openmetrics-00.txt └── draft-richih-opsawg-openmetrics-01.txt ├── src ├── Makefile ├── cmd │ ├── openmetricstest │ │ ├── README.md │ │ ├── main.go │ │ └── validators.go │ ├── openmetricsvalidator │ │ ├── README.md │ │ └── main.go │ └── scrapevalidator │ │ ├── README.md │ │ ├── main.go │ │ └── scrape │ │ ├── loop.go │ │ └── scraper.go ├── go.mod ├── go.sum └── validator │ ├── validator.go │ └── validator_test.go ├── tests ├── implementations │ └── prometheus_client_python_parser │ │ ├── Dockerfile │ │ └── parser.py ├── testdata │ └── parsers │ │ ├── bad_blank_line │ │ ├── metrics │ │ └── test.json │ │ ├── bad_clashing_names_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_clashing_names_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_clashing_names_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_10 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_11 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_12 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_13 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_14 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_15 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_16 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_17 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_18 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_19 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_counter_values_9 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplar_complex_chars │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplar_timestamp_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplar_timestamp_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplar_timestamp_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_10 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_11 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_12 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_9 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_metric_types_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_metric_types_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_metric_types_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_samples_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_samples_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_samples_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_exemplars_on_unallowed_samples_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_10 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_grouping_or_ordering_9 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_help_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_help_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_help_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_help_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_help_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_10 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_11 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_12 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_13 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_14 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_histograms_9 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_info_and_stateset_values_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_info_and_stateset_values_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_invalid_labels_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metadata │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metadata_in_wrong_place_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metadata_in_wrong_place_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metadata_in_wrong_place_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metric_names_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metric_names_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_metric_names_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_equal_or_label_value_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_equal_or_label_value_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_equal_or_label_value_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_equal_or_label_value_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_equal_or_label_value_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_extra_commas_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_extra_commas_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_extra_commas_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_invalid_labels_for_a_type_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_wrong_quotes_on_label_value_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_wrong_quotes_on_label_value_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_or_wrong_quotes_on_label_value_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_value_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_missing_value_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_no_eof │ │ ├── metrics │ │ └── test.json │ │ ├── bad_repeated_metadata_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_repeated_metadata_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_repeated_metadata_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_repeated_metadata_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_stateset_info_values_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_stateset_info_values_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_stateset_info_values_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_stateset_info_values_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_text_after_eof_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_text_after_eof_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_timestamp_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_type_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_unit_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_0 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_1 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_10 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_11 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_12 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_2 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_3 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_4 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_5 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_6 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_7 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_8 │ │ ├── metrics │ │ └── test.json │ │ ├── bad_value_9 │ │ ├── metrics │ │ └── test.json │ │ ├── counter_exemplars │ │ ├── metrics │ │ └── test.json │ │ ├── counter_exemplars_empty_brackets │ │ ├── metrics │ │ └── test.json │ │ ├── counter_unit │ │ ├── metrics │ │ └── test.json │ │ ├── duplicate_timestamps_0 │ │ ├── metrics │ │ └── test.json │ │ ├── duplicate_timestamps_1 │ │ ├── metrics │ │ └── test.json │ │ ├── empty_brackets │ │ ├── metrics │ │ └── test.json │ │ ├── empty_help │ │ ├── metrics │ │ └── test.json │ │ ├── empty_label │ │ ├── metrics │ │ └── test.json │ │ ├── empty_metadata │ │ ├── metrics │ │ └── test.json │ │ ├── escaping │ │ ├── metrics │ │ └── test.json │ │ ├── exemplars_wide_chars │ │ ├── metrics │ │ └── test.json │ │ ├── exemplars_with_hash_in_label_values │ │ ├── metrics │ │ └── test.json │ │ ├── float_gauge │ │ ├── metrics │ │ └── test.json │ │ ├── gaugehistogram_exemplars │ │ ├── metrics │ │ └── test.json │ │ ├── hash_in_label_value │ │ ├── metrics │ │ └── test.json │ │ ├── help_escaping │ │ ├── metrics │ │ └── test.json │ │ ├── histogram_exemplars │ │ ├── metrics │ │ └── test.json │ │ ├── histogram_noncanonical │ │ ├── metrics │ │ └── test.json │ │ ├── info_timestamps │ │ ├── metrics │ │ └── test.json │ │ ├── label_escaping │ │ ├── metrics │ │ └── test.json │ │ ├── labels_and_infinite │ │ ├── metrics │ │ └── test.json │ │ ├── labels_with_curly_braces │ │ ├── metrics │ │ └── test.json │ │ ├── leading_zeros_float_gauge │ │ ├── metrics │ │ └── test.json │ │ ├── leading_zeros_simple_gauge │ │ ├── metrics │ │ └── test.json │ │ ├── nan │ │ ├── metrics │ │ └── test.json │ │ ├── nan_gauge │ │ ├── metrics │ │ └── test.json │ │ ├── negative_bucket_gaugehistogram │ │ ├── metrics │ │ └── test.json │ │ ├── negative_bucket_histogram │ │ ├── metrics │ │ └── test.json │ │ ├── no_metadata │ │ ├── metrics │ │ └── test.json │ │ ├── no_newline_after_eof │ │ ├── metrics │ │ └── test.json │ │ ├── null_byte │ │ ├── metrics │ │ └── test.json │ │ ├── roundtrip │ │ ├── metrics │ │ └── test.json │ │ ├── simple_counter │ │ ├── metrics │ │ └── test.json │ │ ├── simple_gauge │ │ ├── metrics │ │ └── test.json │ │ ├── simple_gaugehistogram │ │ ├── metrics │ │ └── test.json │ │ ├── simple_histogram │ │ ├── metrics │ │ └── test.json │ │ ├── simple_stateset │ │ ├── metrics │ │ └── test.json │ │ ├── simple_summary │ │ ├── metrics │ │ └── test.json │ │ ├── summary_quantiles │ │ ├── metrics │ │ └── test.json │ │ ├── timestamps │ │ ├── metrics │ │ └── test.json │ │ ├── type_help_switched │ │ ├── metrics │ │ └── test.json │ │ ├── uint64_counter │ │ ├── metrics │ │ └── test.json │ │ ├── unit_gauge │ │ ├── metrics │ │ └── test.json │ │ └── untyped │ │ ├── metrics │ │ └── test.json └── urls.txt └── website ├── Makefile ├── README.md ├── assets └── sass │ └── style.sass ├── config.yaml ├── content └── .gitkeep ├── layouts ├── _default │ └── baseof.html ├── index.html └── partials │ ├── cncf.html │ ├── css.html │ ├── hero.html │ └── meta.html ├── package.json ├── static ├── favicon.png ├── fonts │ └── Gotham-Book.otf └── images │ ├── hero-bg.png │ └── logo │ ├── cncf.svg │ ├── logo-rgb.eps │ ├── logo-with-text-rgb.eps │ ├── logo-with-text.ai │ ├── logo-with-text.eps │ ├── logo-with-text.jpg │ ├── logo-with-text.pdf │ ├── logo-with-text.png │ ├── logo-with-text.psd │ ├── logo.ai │ ├── logo.eps │ ├── logo.jpg │ ├── logo.pdf │ ├── logo.png │ └── logo.psd └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2.1 3 | 4 | executors: 5 | golang: 6 | docker: 7 | - image: cimg/go:1.15 8 | ruby: 9 | docker: 10 | - image: ruby:2.7 11 | 12 | jobs: 13 | build: 14 | executor: golang 15 | steps: 16 | - checkout 17 | - run: "cd ./src && make binaries" 18 | unit-test: 19 | executor: golang 20 | steps: 21 | - checkout 22 | - run: "cd ./src && go test ./..." 23 | test-success: 24 | executor: golang 25 | steps: 26 | - checkout 27 | - run: "make test-impl cmd-parser-text=echo" 28 | test-python: 29 | machine: true 30 | steps: 31 | - checkout 32 | - run: "make test_prometheus_client_python_parser" 33 | test-golang: 34 | executor: golang 35 | steps: 36 | - checkout 37 | - run: "make test_open_metrics_validator" 38 | kdrfc: 39 | executor: ruby 40 | steps: 41 | - checkout 42 | - run: bundle install 43 | - run: bundle exec kdrfc specification/OpenMetrics.md 44 | - run: git diff --exit-code 45 | 46 | workflows: 47 | version: 2 48 | openmetrics: 49 | jobs: 50 | - build 51 | - unit-test 52 | - kdrfc 53 | - test-python 54 | - test-golang 55 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | insert_final_newline = true 4 | charset = utf-8 5 | max_line_length = 80 6 | trim_trailing_whitespace = true 7 | 8 | [*.{html,js,sh,sass,scss,md,mmark,yaml}] 9 | indent_style = space 10 | indent_size = 2 11 | 12 | [Makefile] 13 | indent_style = tab 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/openmetrics-2-0-proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: OpenMetrics 2.0 Proposal 3 | about: Propose an enhancement to OpenMetrics for the 2.0 project. 4 | title: 'OM 2.0: ' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Problem Statement 11 | 12 | <--! describe the issue with the spec you are trying to solve --> 13 | 14 | ## Proposed solution 15 | 16 | <--! describe the high-level outline of your proposed solution. If the overall direction is accepted and needs more detail, a complete proposal can be written to https://github.com/prometheus/proposals--> 17 | 18 | ## Alternatives considered 19 | 20 | <--! describe the high-level outline of alternative solutions you considered, and why you chose your proposed solution over these alternatives--> 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS stuff 2 | .DS_Store 3 | 4 | # Node.js artifacts (mostly Sass sources) 5 | node_modules/ 6 | 7 | # Hugo-generated assets 8 | public/ 9 | resources/ 10 | 11 | # Binaries 12 | bin/ 13 | 14 | # Ignore kdrfc working files 15 | OpenMetrics.xml 16 | .refcache/ 17 | 18 | # Ignore kdrfc ruby bundle and vendor 19 | .bundle 20 | vendor/ 21 | 22 | # Golang vendor 23 | src/vendor/ 24 | -------------------------------------------------------------------------------- /ADOPTERS.md: -------------------------------------------------------------------------------- 1 | * Everquote 2 | * GitLab 3 | * Grafana Labs 4 | * SoundCloud 5 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | * Richard "RichiH" Hartmann (Grafana Labs) 2 | * Brian Brazil (Robust Perception) 3 | * Paul Dix (InfluxDB) 4 | * Morgan McLean (Google) 5 | * Sumeer Bhola (Google) 6 | * Bogdan Drutu (Splunk) 7 | * Rob Skillington (Chronosphere) 8 | * Ben Kochie (GitLab) 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'kramdown-rfc2629' 4 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | base64 (0.2.0) 5 | certified (1.0.0) 6 | connection_pool (2.4.1) 7 | differ (0.1.2) 8 | json_pure (2.7.2) 9 | kramdown (2.4.0) 10 | rexml 11 | kramdown-parser-gfm (1.1.0) 12 | kramdown (~> 2.0) 13 | kramdown-rfc2629 (1.7.19) 14 | base64 (>= 0.1) 15 | certified (~> 1.0) 16 | differ (~> 0.1) 17 | json_pure (~> 2.0) 18 | kramdown (~> 2.4.0) 19 | kramdown-parser-gfm (~> 1.1) 20 | net-http-persistent (~> 4.0) 21 | unicode-blocks (~> 1.0) 22 | unicode-name (~> 1.0) 23 | unicode-scripts (~> 1.0) 24 | net-http-persistent (4.0.4) 25 | connection_pool (~> 2.2) 26 | rexml (3.3.7) 27 | unicode-blocks (1.10.0) 28 | unicode-name (1.13.0) 29 | unicode-types (~> 1.10) 30 | unicode-scripts (1.10.0) 31 | unicode-types (1.10.0) 32 | 33 | PLATFORMS 34 | ruby 35 | 36 | DEPENDENCIES 37 | kramdown-rfc2629 38 | 39 | BUNDLED WITH 40 | 2.1.4 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner]. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | * Ben Kochie 2 | * Brian Brazil 3 | * Richard Hartmann 4 | * Rob Skillington 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILD := $(abspath ./bin) 2 | 3 | # test-impl tests an OpenMetrics implementation. 4 | # 5 | # To test echo parser: 6 | # make test-impl cmd-parser-text=echo 7 | .PHONY: test-impl 8 | test-impl: 9 | # openmetricstest needs to be built in /src since it requires /src/go.mod 10 | cd ./src && make openmetricstest 11 | $(BUILD)/openmetricstest -cmd-parser-text="$(cmd-parser-text)" 12 | 13 | .PHONY: prometheus_client_python_parser 14 | prometheus_client_python_parser: 15 | docker build -t prometheus_client_python_parser:latest \ 16 | -f ./tests/implementations/prometheus_client_python_parser/Dockerfile \ 17 | ./tests/implementations/prometheus_client_python_parser 18 | 19 | # To test github.com/prometheus/client_python parser: 20 | .PHONY: test_prometheus_client_python_parser 21 | test_prometheus_client_python_parser: 22 | make prometheus_client_python_parser 23 | make test-impl cmd-parser-text="docker run --rm -i prometheus_client_python_parser:latest" 24 | 25 | # To test OpenMetrics validator: 26 | .PHONY: test_open_metrics_validator 27 | test_open_metrics_validator: 28 | cd ./src && make openmetricsvalidator 29 | make test-impl cmd-parser-text="./bin/openmetricsvalidator" 30 | 31 | 32 | .PHONY: proto_go 33 | proto_go: setup 34 | protoc --go_out=$(BUILD) --go_opt=paths=source_relative ./proto/*.proto 35 | 36 | .PHONY: setup 37 | setup: 38 | mkdir -p $(BUILD) 39 | 40 | .PHONY: clean 41 | clean: 42 | rm -rf $(BUILD) 43 | -------------------------------------------------------------------------------- /OpenMetrics.md: -------------------------------------------------------------------------------- 1 | specification/OpenMetrics.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![OpenMetrics Logo](website/static/images/logo/logo-with-text.png) 3 | 4 | # OpenMetrics 5 | 6 | OpenMetrics a specification built upon and carefully extending [Prometheus exposition format](https://prometheus.io/docs/instrumenting/exposition_formats/) in almost 100% backwards-compatible ways. 7 | 8 | > NOTE: This project recently moved to Prometheus and we are working on OpenMetrics 2.0! See the details in [#276](https://github.com/prometheus/OpenMetrics/issues/276) on how to participate! 9 | 10 | # Spec 11 | 12 | See [our spec file](specification/OpenMetrics.md) and [our proto](proto/openmetrics_data_model.proto). 13 | 14 | # News and updates 15 | 16 | Join the [mailing list](https://groups.google.com/forum/m/#!forum/openmetrics) or follow us on [Twitter](https://twitter.com/OpenMetricsIO) 17 | 18 | # Code of Conduct 19 | To make OpenMetrics a welcoming and harassment-free experience for everyone, we follow the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). 20 | 21 | # OpenMetrics 2.0 development 22 | 23 | OpenMetrics 2.0 is currently under development. You can see [our charter](https://docs.google.com/document/d/1FCD-38Xz1-9b3ExgHOeDTQUKUatzgj5KbCND9t-abZY/edit?tab=t.6h53vr4k28b4#heading=h.uaaplxxbz60u) to understand our direction and our [meeting notes](https://docs.google.com/document/d/1FCD-38Xz1-9b3ExgHOeDTQUKUatzgj5KbCND9t-abZY/edit?tab=t.lvx6fags1fga#heading=h.uaaplxxbz60u) to understand our latest discussions. 24 | 25 | ## Contributing to OpenMetrics 2.0 26 | 27 | ### How can one propose a spec change to OpenMetrics? 28 | 29 | The process starts with creating a new issue in the OpenMetrics’ GitHub repository: https://github.com/prometheus/OpenMetrics. 30 | 31 | When opening an Issue, the author should try to describe the problem in detail. An issue asking for a change without explaining why such a thing is necessary will be ignored or closed. It's a good practice to focus on a feature that would be enabled by the change instead of going straight to implementation details. 32 | 33 | Example of a bad issue: 34 | 35 | ``` 36 | Title: Relax requirement to add unit as suffixes 37 | Body: It's annoying. 38 | ``` 39 | 40 | Example of a better issue: 41 | 42 | ``` 43 | Title: Allow exposing multiple metrics with same name in the same target 44 | Body: 45 | 46 | 47 | # Problem Statement 48 | 49 | Prometheus' federation endpoint cannot follow OpenMetrics specification because it's possible that multiple targets expose the same metric with same name but different metadata like Type/Help/Unit, but they all become a single target once exposed by Prometheus /federate endpoint. 50 | 51 | The same problem occurs with OpenTelemetry's Collector, who is able to collect metrics from several places and expose them in a single endpoint. 52 | 53 | # Proposed idea 54 | 55 | OpenMetrics should relax the requirement of exposing only one metric family by metric name. Instead, it should be allowed as long as metric TYPE or UNIT are different. 56 | ``` 57 | 58 | Once the issue is created, one of the maintainers should act by adding the necessary labels or closing the Issue if the idea is rejected. 59 | 60 | ### Labeling issues 61 | 62 | #### `triage:deciding:*` 63 | 64 | These labels are applied to issues when it is unclear yet if they are something the project will take on. 65 | 66 | * `triage:deciding:community-feedback` - This issue is open to community discussion. If the community can provide sufficient reasoning, the project may accept it. 67 | * `triage:deciding:needs-info` - This issue does not provide enough information for the project to accept it. It is left open to give the author time to add more details. 68 | 69 | #### `triage:accepted:*` 70 | 71 | These labels are applied to issues that describe a problem that is in scope and that we would like to tackle. Just because an issue is accepted does not mean that a solution suggested by the issue will be the solution applied. 72 | 73 | * `triage:accepted:needs-champion` - This issue was discussed enough and the outcome is clear to the maintainers, however, someone to take this to the finish line is still needed. 74 | * `triage:accepted:needs-formal-proposal` - This issue was discussed enough, the outcome is clear, and someone has already been assigned to implement the solution. The next step is to open a PR to the repository prometheus/proposals explaining the change to the wider Prometheus community. This proposal will cover the necessary changes that SDKs and/or Prometheus server will need to make. 75 | * `triage:accepted:PoC-needed` - This issue was discussed amongst maintainers, but it's still unclear if the implementation is doable efficiently. A Proof of Concept showcasing the results is necessary to advance. 76 | * `triage:accepted:ready` - The formal proposal has been accepted by the wider Prometheus community and is ready to be implemented. 77 | 78 | 79 | A closed issue means it was rejected. 80 | 81 | ### Formal proposals 82 | 83 | Compared to the whole Prometheus community, OpenMetrics maintainers and contributors are a relatively small group. However, whatever is decided in OpenMetrics impacts several SDKs, Prometheus Server itself, and several other projects in the ecosystem, e.g. Thanos, Cortex, and OpenTelemetry. 84 | 85 | We follow Prometheus's proposal process to ensure we don't make changes that could harm the ecosystem. 86 | 87 | When writing a formal proposal, the author needs to cover all the changes the ecosystem will need to make. If a proposal touches several parts of the ecosystem, such as parsers, storage, and SDKs, being as detailed as possible in all aspects will accelerate the approval needed to start the implementation. 88 | 89 | Don't hesitate to create PoCs to better illustrate the final outcome. 90 | 91 | ### Accepted Proposals 92 | 93 | To finalize the process, a PR is necessary to update the spec in: https://github.com/prometheus/OpenMetrics/blob/main/specification/OpenMetrics.md 94 | -------------------------------------------------------------------------------- /TIMELINE.MD: -------------------------------------------------------------------------------- 1 | This is a short overview of important dates & meetings from the point of view of OpenMetrics 2 | 3 | # Timeline 4 | 5 | ## 2014 6 | 7 | Prometheus exposition format 0.0.4 introduced, and stable since then. 8 | 9 | ## 2015 10 | 11 | First thoughts around RFC 12 | 13 | ## 2016 14 | 15 | ## 2017 16 | 17 | ### 2017-06 OpenConfig & OpenMetrics 18 | 19 | Meeting to see if the projects can collaborate, and how. 20 | 21 | Anees Shaikh (Google), Ben Kochie (GitLab), Carl Lebsack (Google), Eric Silva (Google), Jeromy Carriere (Google), Murali Suriar (Google), Richard "RichiH" Hartmann (SpaceNet) 22 | 23 | 24 | ### 2017-10 OpenCensus & OpenMetrics meeting at Google London 25 | 26 | [Meeting notes](legacy/meetings/2017-10-10--face-to-face.md) 27 | 28 | ### 2017-11 Uber joins OpenMetrics 29 | 30 | Rob Skillington (Uber) and Jerome ??? (Uber) join 31 | 32 | ## 2020 33 | 34 | * release 35 | 36 | * SIG o11y DD 37 | 38 | ## 2021 39 | 40 | All meetings public, recorded, and published to YouTube 41 | 42 | [Meeting notes](https://docs.google.com/document/d/17j5w4CZGT5bg6mtqFkJjTp4Vx53K1RU543rhA05Dxzg) 43 | 44 | # TODO 45 | 46 | * When did Lee Calcote (SolarWinds) join & leave 47 | * When did Sumeer leave 48 | -------------------------------------------------------------------------------- /legacy/markdown/metric_exposition_format.md: -------------------------------------------------------------------------------- 1 | # Current Prometheus text format (0.0.4) 2 | 3 | Official docs: 4 | Old working document: 5 | 6 | Note: In-line comments _not_ copied over 7 | 8 | Basic format looks like: 9 | 10 | # HELP http_requests_total The total number of HTTP requests. 11 | # TYPE http_requests_total counter 12 | http_requests_total{method="post",code="200"} 1027 1395066363000 13 | http_requests_total{method="post",code="400"} 3 1395066363000 14 | 15 | Escaping in label values: 16 | 17 | msdos_file_access_time_seconds{path="C:\\DIR\\FILE.TXT",error="Cannot find file:\n\"FILE.TXT\""} 1.458255915e9 18 | 19 | Minimalistic line: 20 | 21 | metric_without_timestamp_and_labels 12.47 22 | 23 | A weird metric from before the epoch: 24 | 25 | something_weird{problem="division by zero"} +Inf -3982045 26 | 27 | A histogram, which has a pretty complex representation in the text format: 28 | 29 | # HELP http_request_duration_seconds A histogram of the request duration. 30 | # TYPE http_request_duration_seconds histogram 31 | http_request_duration_seconds_bucket{le="0.05"} 24054 32 | http_request_duration_seconds_bucket{le="0.1"} 33444 33 | http_request_duration_seconds_bucket{le="0.2"} 100392 34 | http_request_duration_seconds_bucket{le="0.5"} 129389 35 | http_request_duration_seconds_bucket{le="1"} 133988 36 | http_request_duration_seconds_bucket{le="+Inf"} 144320 37 | http_request_duration_seconds_sum 53423 38 | http_request_duration_seconds_count 144320 39 | 40 | Finally a summary, which has a complex representation, too: 41 | 42 | # HELP rpc_duration_seconds A summary of the RPC duration in seconds. 43 | # TYPE rpc_duration_seconds summary 44 | rpc_duration_seconds{quantile="0.01"} 3102 45 | rpc_duration_seconds{quantile="0.05"} 3272 46 | rpc_duration_seconds{quantile="0.5"} 4773 47 | rpc_duration_seconds{quantile="0.9"} 9001 48 | rpc_duration_seconds{quantile="0.99"} 76656 49 | rpc_duration_seconds_sum 1.7560473e+07 50 | rpc_duration_seconds_count 2693 51 | 52 | 53 | # Notes, some of them Prometheus-specific: 54 | 55 | - Metric names are `[a-zA-Z_:][a-zA-Z0-9_:]*` 56 | - Label names are `[a-zA-Z0-9_]*` 57 | - Label values are full utf-8, null bytes are permitted 58 | - Metrics should not be exposed with colons, that's for end user use for 59 | aggregation by convention 60 | - Counter metrics end in _total by convention, counters start at 0 and only go 61 | up 62 | - Gauges do not have a suffix by convention, can go up and down 63 | - All values are float64 64 | - `\n` is the line terminator 65 | - There's no required ordering on label names, however for performance reasons 66 | a consistent ordering is encouraged 67 | - Histogram values are cumulative, so the le="0.5" bucket includes the values 68 | in the previous buckets 69 | - The reasoning behind this is that you can remove buckets and still have 70 | things work. This is intended to allow for abuse mitigation if someone adds 71 | too many buckets. 72 | - The values in the le and quantile labels are float64. 73 | - The quantile label can have values from 0 to 1. 74 | - The le label can be any non-NaN value, which means _sum isn't actually a 75 | counter. 76 | - I, @brian-brazil, am not a fan of this and would prefer to restrict it to 77 | non-negative values only 78 | - The spec says these must be provided in increasing order 79 | - Summaries are quantiles, not percentiles 80 | - This is a general Prometheus best practice, we deal with things in 81 | seconds/bytes/ratios and leave converting to something more human readable at 82 | the display layer. This convention is to avoid a mix of units. 83 | - _sum and _count of histograms/summaries aren't always present, due to some 84 | instrumentation libraries not supporting them. 85 | - _count of a histogram is always the same as the +Inf bucket. 86 | - TYPE and HELP 87 | - Are optional 88 | - Are currently discarded by Prometheus 89 | - If they are stored, conflicts must be handled (last one wins, etc) 90 | - There's a "untyped" TYPE for when you don't know if something is a counter or 91 | gauge 92 | - +Inf, -Inf and NaN are supported 93 | - There is a specified MIME type 94 | - By convention, metrics are exposed on /metrics - though this is often not 95 | followed 96 | - We're starting to add support for selecting specific time series via a url 97 | parameter ?name[]=timeseries, currently only supported in Python and Java 98 | 99 | - There's also a number of other conventions/best practices/patterns about how 100 | to expose time series to be as useful as possible to query in Prometheus, 101 | though the principles should largely apply to other systems too. These range 102 | from simple things like always putting units in the metric name (preferably 103 | base units like seconds), to things that depend on PromQL features such as 104 | how to handle non-identity labels you might want to use with a target for 105 | things like version numbers. 106 | 107 | ## Places it could be improved in general: 108 | 109 | - There's slightly different escaping rules for label names and HELP - we 110 | should unify this 111 | - Whitespace (spaces or tabs) can appear in any number between tokens - this 112 | should be tightened up 113 | - Timestamps can be appended to this as millisecond integers - fractional 114 | seconds would be better to allow for other precisions and be more consistent 115 | with Prometheus generally. 116 | - Specify exactly which spellings of +Inf/-Inf/Inf/NaN are allowed - probably 117 | all of them, case insensitive. Different languages produce different 118 | capitalizations and don't always have the + for +Inf. 119 | - Should we worry about float parsing being otherwise consistent? We haven't 120 | run into any issues yet. 121 | - Adding an end marker, to help detect if the response got cut off 122 | - Users forgetting the final \n is not uncommon when hand-assembling the 123 | format, is there anything we can do there? 124 | 125 | ## Potential expansions 126 | 127 | There are things which the format currently doesn't do, that have been talked about. Here's some of them: 128 | 129 | - It'd be nice to keep the new format parseable by a Prometheus 0.0.4 parser 130 | - The behaviour of Prometheus when a time series is exposed multiple times with 131 | different timestamps is explicitly undefined, we'll need to specify this 132 | (likely sorted oldest first) 133 | - If multiple values at different timestamps are supported, compressing them, 134 | e.g. into one line, might make sense 135 | - Let's figure out semantics first, micro-optimisations can come later 136 | - Timestamp precision other than milliseconds 137 | - Expose as an integer with fractional seconds/float64? 138 | - What should we do about before 1970? 139 | - 64 bit integer support 140 | - Do we want int64 or uint64? Both? 141 | - Anyone reading this: Are there any use cases for large, high-precision 142 | negative integers? 143 | - Do we need to indicate to the backend which type a value is (e.g. 0 vs 0.0)? 144 | - If we don’t, what happens when the backend “suddenly” gets float64 when it 145 | could assume it was [u]int64, before 146 | - Gracefully handling this for systems that only support more limited types 147 | - If we know it's a Counter, can we take it mod 2^53 in systems that only 148 | support float64? 149 | - 128 bit float/integer support 150 | - Once CPUs support 128 bits natively, it’s natural to expand the format. 151 | Should this simply be a breaking change (semvar major) or otherwise 152 | anticipated? 153 | - We're using text, so it'll Just Work I imagine 154 | - Boolean support 155 | - Prometheus convention is false=0, true=1. 156 | - Do we need to add tokens for this, or can we just stick to the convention? 157 | - Special values 158 | - Prometheus 2.0 has a special "stale" value used internally (it's a NaN with a 159 | particular bit pattern) which we may wish to expose to other Prometheus 160 | servers. Is this something we should allow (if we end up wanting it), or just 161 | keep as a Prometheus-specific extension? 162 | - String support 163 | - Debate around whether a first class string value should be added 164 | - One idea is around annotations, that are not part of times series identity 165 | - Would these go with a metric or a time series? 166 | - What are the use cases for these? Are they more log-like? 167 | - The approach at 168 | https://www.robustperception.io/how-to-have-labels-for-machine-roles/ may be 169 | an option for annotations 170 | - Gauge with value 1 and a label for each piece of information 171 | - Enum use case, string with limited number of values 172 | - Gauge with one time series per potential value, with 0/1 values? 173 | - Byte string support 174 | - Influx have received a small number of requests for this over the years, not 175 | inclined to support it currently 176 | - Are there additional metadata fields beyond HELP/TYPE that we should 177 | have? 178 | -------------------------------------------------------------------------------- /legacy/meetings/2017-10-10--face-to-face.md: -------------------------------------------------------------------------------- 1 | # OpenMetrics Face-to-Face 2 | 3 | 2017-10-10 - 2017-10-11 4 | 5 | Google London 6 | 7 | # Attendees 8 | * Richard “RichiH” Hartmann richih@richih.org - RichiH@GitHub 9 | * Pim van Pelt pim@google.com - pimvanpelt@GitHub 10 | * Ben Kochie superq@gmail.com - SuperQ@GitHub 11 | * Wilmer van der Gaast wilmer@google.com - Wilm0r@GitHub 12 | * Tom Wilkie tom.wilkie@gmail.com - tomwilkie@GitHub 13 | * Brian Brazil brian.brazil@gmail.com - brian-brazil@GitHub 14 | * Paul Dix paul@influxdb.com - pauldix@GitHub 15 | * Eric Silva ericsilva@google.com ericanthonysilva@GitHub 16 | * Jeromy Carriere jcarriere@google.com - sjcarriere2@GitHub 17 | * Matt Bostock matt@mattbostock.com - mattbostock@GitHub 18 | * Morgan McLean morganmclean@google.com - mtwo@GitHub 19 | * Sumeer Bhola sbhola@google.com - sumeer@GitHub 20 | * Chris Larsen clarsen@oath.com - manolama@GitHub 21 | * Bogdan Drutu bdrutu@google.com - bogdandrutu@Github 22 | * Dino Oliva dpo@google.com - dinooliva@GitHub 23 | 24 | # Content 25 | ## Tuesday 2017-10-10 11:00 26 | 27 | * Introductions 28 | * Pim: Tasked with integrating SRE teams and standardizing our approaches on production between SRE, GCP and Developer Infrastructure, including Borgmon and Monarch; primary responsibilities: Releases/Rollouts (CI/CD), Systems Modeling and Actuation (CA), and Monitoring/Alerting for google’s production stacks. I use Prometheus headed by Grafana for www.sixxs.net, a ~60 server deployment, and other private IoT based projects. 29 | * Ben: Ex-Googler, joined SoundCloud and works on Prometheus. Wants Open Source Streamz - surprised that the industry still hasn’t grokked /varz. 30 | * Wilmer: Long-time Borgmon having spent years hearing how Borgmon sucks from people who never tried outside offerings, grateful that Prometheus now exists. 31 | * Tom: ex-Google, ex-Weaveworks, now Prometheus team and Kausal founder (Kausal runs hosted Prometheus) 32 | * Richi: never worked for Google… way too many years of being on call, want to push proper metrics into the world with the help of an RFC 33 | * Brian: ex-Googler, SRE and and one point helped defined the corp based borgmons. Became borgmon-guy, ended up knowing its power and deficiencies. Now core developer on Prometheus, avoiding new warts and removing others. Person for PromQL and client library semantics. 34 | * Paul Dix: Founded InfluxDB, want to support Prometheus metrics as a first class citizen 35 | * Eric: Product manager of Stackdriver 36 | * Jeromy: Engineering director for Monarch and its external manifestation in stackdriver. Want to make Google’s cloud offering as open as possible, exposing our infrastructure in APIs and a la carte (so customers can pick and choose what they’d like to use, and replace what they don’t like / want). 37 | * Matt Bostock, Cloudflare. Now 190 instances of Prometheus. Also use OpenTSDB. 38 | * Morgan Mclane - OpenCensus PM, 39 | * Chris Larsen - Monitoring engineer @ Yahoo/Oath, member of the valley large scale monitoring group meeting with companies like Paypal, Facebook, Ebay, Apple, LinkedIn, etc. Maintainer and lead on OpenTSDB 40 | * Bogdan: OpenCensus library team lead 41 | * Brian: Prometheus Data Model 42 | * It’s Borgmon, not MySQL 43 | * Not for things which live less than five minutes, Prometheus is not an eventlogger. 44 | * Jeromy: We need quicker than that for things like Cloud Functions and AppEngine 45 | * Brian: Need event logs or statsd 46 | * Jeromy: we do push metrics from appengine; its works… 47 | * Sumeer: We push at the start, every minute, and at the end 48 | * RichiH: No matter how, how long, or how often: the exposition format can be the same 49 | * Label sets are the identity, new label set, new time series 50 | * Implicit namespacing with underscores 51 | * Uses float64 for values and int64 millis for timestamps 52 | * Unix timestamps, base is seconds 53 | * Counters only go up, can do +x (but can be fractional increments); gauges go up/down 54 | * Have non-enforced suffixes for metric names 55 | * Terminology is inconsistent internally within Prometheus, suggested: 56 | * ‘a_count’: time series name 57 | * ‘a’: metric 58 | * ‘a_count{foo=”bar”}’: time series 59 | * ‘a{foo=”bar”}’: child 60 | * _sum/_count suffixes used by convention in Prometheus; should they be metadata? 61 | * (evacuation alarm in LON building) -- resumed at 1pm 62 | * Units 63 | * Worked in one group that did milliseconds for a decade; then a new project got onboarded, which did microseconds and broke dashboards etc.. This is horrible, so we do seconds. 64 | * Float64 as a baseline? Other types could be used if desired 65 | * String annotations: why not make these metrics ending in _info a primary type (metadata) with value 1? 66 | * Enums: what are they used for? 67 | * Nagios alert states, DB connection state etc 68 | * Lots of back and forth: Rough consensus: We talked about Prometheus-specific stuff and where this comes from; this does not mandate doing it this way within OpenMetrics 69 | * Slides https://docs.google.com/presentation/d/1TF1Y7XqgZThb9MUUvJUdEEbVjkNhQ1Ddg54ysTFPgqU/edit?usp=sharing 70 | * Chris: Yamas 71 | * Seconds, no ms, for timestamp. Values are float64 72 | * Common dimensions for set of named metrics 73 | * Status codes and status msg 74 | * AOL argus 75 | * Timestamp is ISO 8601 76 | * First class units 77 | * Binary blobs for digests/sketches 78 | * Annotations stored in line with timeseries 79 | * Would like to see support for blobs in OpenMetrics 80 | * Annotation labels which don’t change the identity of a timeseries 81 | * Slides https://docs.google.com/presentation/d/1UN88du2-mKyEi3F2n_ZFTpQm_yJr1KOQmnoOLPbEhJU/edit?usp=sharing 82 | * Sumeer: Monarch 83 | * Successor to Borgmon 84 | * Multi-tenant 85 | * Path-based, people should claim subtrees to maintain 86 | * 2 instances; google and public cloud 87 | * Supported units are from Unified Code for Units of Measure 88 | * Trace IDs can be attached to histogram buckets 89 | * Buckets can change and will be interpolated at change boundaries if changed 90 | * Timestamps are in microseconds 91 | * Open issues: 92 | * Memory use in clients when storing distributions 93 | * Specifying bucket sizes when metrics are produced 94 | * Census 95 | * Google’s instrumentation code (collects metrics and traces inside Borg) 96 | * Census is the instrumentation for Dapper 97 | * Going open source -> OpenCensus 98 | * Avoid ecosystem fragmentation as a tracing vendor 99 | * Defining data model, not just the API 100 | * AppDynamics might not be keen on a common ground, the rest views themselves as behind and are interested 101 | * Long-term, something will equalize 102 | * Language-specific libraries to send metrics/tracing to any backend 103 | * Example: Zipkin has many OSS libraries but mostly not maintained by the project; multiple libraries per language 104 | * Census will have one library per language 105 | * API for tracing/metrics 106 | * Provides traces and a dozen metrics out of the box 107 | * Census does not yet include profiling 108 | * Any backend supported, contributions welcome 109 | * Microsoft, Amazon interested 110 | * Google will be a contributor/partner to the project in the long-term, “not a Google project” 111 | * Push and pull could be supported; pull can cause contention on hot code paths 112 | * Zpages agent; executable that talks to Census libraries and hosts a web page serving recent metrics and RPCs 113 | * For now, inspired by StackDriver data model 114 | * Views = list of dimensions, metric, aggregation type, window 115 | * Data (views) currently pushed ‘raw’ to Monarch 116 | * InfluxDB 117 | * Open Discussion 118 | * See GitHub issue tracker for developing consensus. 119 | * Consensus 120 | * We spec in Proto 121 | * Some things might change, v2 vs v3 122 | * Text format MUST be supported, it’s the lingua franca 123 | * Easy to write 124 | * Need it for debugging anyway 125 | * We will have a test suite to implement against 126 | * Both linting & validation 127 | 128 | ## Wednesday 2017-10-11 10:00 129 | * Going through more issues 130 | * Fields options: 131 | * Option A (“prometheus”, 2 fields): 132 | * Float64(/Int/Bool) 133 | * Counter/Gauge/Histogram/Summary 134 | * Option B (“monarch”, fields): 135 | * Float/Int/Bool/Distribution 136 | * Cumulative/Gauge/Delta 137 | * Option C: 138 | * Float64/Int/Bool(,Enum?) 139 | * Cumulative/Gauge 140 | * Distribution/Scalar/Summary 141 | * Option D: 142 | * Float/Int/Bool 143 | * Counter/Gauge/Counter Histogram/Gauge Histogram 144 | * Option E: 145 | * Float/Int/Bool/Float Distribution/Int Distribution 146 | * Cumulative/Gauge/Delta 147 | * Option Z - a single field which could be: 148 | * Float Counter/Cumulative 149 | * Int Counter/Cumulative 150 | * Float Gauge 151 | * Int Gauge 152 | * Bool Gauge 153 | * Float Counter/Cumulative Histogram/Distribution 154 | * Int Counter/Cumulative Histogram/Distribution (sums & boundaries are ints vs floats) 155 | * Float Gauge Histogram/Distribution 156 | * Int Gauge Histogram/Distribution 157 | * Also: 158 | * Enums 159 | * Should it be an Enum Gauge Scalar or a Bool Counter Enum? 160 | * At datamodel level, is it a ‘type’ like int, float or bool? 161 | * What about float128 or uint64? 162 | * Geo postitioning 163 | * Deltas (could ignore for v1, AWS reports a bajillion) 164 | * Tuples? 165 | * They get complicated... 166 | * Do we want to support strings? 167 | * Will there be OpenMetrics client libraries, or will we just make the Prometheus client libraries OpenMetrics compatible? 168 | * Start timestamps on samples 169 | * Allows you to get more accurate rates when samples are sent infrequently 170 | * Ie really wide sampling intervals, every hour 171 | * Can allow you to detect when samples are dropped 172 | * Can allow you to GC large local histogram dimensions 173 | * Easily represent deltas in a cumulative stream 174 | * Just needed for cumulative type 175 | * Needed for representing deltas (a special case of cumulative). 176 | * Could be added to a “point” type in the data model, and represented as a second time series for each _child_ 177 | * Is a pretty advanced use case, so client libraries probably doesn’t need to expose it. But would like to have wire format and data model support it. 178 | * Exemplars 179 | * Suggested protos to hash out data structure 180 | * https://github.com/RichiH/OpenMetrics/tree/master/protos 181 | -------------------------------------------------------------------------------- /legacy/protos/.gitignore: -------------------------------------------------------------------------------- 1 | *.pb.go 2 | -------------------------------------------------------------------------------- /legacy/protos/Makefile: -------------------------------------------------------------------------------- 1 | %.pb.go: %.proto 2 | protoc --go_out=plugins=grpc:. $< 3 | 4 | all: $(patsubst %.proto,%.pb.go,$(wildcard *.proto)) 5 | -------------------------------------------------------------------------------- /legacy/protos/bogdandrutu.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package openmetrics.proto; 4 | 5 | enum ValueType { 6 | BOOL = 0; 7 | INT64 = 1; 8 | DOUBLE = 2; 9 | } 10 | 11 | message TypedValue { 12 | oneof value { 13 | bool bool_value = 1; 14 | int64 int64_value = 2; 15 | double double_value = 3; 16 | } 17 | } 18 | 19 | enum MetricKind { 20 | METRIC_KIND_UNSPECIFIED = 0; 21 | GAUGE = 1; 22 | CUMULATIVE = 2; 23 | // DELTA = 3; ?? 24 | } 25 | 26 | message LabelDescriptor { 27 | enum ValueType { 28 | STRING = 0; 29 | BOOL = 1; 30 | INT64 = 2; 31 | } 32 | string key = 1; 33 | ValueType value_type = 2; 34 | string description = 3; 35 | } 36 | 37 | message Bucket { 38 | int64 count = 1; 39 | TypedValue lower = 2; 40 | TypedValue upper = 3; 41 | } 42 | 43 | message Distribution { 44 | int64 count = 1; 45 | TypedValue sum = 2; 46 | TypedValue sum_of_squared_deviation = 3; 47 | repeated Bucket buckets = 4; 48 | } 49 | 50 | message Scalar { 51 | TypedValue value = 1; 52 | } 53 | 54 | message MetricValue { 55 | oneof value { 56 | Distribution distribution = 1; 57 | Scalar scalar = 2; 58 | } 59 | } 60 | 61 | message MetricDescription { 62 | string name = 1; 63 | repeated LabelDescriptor labels = 2; 64 | MetricKind kind = 3; 65 | ValueType value_type = 5; 66 | string unit = 6; 67 | string description = 7; 68 | } 69 | 70 | message IntervalTime { 71 | double start_time = 1; 72 | double end_time = 2; 73 | } 74 | 75 | message Metric { 76 | MetricDescription metric_description = 1; 77 | map labels = 2; 78 | MetricValue value = 3; 79 | IntervalTime interval = 4; 80 | } 81 | -------------------------------------------------------------------------------- /legacy/protos/brian-brazil.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package openmetrics; 4 | 5 | message Frame { 6 | repeated Metric metrics = 1; 7 | } 8 | 9 | message Metric { 10 | string name = 1; // required 11 | string unit = 2; 12 | string description = 3; 13 | 14 | // Type matches what's used in children - should use a proto enum 15 | Type string = 4; 16 | 17 | // (labels,timestamp) must be unique 18 | // Ordering/grouping stuff needs specification 19 | repeated Child children = 5; 20 | } 21 | 22 | enum Type { 23 | GaugeType = 0; 24 | CounterType = 1; 25 | // etc 26 | } 27 | 28 | message Child { 29 | map labels = 1; 30 | Value timestamp = 2; 31 | 32 | oneof value { 33 | Gauge gauge = 3; 34 | Counter Counter = 4; 35 | CumulativeHistogram cumulative_histogram = 5; 36 | GaugeCumulativeHistogram gauge_cumulative_histogram = 6; 37 | Enum enum = 7; 38 | Annotation annotation = 8; 39 | Summary summary = 9; 40 | Unknown unknown = 10; 41 | } 42 | } 43 | 44 | message Value { 45 | oneof value { 46 | double float64 = 1; 47 | uint64 uint64 = 2; 48 | // Can add more here 49 | } 50 | } 51 | 52 | message Gauge { 53 | Value value = 1; // required 54 | } 55 | 56 | message Counter { 57 | Value total = 1; // required 58 | Value created_time = 2; 59 | } 60 | 61 | message GaugeCumulativeHistogram { 62 | message Bucket { 63 | Value less_than_or_equal_to = 1; 64 | Value count = 2; 65 | } 66 | // Sorted, must have +Inf last 67 | // Buckets are configured statically for each metric in the instrumentation 68 | // API, i.e. don't dynamically change from scrape to scrape. 69 | repeated Bucket bucket = 1; 70 | 71 | // TODO: What other fields make sense here? 72 | } 73 | 74 | message CumulativeHistogram { 75 | message Bucket { 76 | Value less_than_or_equal_to = 1; 77 | Value count = 2; 78 | } 79 | 80 | // Sorted, must have +Inf last 81 | repeated Bucket buckets = 1; 82 | Value sum = 2; 83 | Value sum_of_squares_total = 3; 84 | Value created_time = 4; 85 | } 86 | 87 | message Enum { 88 | repeated string possible = 1; 89 | string value = 2; // required 90 | } 91 | 92 | message Summary { 93 | message Quantile { 94 | Value quantile = 1; 95 | Value value = 2; 96 | } 97 | 98 | repeated Quantile quantiles = 1; 99 | Value sum = 2; 100 | Value count = 3; 101 | Value sum_of_squares = 4; 102 | Value created_time = 5; 103 | } 104 | 105 | message Annotation { 106 | message Annotation { 107 | map annotation_labels = 1; 108 | } 109 | repeated Annotation annotations = 1; 110 | } 111 | 112 | message Unknown { 113 | Value value = 1; // required 114 | } 115 | -------------------------------------------------------------------------------- /legacy/protos/manolama.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package openmetrics; 4 | 5 | enum MetricType { 6 | COUNTER = 0; 7 | GAUGE = 1; 8 | SUMMARY = 2; 9 | ENUM = 3; 10 | BUCKETED_HISTOGRAM = 4; 11 | SKETCH_DISTRIBUTION = 5; 12 | // ... more 13 | } 14 | 15 | message Enum { 16 | map values = 1; 17 | } 18 | 19 | message Value { 20 | oneof value { 21 | int64 int64 = 1; 22 | double float64 = 2; 23 | } 24 | } 25 | 26 | message Counter { 27 | Value value = 1; 28 | int64 start_timestamp = 2; 29 | } 30 | 31 | message Gauge { 32 | Value value = 1; 33 | } 34 | 35 | message Summary { 36 | Value sum = 1; // required 37 | Value count = 2; // required 38 | int64 start_timestamp = 3; 39 | Value sum_of_squares = 4; 40 | Value max = 5; 41 | Value min = 6; 42 | } 43 | 44 | message SketchDistribution { 45 | bytes value = 1; 46 | } 47 | 48 | message BucketedHistogram { 49 | message Bucket { 50 | Value start = 1; // required 51 | Value end = 2; // required; allows for narrow range buckets 52 | // ---- 53 | Value count = 3; // required 54 | } 55 | repeated Bucket buckets = 1; 56 | Value overflow = 2; // required 57 | Value underflow = 3; // required 58 | } 59 | 60 | message DataPoint { 61 | string metric = 1; // required 62 | map labels = 2; // required 63 | MetricType metric_type = 3; // required 64 | int64 timestamp = 4; // required 65 | string unit = 5; 66 | Value value = 6; 67 | string annotation = 7; // e.g. exemplar/usernote 68 | } 69 | 70 | message CompactFormat { 71 | string metric = 1; // required 72 | MetricType metric_type = 2; // required 73 | Value value = 3; 74 | string unit = 4; 75 | string annotation = 5; // e.g. exemplar/usernote 76 | } 77 | 78 | message CompactSet{ 79 | map labels = 1; // required 80 | int64 timestamp = 2; // required 81 | CompactFormat data = 3; // required 82 | } 83 | -------------------------------------------------------------------------------- /legacy/protos/prometheus.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Prometheus Team 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | syntax = "proto2"; 15 | 16 | package io.prometheus.client; 17 | option java_package = "io.prometheus.client"; 18 | 19 | message LabelPair { 20 | optional string name = 1; 21 | optional string value = 2; 22 | } 23 | 24 | enum MetricType { 25 | COUNTER = 0; 26 | GAUGE = 1; 27 | SUMMARY = 2; 28 | UNTYPED = 3; 29 | HISTOGRAM = 4; 30 | } 31 | 32 | message Gauge { 33 | optional double value = 1; 34 | } 35 | 36 | message Counter { 37 | optional double value = 1; 38 | } 39 | 40 | message Quantile { 41 | optional double quantile = 1; 42 | optional double value = 2; 43 | } 44 | 45 | message Summary { 46 | optional uint64 sample_count = 1; 47 | optional double sample_sum = 2; 48 | repeated Quantile quantile = 3; 49 | } 50 | 51 | message Untyped { 52 | optional double value = 1; 53 | } 54 | 55 | message Histogram { 56 | optional uint64 sample_count = 1; 57 | optional double sample_sum = 2; 58 | repeated Bucket bucket = 3; // Ordered in increasing order of upper_bound, +Inf bucket is optional. 59 | } 60 | 61 | message Bucket { 62 | optional uint64 cumulative_count = 1; // Cumulative in increasing order. 63 | optional double upper_bound = 2; // Inclusive. 64 | } 65 | 66 | message Metric { 67 | repeated LabelPair label = 1; 68 | optional Gauge gauge = 2; 69 | optional Counter counter = 3; 70 | optional Summary summary = 4; 71 | optional Untyped untyped = 5; 72 | optional Histogram histogram = 7; 73 | optional int64 timestamp_ms = 6; 74 | } 75 | 76 | message MetricFamily { 77 | optional string name = 1; 78 | optional string help = 2; 79 | optional MetricType type = 3; 80 | repeated Metric metric = 4; 81 | } 82 | -------------------------------------------------------------------------------- /legacy/protos/sumeer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package openmetrics; 4 | 5 | message Label { 6 | string name = 1; // required 7 | oneof value { 8 | string string_value = 2; 9 | int64 int64_value = 3; 10 | bool bool_value = 4; 11 | } 12 | } 13 | 14 | message Point { 15 | repeated Label label = 1; 16 | 17 | // The actual metric value. 18 | oneof value { 19 | bool bool_value = 2; 20 | string string_value = 3; 21 | int64 int_value = 4; 22 | EnumValue enum_value = 5; 23 | double double_value = 6; 24 | DistributionValue distribution_value = 7; 25 | } 26 | 27 | int64 start_timestamp = 8; // required 28 | int64 end_timestamp = 9; // required for cumulative 29 | } 30 | 31 | // A set of points belonging to a metric. 32 | message PointSet { 33 | string metric_name = 1; // required 34 | repeated Point point = 2; 35 | } 36 | 37 | message MetricSet { 38 | repeated Label label = 1; // Labels that apply to all metrics 39 | repeated PointSet point_set = 2; 40 | 41 | // Descriptors of all metrics sent in point_set 42 | message MetricDescriptor { 43 | string name = 1; // required 44 | enum ScalarType { 45 | INT = 0; 46 | FLOAT = 1; 47 | STRING = 2; 48 | ENUM = 3; 49 | } 50 | enum Kind { 51 | GAUGE = 0; 52 | CUMULATIVE = 1; 53 | UNKNOWN = 2; 54 | } 55 | enum Type { 56 | SCALAR = 0; 57 | DISTRIBUTION = 1; 58 | SUMMARY = 2; 59 | } 60 | ScalarType scalar_type = 2; 61 | Kind kind = 3; 62 | Type type = 4; 63 | 64 | string description = 5; 65 | } 66 | repeated MetricDescriptor md = 3; 67 | } 68 | 69 | message EnumValue { 70 | string value = 1; 71 | repeated string set_of_possible_values = 2; 72 | } 73 | 74 | message DistributionValue { 75 | int64 count = 1; 76 | double mean = 2; 77 | double sum_of_square_deviation = 3; 78 | 79 | message Range { 80 | double min = 1; 81 | double max = 2; 82 | } 83 | 84 | Range range = 4; 85 | 86 | 87 | // Buckets are optional. 88 | message BucketOptions { 89 | oneof options { 90 | // The linear bucket. 91 | Linear linear_buckets = 1; 92 | 93 | // The exponential buckets. 94 | Exponential exponential_buckets = 2; 95 | 96 | // The explicit buckets. 97 | Explicit explicit_buckets = 3; 98 | } 99 | } 100 | BucketOptions bucket_options = 5; 101 | // First and last buckets are underflow and overflow counts 102 | repeated int64 bucket_counts = 7; 103 | } 104 | 105 | message Linear { 106 | // TODO 107 | } 108 | 109 | message Exponential { 110 | // TODO 111 | } 112 | 113 | message Explicit { 114 | // TODO 115 | } 116 | -------------------------------------------------------------------------------- /legacy/protos/tomwilkie.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package openmetrics; 4 | 5 | message Frame { 6 | repeated Metric metrics = 1; 7 | } 8 | 9 | message Metric { 10 | string name = 1; 11 | string unit = 2; 12 | string help = 3; 13 | 14 | Type type = 4; 15 | Kind kind = 5; 16 | Structure struct = 6; 17 | 18 | repeated Child children = 7; 19 | 20 | // Q: list label keys here so don’t repeat the keys? 21 | // .. or not, due to federation. 22 | } 23 | 24 | enum Type { 25 | FLOAT64 = 0; 26 | INT64 = 1; 27 | BOOL = 2; 28 | ENUM = 3; 29 | } 30 | 31 | enum Kind { 32 | CUMULATIVE = 0; 33 | GAUGE = 1; 34 | UNKNOWN = 2; 35 | } 36 | 37 | enum Structure { 38 | SCALAR = 0; 39 | HISTOGRAM = 1; 40 | SUMMARY = 2; 41 | } 42 | 43 | message Child { 44 | map labels = 1; 45 | 46 | // TODO want to have multiple timestamps in the model? 47 | oneof value { 48 | Scalar scalar = 2; 49 | Summary summary = 3; 50 | Histogram histogram = 4; 51 | } 52 | } 53 | 54 | message Scalar { 55 | int64 timestamp = 1; 56 | Value value = 2; 57 | } 58 | 59 | message Summary { 60 | int64 timestamp = 1; 61 | uint64 sample_count = 2; 62 | Value sample_sum = 3; 63 | repeated Quantile quantile = 4; 64 | } 65 | 66 | message Quantile { 67 | double quantile = 1; 68 | Value value = 2; 69 | } 70 | 71 | message Histogram { 72 | int64 timestamp = 1; 73 | uint64 sample_count = 2; 74 | Value sample_sum = 3; 75 | repeated Bucket bucket = 4; 76 | } 77 | 78 | message Bucket { 79 | uint64 count = 1; 80 | Value upper_bound = 2; 81 | } 82 | 83 | message Value { 84 | oneof value { 85 | double double = 2; 86 | uint64 uint64 = 3; 87 | bool bool = 4; 88 | string enum = 6; 89 | } 90 | 91 | // Possible values have to be here for federation use case. 92 | repeated string enum_values = 7; 93 | } 94 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # This file contains the configuration for the OpenMetrics website, 2 | # which is built by the Hugo (https://gohugo.io) static site 3 | # generator and hosted by Netlify (https://netlify.com). All assets 4 | # for the website are in the /website folder. 5 | [build] 6 | base = "website" 7 | publish = "website/public" 8 | command = "make netlify-production-build" 9 | 10 | [build.environment] 11 | HUGO_VERSION = "0.46" 12 | 13 | [context.deploy-preview] 14 | command = "make netlify-staging-build" 15 | 16 | [context.branch-deploy] 17 | command = "hugo netlify-staging-build" 18 | -------------------------------------------------------------------------------- /proto/openmetrics_data_model.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | // The OpenMetrics protobuf schema which defines the protobuf wire format. 4 | // Ensure to interpret "required" as semantically required for a valid message. 5 | // All string fields MUST be UTF-8 encoded strings. 6 | package openmetrics; 7 | 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | // The top-level container type that is encoded and sent over the wire. 11 | message MetricSet { 12 | // Each MetricFamily has one or more MetricPoints for a single Metric. 13 | repeated MetricFamily metric_families = 1; 14 | } 15 | 16 | // One or more Metrics for a single MetricFamily, where each Metric 17 | // has one or more MetricPoints. 18 | message MetricFamily { 19 | // Required. 20 | string name = 1; 21 | 22 | // Optional. 23 | MetricType type = 2; 24 | 25 | // Optional. 26 | string unit = 3; 27 | 28 | // Optional. 29 | string help = 4; 30 | 31 | // Optional. 32 | repeated Metric metrics = 5; 33 | } 34 | 35 | // The type of a Metric. 36 | enum MetricType { 37 | // Unknown must use unknown MetricPoint values. 38 | UNKNOWN = 0; 39 | // Gauge must use gauge MetricPoint values. 40 | GAUGE = 1; 41 | // Counter must use counter MetricPoint values. 42 | COUNTER = 2; 43 | // State set must use state set MetricPoint values. 44 | STATE_SET = 3; 45 | // Info must use info MetricPoint values. 46 | INFO = 4; 47 | // Histogram must use histogram value MetricPoint values. 48 | HISTOGRAM = 5; 49 | // Gauge histogram must use histogram value MetricPoint values. 50 | GAUGE_HISTOGRAM = 6; 51 | // Summary quantiles must use summary value MetricPoint values. 52 | SUMMARY = 7; 53 | } 54 | 55 | // A single metric with a unique set of labels within a metric family. 56 | message Metric { 57 | // Optional. 58 | repeated Label labels = 1; 59 | 60 | // Optional. 61 | repeated MetricPoint metric_points = 2; 62 | } 63 | 64 | // A name-value pair. These are used in multiple places: identifying 65 | // timeseries, value of INFO metrics, and exemplars in Histograms. 66 | message Label { 67 | // Required. 68 | string name = 1; 69 | 70 | // Required. 71 | string value = 2; 72 | } 73 | 74 | // A MetricPoint in a Metric. 75 | message MetricPoint { 76 | // Required. 77 | oneof value { 78 | UnknownValue unknown_value = 1; 79 | GaugeValue gauge_value = 2; 80 | CounterValue counter_value = 3; 81 | HistogramValue histogram_value = 4; 82 | StateSetValue state_set_value = 5; 83 | InfoValue info_value = 6; 84 | SummaryValue summary_value = 7; 85 | } 86 | 87 | // Optional. 88 | google.protobuf.Timestamp timestamp = 8; 89 | } 90 | 91 | // Value for UNKNOWN MetricPoint. 92 | message UnknownValue { 93 | // Required. 94 | oneof value { 95 | double double_value = 1; 96 | int64 int_value = 2; 97 | } 98 | } 99 | 100 | // Value for GAUGE MetricPoint. 101 | message GaugeValue { 102 | // Required. 103 | oneof value { 104 | double double_value = 1; 105 | int64 int_value = 2; 106 | } 107 | } 108 | 109 | // Value for COUNTER MetricPoint. 110 | message CounterValue { 111 | // Required. 112 | oneof total { 113 | double double_value = 1; 114 | uint64 int_value = 2; 115 | } 116 | 117 | // The time values began being collected for this counter. 118 | // Optional. 119 | google.protobuf.Timestamp created = 3; 120 | 121 | // Optional. 122 | Exemplar exemplar = 4; 123 | } 124 | 125 | // Value for HISTOGRAM or GAUGE_HISTOGRAM MetricPoint. 126 | message HistogramValue { 127 | // Optional. 128 | oneof sum { 129 | double double_value = 1; 130 | int64 int_value = 2; 131 | } 132 | 133 | // Optional. 134 | uint64 count = 3; 135 | 136 | // The time values began being collected for this histogram. 137 | // Optional. 138 | google.protobuf.Timestamp created = 4; 139 | 140 | // Optional. 141 | repeated Bucket buckets = 5; 142 | 143 | // Bucket is the number of values for a bucket in the histogram 144 | // with an optional exemplar. 145 | message Bucket { 146 | // Required. 147 | uint64 count = 1; 148 | 149 | // Optional. 150 | double upper_bound = 2; 151 | 152 | // Optional. 153 | Exemplar exemplar = 3; 154 | } 155 | } 156 | 157 | message Exemplar { 158 | // Required. 159 | double value = 1; 160 | 161 | // Optional. 162 | google.protobuf.Timestamp timestamp = 2; 163 | 164 | // Labels are additional information about the exemplar value (e.g. trace id). 165 | // Optional. 166 | repeated Label label = 3; 167 | } 168 | 169 | // Value for STATE_SET MetricPoint. 170 | message StateSetValue { 171 | // Optional. 172 | repeated State states = 1; 173 | 174 | message State { 175 | // Required. 176 | bool enabled = 1; 177 | 178 | // Required. 179 | string name = 2; 180 | } 181 | } 182 | 183 | // Value for INFO MetricPoint. 184 | message InfoValue { 185 | // Optional. 186 | repeated Label info = 1; 187 | } 188 | 189 | // Value for SUMMARY MetricPoint. 190 | message SummaryValue { 191 | // Optional. 192 | oneof sum { 193 | double double_value = 1; 194 | int64 int_value = 2; 195 | } 196 | 197 | // Optional. 198 | uint64 count = 3; 199 | 200 | // The time sum and count values began being collected for this summary. 201 | // Optional. 202 | google.protobuf.Timestamp created = 4; 203 | 204 | // Optional. 205 | repeated Quantile quantile = 5; 206 | 207 | message Quantile { 208 | // Required. 209 | double quantile = 1; 210 | 211 | // Required. 212 | double value = 2; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /specification/README.md: -------------------------------------------------------------------------------- 1 | # Generating the RFC text 2 | 3 | The OpenMetrics.md is the source of the RFC text. To generate the output text, 4 | [kramdown-rfc2629](https://github.com/cabo/kramdown-rfc2629) is used. This 5 | requires Ruby. 6 | 7 | From the top of the repository: 8 | 9 | bundle install 10 | bundle exec kdrfc specification/OpenMetrics.md 11 | mv -v specification/OpenMetrics.txt specification/draft-richih-opsawg-openmetrics-00.txt 12 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | BUILD := $(abspath ../bin) 2 | BINARIES := \ 3 | openmetricstest \ 4 | openmetricsvalidator \ 5 | scrapevalidator \ 6 | 7 | .PHONY: setup 8 | setup: 9 | mkdir -p $(BUILD) 10 | 11 | .PHONY: binaries 12 | binaries: $(BINARIES) 13 | 14 | define BINARY_RULES 15 | 16 | .PHONY: $(BINARY) 17 | $(BINARY): setup 18 | @echo Building $(BINARY) 19 | go build -o $(BUILD)/$(BINARY) ./cmd/$(BINARY)/. 20 | 21 | endef 22 | 23 | $(foreach BINARY,$(BINARIES),$(eval $(BINARY_RULES))) 24 | -------------------------------------------------------------------------------- /src/cmd/openmetricstest/README.md: -------------------------------------------------------------------------------- 1 | # openmetricstest 2 | 3 | A command line tool to drive testing an Open Metrics parser and exposition implementation. 4 | 5 | ## Compile 6 | 7 | From the /src directory: 8 | 9 | ``` 10 | make openmetricstest 11 | ``` 12 | 13 | ## Usage 14 | 15 | ``` 16 | Usage of ./openmetricstest: 17 | -cmd-parser-text string 18 | command to run to test parser in text mode 19 | -testdata-dir string 20 | testdata directory to use (default "./tests/testdata") 21 | ``` 22 | 23 | ## Testing an implementation 24 | 25 | ### Testing parsing 26 | 27 | The parse tests require the path to a binary to be supplied, the tests then pass input to that binary through `stdin` and the binary is expected to return a success exit code of 0 if it was able to parse the input, or any other exit code if not able to process the input. 28 | 29 | ### How it works 30 | 31 | The tool will walk the `testdata-dir` directory and execute all tests it finds (any directory with `test.json` is a test). 32 | 33 | To run the tests against an implementation you must specify a process to test a feature (such as parsing). 34 | 35 | When testing a library you will need to have a process that can house the library to test a feature. 36 | 37 | ### Test types 38 | 39 | > `cmd-parser-text` 40 | 41 | This command specifies the process to run to test parsing OpenMetrics text exposition test cases. It should take the OpenMetrics text exposition as stdin. 42 | 43 | ## Examples 44 | 45 | These examples are from running the tool in the repository root after building it. 46 | 47 | ### Testing text parsing with "true" 48 | 49 | This is an example of testing that "true" can parse a simple counter text exposition: 50 | 51 | ``` 52 | # Run and since echo will always accept any stdin observe success in the root directory. 53 | ./bin/openmetricstest -testdata-dir ./tests/testdata/parsers/simple_counter -cmd-parser-text true 54 | 2019/07/02 09:15:07 RUN test: simple_counter 55 | 2019/07/02 09:15:07 parse-result-validator ok 56 | 2019/07/02 09:15:07 PASS test: simple_counter 57 | 2019/07/02 09:15:07 OK passed=1, failed=0, total_failures=0 58 | ``` 59 | 60 | ### Testing text parsing with a script that always fails 61 | 62 | ``` 63 | # Run and since the script will always fail regardless of stdin observe failure in the root directory. 64 | ./bin/openmetricstest -testdata-dir ./tests/testdata/parsers/simple_counter -cmd-parser-text false 65 | 2019/04/09 21:40:30 RUN test: simple_counter 66 | 2019/04/09 21:40:30 parse-result-validator error: 67 | 2019/04/09 21:40:30 > parse error: exit status 1 68 | 2019/04/09 21:40:30 FAIL test: simple_counter 69 | 2019/04/09 21:40:30 FAILED passed=0, failed=1, total_failures=1 70 | ``` 71 | -------------------------------------------------------------------------------- /src/cmd/openmetricstest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "path" 12 | "path/filepath" 13 | "strings" 14 | ) 15 | 16 | type code int 17 | 18 | const ( 19 | testFileName = "test.json" 20 | 21 | exitOK code = iota 22 | exitUsage 23 | exitFailures 24 | ) 25 | 26 | var ( 27 | testDataDirArg = flag.String("testdata-dir", "./tests/testdata", "testdata directory to use") 28 | cmdTestParserTextArg = flag.String("cmd-parser-text", "", "command to run to test parser in text mode") 29 | ) 30 | 31 | func main() { 32 | flag.Parse() 33 | 34 | testDataDir := *testDataDirArg 35 | cmdTestParserText := *cmdTestParserTextArg 36 | 37 | if cmdTestParserText == "" { 38 | flag.Usage() 39 | os.Exit(int(exitUsage)) 40 | return 41 | } 42 | 43 | r, err := runTests(testDataDir, runTestsOptions{ 44 | cmdTestParserText: cmdTestParserText, 45 | }) 46 | if err != nil { 47 | log.Fatalf("failed to run tests: %v", err) 48 | } 49 | 50 | var success, failed, failures int 51 | for _, elem := range r.tests { 52 | if len(elem.failures) == 0 { 53 | success++ 54 | } else { 55 | failed++ 56 | } 57 | failures += len(elem.failures) 58 | } 59 | 60 | result := fmt.Sprintf("passed=%d, failed=%d, total_failures=%d", 61 | success, failed, failures) 62 | if failures != 0 { 63 | log.Println("FAILED", result) 64 | os.Exit(1) 65 | } 66 | 67 | log.Println("OK", result) 68 | } 69 | 70 | type runTestsOptions struct { 71 | cmdTestParserText string 72 | } 73 | 74 | type runTestsResults struct { 75 | tests []runTestResult 76 | } 77 | 78 | type runTestResult struct { 79 | name string 80 | failures []testFailure 81 | } 82 | 83 | type testFailure struct { 84 | name string 85 | err error 86 | } 87 | 88 | func runTests(dir string, opts runTestsOptions) (runTestsResults, error) { 89 | var results runTestsResults 90 | err := filepath.Walk(dir, func(filePath string, file os.FileInfo, err error) error { 91 | if err != nil { 92 | return fmt.Errorf("cannot read path=%s: %v", filePath, err) 93 | } 94 | if file.Name() != testFileName { 95 | return nil 96 | } 97 | 98 | testDir, _ := path.Split(filePath) 99 | result, err := runTest(testDir, opts) 100 | results.tests = append(results.tests, result) 101 | return err 102 | }) 103 | return results, err 104 | } 105 | 106 | type testDef struct { 107 | Comment string `json:"comment"` 108 | Type string `json:"type"` 109 | File string `json:"file"` 110 | ShouldParse bool `json:"shouldParse"` 111 | } 112 | 113 | func runTest(dir string, opts runTestsOptions) (runTestResult, error) { 114 | result := runTestResult{ 115 | name: path.Base(dir), 116 | } 117 | testFile := path.Join(dir, testFileName) 118 | data, err := ioutil.ReadFile(testFile) 119 | if err != nil { 120 | return result, fmt.Errorf("cannot read test file: %v", err) 121 | } 122 | 123 | var test testDef 124 | if err := json.Unmarshal(data, &test); err != nil { 125 | return result, fmt.Errorf("cannot parse test file: %v", err) 126 | } 127 | 128 | var description string 129 | if test.Comment != "" { 130 | description = fmt.Sprintf("(%s)", test.Comment) 131 | } 132 | 133 | log.Println("RUN test:", result.name, description) 134 | 135 | inputFile := path.Join(dir, test.File) 136 | input, err := ioutil.ReadFile(inputFile) 137 | if err != nil { 138 | return result, fmt.Errorf("cannot read test input: file=%s, err=%v", inputFile, err) 139 | } 140 | 141 | switch test.Type { 142 | case "text": 143 | var testArgs []string 144 | testCmd := opts.cmdTestParserText 145 | if strings.Contains(testCmd, " ") { 146 | // Extrapolate the rest of command as arguments. 147 | split := strings.Split(testCmd, " ") 148 | testCmd = split[0] 149 | testArgs = split[1:] 150 | } 151 | 152 | cmd := exec.Command(testCmd, testArgs...) 153 | 154 | stdin, err := cmd.StdinPipe() 155 | if err != nil { 156 | return result, fmt.Errorf("cannot access stdin: %v", err) 157 | } 158 | 159 | if err := cmd.Start(); err != nil { 160 | return result, fmt.Errorf("cannot start cmd: %v", err) 161 | } 162 | 163 | if _, err := stdin.Write(input); err != nil { 164 | return result, fmt.Errorf("cannot write input: %v", err) 165 | } 166 | if err := stdin.Close(); err != nil { 167 | return result, fmt.Errorf("cannot close input: %v", err) 168 | } 169 | 170 | // Run validators on result and collect failures 171 | result.failures = validateResult(test, cmd) 172 | 173 | if len(result.failures) > 0 { 174 | log.Println("FAIL test:", result.name) 175 | return result, nil 176 | } 177 | 178 | log.Println("PASS test:", result.name) 179 | default: 180 | return result, fmt.Errorf("parse type unknown: %s", test.Type) 181 | } 182 | 183 | return result, nil 184 | } 185 | 186 | func validateResult(test testDef, cmd *exec.Cmd) []testFailure { 187 | result := testResult{ 188 | cmd: cmd, 189 | err: cmd.Wait(), 190 | } 191 | 192 | var failures []testFailure 193 | validate := func(v testResultValidator) { 194 | if err := v.ValidateResult(result); err != nil { 195 | log.Println(v.Name(), "error:") 196 | log.Println(">", err) 197 | failures = append(failures, testFailure{ 198 | name: v.Name(), 199 | err: err, 200 | }) 201 | return 202 | } 203 | log.Println(v.Name(), "ok") 204 | } 205 | 206 | // Run validators 207 | validate(newParseResultValidator(test)) 208 | 209 | // Future validators come here 210 | return failures 211 | } 212 | -------------------------------------------------------------------------------- /src/cmd/openmetricstest/validators.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | ) 7 | 8 | type testResult struct { 9 | cmd *exec.Cmd 10 | err error 11 | } 12 | 13 | type testResultValidator interface { 14 | Name() string 15 | ValidateResult(r testResult) error 16 | } 17 | 18 | type parseResultValidator struct { 19 | shouldParse bool 20 | } 21 | 22 | func newParseResultValidator(def testDef) testResultValidator { 23 | return parseResultValidator{shouldParse: def.ShouldParse} 24 | } 25 | 26 | func (v parseResultValidator) Name() string { 27 | return "parse-result-validator" 28 | } 29 | 30 | func (v parseResultValidator) ValidateResult(r testResult) error { 31 | if v.shouldParse && r.err != nil { 32 | return fmt.Errorf("parse error: %v", r.err) 33 | } else if !v.shouldParse && r.err == nil { 34 | return fmt.Errorf("expected a parse error, none found") 35 | } 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /src/cmd/openmetricsvalidator/README.md: -------------------------------------------------------------------------------- 1 | # openmetricsvalidator 2 | 3 | A command tool to wrap the golang [OpenMetrics](https://github.com/prometheus/prometheus/blob/39d79c3cfb86c47d6bc06a9e9317af582f1833bb/pkg/textparse/openmetricsparse.go#L102) parser. 4 | 5 | ## Compile 6 | 7 | From the /src directory: 8 | 9 | ``` 10 | make openmetricsvalidator 11 | ``` 12 | 13 | ## Example 14 | 15 | Here are some examples of running the golang parser from the root directory. 16 | 17 | ``` 18 | cat ./tests/testdata/parsers/bad_help_0/metrics | ./bin/openmetricsvalidator 19 | 2021/06/08 20:04:20 failed to validate input: "INVALID" "\n" is not a valid start token 20 | 21 | cat ./tests/testdata/parsers/simple_counter/metrics | ./bin/openmetricsvalidator 22 | 2021/06/08 20:04:30 successfully validated input 23 | ``` 24 | -------------------------------------------------------------------------------- /src/cmd/openmetricsvalidator/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | "log" 6 | "os" 7 | 8 | "github.com/OpenObservability/OpenMetrics/src/validator" 9 | ) 10 | 11 | func main() { 12 | b, err := ioutil.ReadAll(os.Stdin) 13 | if err != nil { 14 | log.Fatalf("could not read stdin: %v", err) 15 | } 16 | v := validator.NewValidator(validator.ErrorLevelMust) 17 | if err := v.Validate(b); err != nil { 18 | log.Fatalf("failed to validate input: %v", err) 19 | } 20 | log.Println("successfully validated input") 21 | } 22 | -------------------------------------------------------------------------------- /src/cmd/scrapevalidator/README.md: -------------------------------------------------------------------------------- 1 | # scrapevalidator 2 | 3 | A command tool to scrape an OpenMetrics endpoint and validate against the OpenMetrics spec. 4 | 5 | ## Compile 6 | 7 | From the /src directory: 8 | 9 | ``` 10 | make scrapevalidator 11 | ``` 12 | 13 | ## Example 14 | 15 | Here are some examples of running the tool from the root directory. 16 | 17 | ``` 18 | ./bin/scrapevalidator --endpoint "http://localhost:9100/metrics" 19 | 2021/06/15 16:23:32 scraped successfully 20 | 2021/06/15 16:23:32 parsed 10 data points, validated successfully 21 | ``` -------------------------------------------------------------------------------- /src/cmd/scrapevalidator/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | "os" 7 | "time" 8 | 9 | "github.com/OpenObservability/OpenMetrics/src/cmd/scrapevalidator/scrape" 10 | "github.com/OpenObservability/OpenMetrics/src/validator" 11 | ) 12 | 13 | var ( 14 | endpointArg = flag.String("endpoint", "", "prom endpoint to validate, this is required") 15 | scrapeTimeoutArg = flag.Duration("scrape-timeout", 8*time.Second, "timeout for each scrape") 16 | scrapeIntervalArg = flag.Duration("scrape-interval", 10*time.Second, "time between scrapes") 17 | errorLevelArg = flag.String("error-level", "should", `OpenMetrics defines rules in different categories like "SHOULD" and "MUST", by default this parameter is set to "should" so that it validates the rules in both the "MUST" and "SHOULD" categories, the alternative value is "must" which validates only the rules in the "MUST" category.`) 18 | killAfter = flag.Duration("kill-after", 5*time.Minute, "kill the tool after") 19 | ) 20 | 21 | func main() { 22 | flag.Parse() 23 | 24 | if *endpointArg == "" { 25 | flag.Usage() 26 | os.Exit(2) 27 | } 28 | 29 | opts := []scrape.Option{ 30 | scrape.WithScrapeInterval(*scrapeIntervalArg), 31 | scrape.WithScrapeTimeout(*scrapeTimeoutArg), 32 | } 33 | if *errorLevelArg != "" { 34 | el, err := validator.NewErrorLevel(*errorLevelArg) 35 | if err != nil { 36 | log.Fatalf("invalid error level: %v", err) 37 | } 38 | opts = append(opts, scrape.WithErrorLevel(el)) 39 | } 40 | 41 | s := scrape.NewLoop(*endpointArg, opts...) 42 | s.Run(*killAfter) 43 | } 44 | -------------------------------------------------------------------------------- /src/cmd/scrapevalidator/scrape/loop.go: -------------------------------------------------------------------------------- 1 | package scrape 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | "github.com/OpenObservability/OpenMetrics/src/validator" 9 | ) 10 | 11 | // Option sets options in Loop. 12 | type Option func(*Loop) 13 | 14 | // WithScrapeTimeout sets the scrape timeout. 15 | func WithScrapeTimeout(timeout time.Duration) Option { 16 | return func(l *Loop) { 17 | l.scrapeTimeout = timeout 18 | } 19 | } 20 | 21 | // WithScrapeInterval sets the scrape interval. 22 | func WithScrapeInterval(interval time.Duration) Option { 23 | return func(l *Loop) { 24 | l.scrapeInterval = interval 25 | } 26 | } 27 | 28 | // WithErrorLevel sets the error level. 29 | func WithErrorLevel(el validator.ErrorLevel) Option { 30 | return func(l *Loop) { 31 | l.validator = validator.NewValidator(el) 32 | } 33 | } 34 | 35 | // Loop and perform scrape and validate in a loop. 36 | type Loop struct { 37 | validator *validator.OpenMetricsValidator 38 | scraper scraper 39 | scrapeTimeout time.Duration 40 | scrapeInterval time.Duration 41 | } 42 | 43 | // NewLoop creates a new scrape and validate loop. 44 | func NewLoop( 45 | endpoint string, 46 | opts ...Option, 47 | ) *Loop { 48 | l := &Loop{ 49 | validator: validator.NewValidator(validator.ErrorLevelMust), 50 | scraper: newSimpleScraper(endpoint), 51 | } 52 | for _, opt := range opts { 53 | opt(l) 54 | } 55 | return l 56 | } 57 | 58 | // Run runs the loop. 59 | func (l *Loop) Run(killAfter time.Duration) { 60 | l.runOnce() 61 | 62 | ticker := time.NewTicker(l.scrapeInterval) 63 | defer ticker.Stop() 64 | 65 | for { 66 | select { 67 | case <-ticker.C: 68 | l.runOnce() 69 | case <-time.After(killAfter): 70 | return 71 | } 72 | } 73 | } 74 | 75 | func (l *Loop) runOnce() { 76 | ctx, cancel := context.WithTimeout(context.Background(), l.scrapeTimeout) 77 | defer cancel() 78 | 79 | b, err := l.scraper.Scrape(ctx) 80 | if err != nil { 81 | log.Printf("scrape failed: %v\n", err) 82 | return 83 | } 84 | log.Println("scraped successfully") 85 | 86 | if err := l.validator.Validate(b); err != nil { 87 | l.validator.Reset() 88 | log.Printf("validation failed: %v\n", err) 89 | return 90 | } 91 | log.Println("validated successfully") 92 | } 93 | -------------------------------------------------------------------------------- /src/cmd/scrapevalidator/scrape/scraper.go: -------------------------------------------------------------------------------- 1 | package scrape 2 | 3 | import ( 4 | "context" 5 | "io/ioutil" 6 | "net/http" 7 | ) 8 | 9 | type scraper interface { 10 | Scrape(ctx context.Context) ([]byte, error) 11 | } 12 | 13 | type simpleScraper struct { 14 | addr string 15 | } 16 | 17 | func newSimpleScraper(addr string) *simpleScraper { 18 | return &simpleScraper{addr: addr} 19 | } 20 | 21 | func (s simpleScraper) Scrape(ctx context.Context) ([]byte, error) { 22 | resp, err := http.Get(s.addr) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return ioutil.ReadAll(resp.Body) 27 | } 28 | -------------------------------------------------------------------------------- /src/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/OpenObservability/OpenMetrics/src 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/linode/linodego v1.2.1 // indirect 7 | github.com/prometheus/prometheus v1.8.2-0.20210629155649-1a1394fc5873 8 | github.com/stretchr/testify v1.7.0 9 | go.uber.org/multierr v1.7.0 10 | ) 11 | -------------------------------------------------------------------------------- /tests/implementations/prometheus_client_python_parser/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:latest 2 | 3 | RUN pip install -Iv prometheus_client==0.9.0 4 | 5 | RUN mkdir /src 6 | 7 | ADD parser.py /src/parser.py 8 | 9 | CMD ["python","/src/parser.py"] 10 | -------------------------------------------------------------------------------- /tests/implementations/prometheus_client_python_parser/parser.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from prometheus_client.openmetrics.parser import text_string_to_metric_families 3 | 4 | input = sys.stdin.read() 5 | families = text_string_to_metric_families(input) 6 | print(list(families)) 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_blank_line/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_blank_line/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_clashing_names_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # TYPE a counter 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_clashing_names_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_clashing_names_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a info 2 | # TYPE a counter 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_clashing_names_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_clashing_names_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a_created gauge 2 | # TYPE a counter 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_clashing_names_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_10/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_10/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_11/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} -1 3 | a_gcount -1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_11/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_12/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_12/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_13/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} 1 3 | a_gsum -1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_13/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_14/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} 1 3 | a_gsum NaN 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_14/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_15/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a_sum NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_15/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_16/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a_count NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_16/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_17/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a_sum -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_17/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_18/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a_count -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_18/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_19/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a{quantile="0.5"} -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_19/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_sum NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_count NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_4/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_5/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_sum -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_count -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} -1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_8/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="-1.0"} 1 3 | a_bucket{le="+Inf"} 2 4 | a_sum -1 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_9/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="-1.0"} 1 3 | a_bucket{le="+Inf"} 2 4 | a_sum 1 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_counter_values_9/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_complex_chars/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {a="Ơ̸̡̧̻̲͆p̵̱̰̰̐ȩ̸̞̭̋͋̾̈́͝n̸̠̯̭̥̠̈́̌̉̐M̵̛̝͆̊͆͐e̴͚͚͛̌ţ̷̫͚͌̕̚r̵͕̲̋̚į̶̤̰̥̻̬̩̊̊̔̂͝c̸̱̖̀͛̊̕͝ş̷̽̌̀́̄789012345678901234567890123456789"} 1 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_complex_chars/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label characters exceed 128 code points, but fewer than 128 glyphs", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_timestamp_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 # {a="b"} 0.5 NaN 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_timestamp_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_timestamp_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 # {a="b"} 0.5 Inf 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_timestamp_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_timestamp_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 # {a="b"} 0.5 -Inf 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplar_timestamp_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "no exemplar when opening # is included", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1# {} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "empty exemplar label set", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_10/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 1 # id="a"} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_10/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label set missing opening brace", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_11/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 1 #id=" # "} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_11/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label set missing opening brace and preceeding whitespace", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_12/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 1 id=" # "} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_12/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar malformed but still contains # on the line", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 #{} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label set missing preceding whitespace", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {}1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label set missing following whitespace", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_4/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar with whitespace following exemplar value missing timestamp", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_5/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {} 1 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar with trailing whitespace after timestamp", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {a="23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"} 1 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label characters exceed max length of 128", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {} 0x1p-3 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar with invalid scientific notation float for exemplar value", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_8/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {} 1 0x1p-3 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar with invalid scientific notation float for exemplar timestamp", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_9/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_total 1 1 # {id="a"} 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_9/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar missing exemplar value", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_metric_types_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 1 # {a="b"} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_metric_types_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_metric_types_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a info 2 | a_info 1 # {a="b"} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_metric_types_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_metric_types_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a stateset 2 | a{a="b"} 1 # {c="d"} 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_metric_types_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_sum 1 # {a="b"} 0.5 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_sum 1 # {a="b"} 0.5 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a_bucket gauge 2 | a_bucket 1 # {a="b"} 0.5 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | a_created 1 # {a="b"} 0.5 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_exemplars_on_unallowed_samples_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_sum{a="1"} 0 3 | a_bucket{a="2",le="+Inf"} 0 4 | a_count{a="2"} 0 5 | a_sum{a="2"} 0 6 | a_bucket{a="1",le="+Inf"} 0 7 | a_count{a="1"} 0 8 | # EOF 9 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{a="1",le="1"} 0 3 | a_bucket{a="2",le="+Inf""} 0 4 | a_bucket{a="1",le="+Inf"} 0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_10/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 0 3 | a 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_10/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_gsum{a="1"} 0 3 | a_gsum{a="2"} 0 4 | a_gcount{a="1"} 0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | quantile{quantile="0"} 0 3 | a_sum{a="1"} 0 4 | quantile{quantile="1"} 0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_4/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 -1 3 | a 0 -2 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_5/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 -1 3 | a 0 -1.1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 1 3 | a 0 -1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 1.1 3 | a 0 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_8/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 1 3 | a 0 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_9/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 0 3 | a 0 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_grouping_or_ordering_9/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_0/metrics: -------------------------------------------------------------------------------- 1 | # HELP 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_1/metrics: -------------------------------------------------------------------------------- 1 | # HELP 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_2/metrics: -------------------------------------------------------------------------------- 1 | # HELP a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_3/metrics: -------------------------------------------------------------------------------- 1 | # HELP a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_4/metrics: -------------------------------------------------------------------------------- 1 | # HELP a meh 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_help_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_sum 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 0 3 | a_sum 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_10/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="1"} 1 3 | a_bucket{le="2"} 1 4 | a_bucket{le="+Inf"} 0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_10/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_11/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 0 3 | a_count 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_11/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_12/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+INF"} 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_12/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_13/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_count 1 3 | a_bucket{le="+Inf"} 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_13/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "histogram with count that doesn't match the +Inf bucket", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_14/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} 0 3 | a_gcount 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_14/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "gauge histogram with _gcount but no _gsum", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 0 3 | a_count 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="-1"} 0 3 | a_bucket{le="+Inf"} 0 4 | a_sum 0 5 | a_count 0 6 | # EOF 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_4/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 0 3 | #a_sum 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_5/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 0 3 | #a_count 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_gsum 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} 1 3 | a_gsum -1 4 | a_gcount 1 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_8/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket{le="+Inf"} 0 3 | a_gsum 0 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_9/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="2"} 0 3 | a_bucket{le="1"} 0 4 | a_bucket{le="+Inf"} 0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_histograms_9/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "must have buckets in order", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": false 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_info_and_stateset_values_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a info 2 | a_info{foo="bar"} 2 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_info_and_stateset_values_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_info_and_stateset_values_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a stateset 2 | a{a="bar"} 2 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_info_and_stateset_values_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_0/metrics: -------------------------------------------------------------------------------- 1 | a{1="1"} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_1/metrics: -------------------------------------------------------------------------------- 1 | a{1="1"}1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_2/metrics: -------------------------------------------------------------------------------- 1 | a{a="1",a="1"} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_3/metrics: -------------------------------------------------------------------------------- 1 | a{a="1"b} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_4/metrics: -------------------------------------------------------------------------------- 1 | a{1=" # "} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_5/metrics: -------------------------------------------------------------------------------- 1 | a{a=" # ",a=" # "} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_6/metrics: -------------------------------------------------------------------------------- 1 | a{a=" # "}1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_7/metrics: -------------------------------------------------------------------------------- 1 | a{a=" # ",b=}1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_8/metrics: -------------------------------------------------------------------------------- 1 | a{a=" # "b}1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_invalid_labels_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata/metrics: -------------------------------------------------------------------------------- 1 | # FOO a x 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata_in_wrong_place_0/metrics: -------------------------------------------------------------------------------- 1 | # HELP a x 2 | a 1 3 | # TYPE a gauge 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata_in_wrong_place_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata_in_wrong_place_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | a 1 3 | # HELP a gauge 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata_in_wrong_place_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata_in_wrong_place_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a_s gauge 2 | a_s 1 3 | # UNIT a_s s 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metadata_in_wrong_place_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metric_names_0/metrics: -------------------------------------------------------------------------------- 1 | 0a 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metric_names_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metric_names_1/metrics: -------------------------------------------------------------------------------- 1 | a.b 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metric_names_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metric_names_2/metrics: -------------------------------------------------------------------------------- 1 | a-b 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_metric_names_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_0/metrics: -------------------------------------------------------------------------------- 1 | a{a} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_1/metrics: -------------------------------------------------------------------------------- 1 | a{a"value"} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_2/metrics: -------------------------------------------------------------------------------- 1 | a{a""} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_3/metrics: -------------------------------------------------------------------------------- 1 | a{a=} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_4/metrics: -------------------------------------------------------------------------------- 1 | a{a="} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_equal_or_label_value_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_extra_commas_0/metrics: -------------------------------------------------------------------------------- 1 | a{a="1"b="2"} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_extra_commas_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_extra_commas_1/metrics: -------------------------------------------------------------------------------- 1 | a{a="1",,b="2"} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_extra_commas_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_extra_commas_2/metrics: -------------------------------------------------------------------------------- 1 | a{a="1",b="2",} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_extra_commas_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a{quantile="-1"} 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a{quantile="foo"} 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a{quantile="1.01"} 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_4/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | a{quantile="NaN"} 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_5/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | a_bucket 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a stateset 2 | a 0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_invalid_labels_for_a_type_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_wrong_quotes_on_label_value_0/metrics: -------------------------------------------------------------------------------- 1 | a{a=1} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_wrong_quotes_on_label_value_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_wrong_quotes_on_label_value_1/metrics: -------------------------------------------------------------------------------- 1 | a{a="1} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_wrong_quotes_on_label_value_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_wrong_quotes_on_label_value_2/metrics: -------------------------------------------------------------------------------- 1 | a{a='1'} 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_or_wrong_quotes_on_label_value_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_value_0/metrics: -------------------------------------------------------------------------------- 1 | a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_value_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_value_1/metrics: -------------------------------------------------------------------------------- 1 | a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_missing_value_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_no_eof/metrics: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/tests/testdata/parsers/bad_no_eof/metrics -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_no_eof/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_0/metrics: -------------------------------------------------------------------------------- 1 | # HELP a 2 | # HELP a 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_1/metrics: -------------------------------------------------------------------------------- 1 | # HELP a x 2 | # HELP a x 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a untyped 2 | # TYPE a untyped 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_3/metrics: -------------------------------------------------------------------------------- 1 | # UNIT a_s s 2 | # UNIT a_s s 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_repeated_metadata_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a stateset 2 | a 2 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a info 2 | a 2 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a stateset 2 | a 2.0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a info 2 | a 2.0 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_stateset_info_values_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_text_after_eof_0/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | # EOF 3 | blah -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_text_after_eof_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_text_after_eof_1/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | # EOFblah -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_text_after_eof_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_0/metrics: -------------------------------------------------------------------------------- 1 | a 1 z 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_1/metrics: -------------------------------------------------------------------------------- 1 | a 1 1z 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_2/metrics: -------------------------------------------------------------------------------- 1 | a 1 1_2 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_3/metrics: -------------------------------------------------------------------------------- 1 | a 1 1.1.1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_4/metrics: -------------------------------------------------------------------------------- 1 | a 1 NaN 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_5/metrics: -------------------------------------------------------------------------------- 1 | a 1 Inf 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_6/metrics: -------------------------------------------------------------------------------- 1 | a 1 Inf 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_7/metrics: -------------------------------------------------------------------------------- 1 | a 1 -Inf 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_8/metrics: -------------------------------------------------------------------------------- 1 | a 1 0x1p-3 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_timestamp_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_2/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_3/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_4/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a meh 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_5/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a meh 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a untyped 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_type_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_0/metrics: -------------------------------------------------------------------------------- 1 | # UNIT 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_1/metrics: -------------------------------------------------------------------------------- 1 | # UNIT 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_2/metrics: -------------------------------------------------------------------------------- 1 | # UNIT a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_3/metrics: -------------------------------------------------------------------------------- 1 | # UNIT a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_4/metrics: -------------------------------------------------------------------------------- 1 | # UNIT a seconds 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_5/metrics: -------------------------------------------------------------------------------- 1 | # UNIT a_seconds seconds 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_6/metrics: -------------------------------------------------------------------------------- 1 | # TYPE x_u info 2 | # UNIT x_u u 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_7/metrics: -------------------------------------------------------------------------------- 1 | # TYPE x_u stateset 2 | # UNIT x_u u 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_unit_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_0/metrics: -------------------------------------------------------------------------------- 1 | a a 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_1/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_10/metrics: -------------------------------------------------------------------------------- 1 | a 0X1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_10/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_11/metrics: -------------------------------------------------------------------------------- 1 | a 0o1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_11/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_12/metrics: -------------------------------------------------------------------------------- 1 | a 0O1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_12/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_2/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_2/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_3/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_3/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_4/metrics: -------------------------------------------------------------------------------- 1 | a 1_2 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_4/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_5/metrics: -------------------------------------------------------------------------------- 1 | a 0x1p-3 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_5/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_6/metrics: -------------------------------------------------------------------------------- 1 | a 0x1P-3 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_6/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_7/metrics: -------------------------------------------------------------------------------- 1 | a 0b1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_7/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_8/metrics: -------------------------------------------------------------------------------- 1 | a 0B1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_8/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_9/metrics: -------------------------------------------------------------------------------- 1 | a 0x1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/bad_value_9/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": false 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/counter_exemplars/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total 0 123 # {a="b"} 0.5 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/counter_exemplars/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/counter_exemplars_empty_brackets/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total{} 0 123 # {a="b"} 0.5 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/counter_exemplars_empty_brackets/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/counter_unit/metrics: -------------------------------------------------------------------------------- 1 | # HELP cc_seconds A counter 2 | # TYPE cc_seconds counter 3 | # UNIT cc_seconds seconds 4 | cc_seconds_total 1.0 5 | cc_seconds_created 123.456 6 | # EOF 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/counter_unit/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/duplicate_timestamps_0/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a{a="1",foo="bar"} 1 0.0000000000 4 | a{a="1",foo="bar"} 2 0.0000000001 5 | a{a="1",foo="bar"} 3 0.0000000010 6 | a{a="2",foo="bar"} 4 0.0000000000 7 | a{a="2",foo="bar"} 5 0.0000000001 8 | # EOF 9 | -------------------------------------------------------------------------------- /tests/testdata/parsers/duplicate_timestamps_0/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/duplicate_timestamps_1/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a{a="1",foo="bar"} 1 0 4 | a{a="1",foo="bar"} 2 0 5 | a{a="1",foo="bar"} 3 0 6 | a{a="2",foo="bar"} 4 0 7 | a{a="2",foo="bar"} 5 0 8 | # EOF 9 | -------------------------------------------------------------------------------- /tests/testdata/parsers/duplicate_timestamps_1/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_brackets/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total{} 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_brackets/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_help/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a 3 | a_total 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_help/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_label/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total{foo="bar"} 1 4 | a_total{foo=""} 2 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_label/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_metadata/metrics: -------------------------------------------------------------------------------- 1 | # HELP a 2 | # UNIT a 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/empty_metadata/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/escaping/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a he\n\\l\tp 3 | a_total{foo="b\"a\nr"} 1 4 | a_total{foo="b\\a\z"} 2 5 | a_total{foo="b\"a\nr # "} 3 6 | a_total{foo="b\\a\z # "} 4 7 | # EOF 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/escaping/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/exemplars_wide_chars/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | a_bucket{le="+Inf"} 1 # {a="☃345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"} 1 1 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/exemplars_wide_chars/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "exemplar label characters exactly 128 code points, which exceed 128 bytes", 3 | "type": "text", 4 | "file": "metrics", 5 | "shouldParse": true 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/exemplars_with_hash_in_label_values/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | # HELP a help 3 | a_bucket{le="1.0",foo="bar # "} 0 # {a="b",foo="bar # bar"} 0.5 4 | a_bucket{le="2.0",foo="bar # "} 2 # {a="c",foo="bar # bar"} 0.5 5 | a_bucket{le="+Inf",foo="bar # "} 3 # {a="d",foo="bar # bar"} 4 6 | # EOF 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/exemplars_with_hash_in_label_values/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/float_gauge/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a 1.2 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/float_gauge/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/gaugehistogram_exemplars/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | # HELP a help 3 | a_bucket{le="1.0"} 0 123 # {a="b"} 0.5 4 | a_bucket{le="2.0"} 2 123 # {a="c"} 0.5 5 | a_bucket{le="+Inf"} 3 123 # {a="d"} 4 123 6 | # EOF 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/gaugehistogram_exemplars/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/hash_in_label_value/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total{foo="foo # bar"} 1 4 | a_total{foo="} foo # bar # "} 1 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/hash_in_label_value/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/help_escaping/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a0 counter 2 | # HELP a0 foo 3 | a0_total{foo="bar"} 1 4 | # TYPE a1 counter 5 | # HELP a1 \foo 6 | a1_total{foo="bar"} 1 7 | # TYPE a2 counter 8 | # HELP a2 \\foo 9 | a2_total{foo="bar"} 1 10 | # TYPE a3 counter 11 | # HELP a3 foo\\ 12 | a3_total{foo="bar"} 1 13 | # TYPE a4 counter 14 | # HELP a4 \\ 15 | a4_total{foo="bar"} 1 16 | # TYPE a5 counter 17 | # HELP a5 \n 18 | a5_total{foo="bar"} 1 19 | # TYPE a6 counter 20 | # HELP a6 \\n 21 | a6_total{foo="bar"} 1 22 | # TYPE a7 counter 23 | # HELP a7 \\\n 24 | a7_total{foo="bar"} 1 25 | # TYPE a8 counter 26 | # HELP a8 \" 27 | a8_total{foo="bar"} 1 28 | # TYPE a9 counter 29 | # HELP a9 \\" 30 | a9_total{foo="bar"} 1 31 | # EOF 32 | -------------------------------------------------------------------------------- /tests/testdata/parsers/help_escaping/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/histogram_exemplars/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | # HELP a help 3 | a_bucket{le="1.0"} 0 # {a="b"} 0.5 4 | a_bucket{le="2.0"} 2 # {a="c"} 0.5 5 | a_bucket{le="+Inf"} 3 # {a="2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"} 4 123 6 | # EOF 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/histogram_exemplars/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/histogram_noncanonical/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | # HELP a help 3 | a_bucket{le="0"} 0 4 | a_bucket{le="0.00000000001"} 0 5 | a_bucket{le="0.0000000001"} 0 6 | a_bucket{le="1e-04"} 0 7 | a_bucket{le="1.1e-4"} 0 8 | a_bucket{le="1.1e-3"} 0 9 | a_bucket{le="1.1e-2"} 0 10 | a_bucket{le="1"} 0 11 | a_bucket{le="1e+05"} 0 12 | a_bucket{le="10000000000"} 0 13 | a_bucket{le="100000000000.0"} 0 14 | a_bucket{le="+Inf"} 3 15 | a_count 3 16 | a_sum 2 17 | # EOF 18 | -------------------------------------------------------------------------------- /tests/testdata/parsers/histogram_noncanonical/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/info_timestamps/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a info 2 | # HELP a help 3 | a_info{a="1",foo="bar"} 1 1 4 | a_info{a="2",foo="bar"} 1 0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/info_timestamps/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/label_escaping/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a0 counter 2 | # HELP a0 help 3 | a0_total{foo="foo",bar="baz"} 1 4 | # TYPE a1 counter 5 | # HELP a1 help 6 | a1_total{foo="\foo",bar="baz"} 1 7 | # TYPE a2 counter 8 | # HELP a2 help 9 | a2_total{foo="\\foo",bar="baz"} 1 10 | # TYPE a3 counter 11 | # HELP a3 help 12 | a3_total{foo="foo\\",bar="baz"} 1 13 | # TYPE a4 counter 14 | # HELP a4 help 15 | a4_total{foo="\\",bar="baz"} 1 16 | # TYPE a5 counter 17 | # HELP a5 help 18 | a5_total{foo="\n",bar="baz"} 1 19 | # TYPE a6 counter 20 | # HELP a6 help 21 | a6_total{foo="\\n",bar="baz"} 1 22 | # TYPE a7 counter 23 | # HELP a7 help 24 | a7_total{foo="\\\n",bar="baz"} 1 25 | # TYPE a8 counter 26 | # HELP a8 help 27 | a8_total{foo="\"",bar="baz"} 1 28 | # TYPE a9 counter 29 | # HELP a9 help 30 | a9_total{foo="\\\"",bar="baz"} 1 31 | # EOF 32 | -------------------------------------------------------------------------------- /tests/testdata/parsers/label_escaping/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/labels_and_infinite/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a{foo="bar"} +Inf 4 | a{foo="baz"} -Inf 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/labels_and_infinite/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/labels_with_curly_braces/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total{foo="bar",bar="b{a}z"} 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/labels_with_curly_braces/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/leading_zeros_float_gauge/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a 0000000000000000000000000000000000000000001.2e-1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/leading_zeros_float_gauge/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/leading_zeros_simple_gauge/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a 0000000000000000000000000000000000000000001 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/leading_zeros_simple_gauge/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/nan/metrics: -------------------------------------------------------------------------------- 1 | a NaN 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/nan/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/nan_gauge/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a NaN 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/nan_gauge/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/negative_bucket_gaugehistogram/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | # HELP a help 3 | a_bucket{le="-1.0"} 1 4 | a_bucket{le="1.0"} 2 5 | a_bucket{le="+Inf"} 3 6 | a_gcount 3 7 | a_gsum -5 8 | # EOF 9 | -------------------------------------------------------------------------------- /tests/testdata/parsers/negative_bucket_gaugehistogram/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/negative_bucket_histogram/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | # HELP a help 3 | a_bucket{le="-1.0"} 0 4 | a_bucket{le="1.0"} 1 5 | a_bucket{le="+Inf"} 3 6 | # EOF 7 | -------------------------------------------------------------------------------- /tests/testdata/parsers/negative_bucket_histogram/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/no_metadata/metrics: -------------------------------------------------------------------------------- 1 | a 1 2 | # EOF 3 | -------------------------------------------------------------------------------- /tests/testdata/parsers/no_metadata/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/no_newline_after_eof/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a 1 4 | # EOF -------------------------------------------------------------------------------- /tests/testdata/parsers/no_newline_after_eof/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/null_byte/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | # EOF 4 | -------------------------------------------------------------------------------- /tests/testdata/parsers/null_byte/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/roundtrip/metrics: -------------------------------------------------------------------------------- 1 | # HELP go_gc_duration_seconds A summary of the GC invocation durations. 2 | # TYPE go_gc_duration_seconds summary 3 | go_gc_duration_seconds{quantile="0.0"} 0.013300656000000001 4 | go_gc_duration_seconds{quantile="0.25"} 0.013638736 5 | go_gc_duration_seconds{quantile="0.5"} 0.013759906 6 | go_gc_duration_seconds{quantile="0.75"} 0.013962066 7 | go_gc_duration_seconds{quantile="1.0"} 0.021383540000000003 8 | go_gc_duration_seconds_sum 56.12904785 9 | go_gc_duration_seconds_count 7476.0 10 | # HELP go_goroutines Number of goroutines that currently exist. 11 | # TYPE go_goroutines gauge 12 | go_goroutines 166.0 13 | # HELP prometheus_local_storage_indexing_batch_duration_milliseconds Quantiles for batch indexing duration in milliseconds. 14 | # TYPE prometheus_local_storage_indexing_batch_duration_milliseconds summary 15 | prometheus_local_storage_indexing_batch_duration_milliseconds{quantile="0.5"} NaN 16 | prometheus_local_storage_indexing_batch_duration_milliseconds{quantile="0.9"} NaN 17 | prometheus_local_storage_indexing_batch_duration_milliseconds{quantile="0.99"} NaN 18 | prometheus_local_storage_indexing_batch_duration_milliseconds_sum 871.5665949999999 19 | prometheus_local_storage_indexing_batch_duration_milliseconds_count 229.0 20 | # HELP process_cpu_seconds Total user and system CPU time spent in seconds. 21 | # TYPE process_cpu_seconds counter 22 | process_cpu_seconds_total 29323.4 23 | # HELP process_virtual_memory_bytes Virtual memory size in bytes. 24 | # TYPE process_virtual_memory_bytes gauge 25 | process_virtual_memory_bytes 2.478268416e+09 26 | # HELP prometheus_build_info A metric with a constant '1' value labeled by version, revision, and branch from which Prometheus was built. 27 | # TYPE prometheus_build_info gauge 28 | prometheus_build_info{branch="HEAD",revision="ef176e5",version="0.16.0rc1"} 1.0 29 | # HELP prometheus_local_storage_chunk_ops The total number of chunk operations by their type. 30 | # TYPE prometheus_local_storage_chunk_ops counter 31 | prometheus_local_storage_chunk_ops_total{type="clone"} 28.0 32 | prometheus_local_storage_chunk_ops_total{type="create"} 997844.0 33 | prometheus_local_storage_chunk_ops_total{type="drop"} 1.345758e+06 34 | prometheus_local_storage_chunk_ops_total{type="load"} 1641.0 35 | prometheus_local_storage_chunk_ops_total{type="persist"} 981408.0 36 | prometheus_local_storage_chunk_ops_total{type="pin"} 32662.0 37 | prometheus_local_storage_chunk_ops_total{type="transcode"} 980180.0 38 | prometheus_local_storage_chunk_ops_total{type="unpin"} 32662.0 39 | # HELP foo histogram Testing histogram buckets 40 | # TYPE foo histogram 41 | foo_bucket{le="0.0"} 0.0 42 | foo_bucket{le="1e-05"} 0.0 43 | foo_bucket{le="0.0001"} 0.0 44 | foo_bucket{le="0.1"} 8.0 45 | foo_bucket{le="1.0"} 10.0 46 | foo_bucket{le="10.0"} 17.0 47 | foo_bucket{le="100000.0"} 17.0 48 | foo_bucket{le="1e+06"} 17.0 49 | foo_bucket{le="1.55555555555552e+06"} 17.0 50 | foo_bucket{le="1e+23"} 17.0 51 | foo_bucket{le="+Inf"} 17.0 52 | foo_count 17.0 53 | foo_sum 324789.3 54 | foo_created 1.520430000123e+09 55 | # HELP bar histogram Testing with labels 56 | # TYPE bar histogram 57 | bar_bucket{a="b",le="+Inf"} 0.0 58 | bar_bucket{a="c",le="+Inf"} 0.0 59 | # EOF 60 | -------------------------------------------------------------------------------- /tests/testdata/parsers/roundtrip/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_counter/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_counter/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_gauge/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gauge 2 | # HELP a help 3 | a 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_gauge/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_gaugehistogram/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a gaugehistogram 2 | # HELP a help 3 | a_bucket{le="1.0"} 0 4 | a_bucket{le="+Inf"} 3 5 | a_gcount 3 6 | a_gsum 2 7 | # EOF 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_gaugehistogram/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_histogram/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a histogram 2 | # HELP a help 3 | a_bucket{le="1.0"} 0 4 | a_bucket{le="+Inf"} 3 5 | a_count 3 6 | a_sum 2 7 | # EOF 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_histogram/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_stateset/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a stateset 2 | # HELP a help 3 | a{a="bar"} 0 4 | a{a="foo"} 1.0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_stateset/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_summary/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | # HELP a help 3 | a_count 1 4 | a_sum 2 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/simple_summary/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/summary_quantiles/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a summary 2 | # HELP a help 3 | a_count 1 4 | a_sum 2 5 | a{quantile="0.5"} 0.7 6 | a{quantile="1"} 0.8 7 | # EOF 8 | -------------------------------------------------------------------------------- /tests/testdata/parsers/summary_quantiles/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/timestamps/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total{foo="1"} 1 000 4 | a_total{foo="2"} 1 0.0 5 | a_total{foo="3"} 1 1.1 6 | a_total{foo="4"} 1 12345678901234567890.1234567890 7 | a_total{foo="5"} 1 1.5e3 8 | # TYPE b counter 9 | # HELP b help 10 | b_total 2 1234567890 11 | # EOF 12 | -------------------------------------------------------------------------------- /tests/testdata/parsers/timestamps/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/type_help_switched/metrics: -------------------------------------------------------------------------------- 1 | # HELP a help 2 | # TYPE a counter 3 | a_total 1 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/type_help_switched/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/uint64_counter/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a counter 2 | # HELP a help 3 | a_total 9223372036854775808 4 | # EOF 5 | -------------------------------------------------------------------------------- /tests/testdata/parsers/uint64_counter/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/unit_gauge/metrics: -------------------------------------------------------------------------------- 1 | # TYPE a_seconds gauge 2 | # UNIT a_seconds seconds 3 | # HELP a_seconds help 4 | a_seconds 1 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/unit_gauge/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/untyped/metrics: -------------------------------------------------------------------------------- 1 | # HELP redis_connected_clients Redis connected clients 2 | # TYPE redis_connected_clients unknown 3 | redis_connected_clients{instance="rough-snowflake-web",port="6380"} 10.0 4 | redis_connected_clients{instance="rough-snowflake-web",port="6381"} 12.0 5 | # EOF 6 | -------------------------------------------------------------------------------- /tests/testdata/parsers/untyped/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "text", 3 | "file": "metrics", 4 | "shouldParse": true 5 | } 6 | -------------------------------------------------------------------------------- /website/Makefile: -------------------------------------------------------------------------------- 1 | get-sass: 2 | yarn 3 | 4 | netlify-production-build: get-sass 5 | hugo 6 | 7 | netlify-staging-build: get-sass 8 | hugo -b $(DEPLOY_PRIME_URL) 9 | 10 | dev: 11 | hugo server --disableFastRender 12 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # The OpenMetrics website 2 | 3 | The website for the OpenMetrics project is available at https://openmetrics.io. The site is built using the [Hugo](https://gohugo.io) static site generator and styled using the [Bulma](https://bulma.io) CSS framework. 4 | 5 | ## Infrastructure 6 | 7 | The site is deployed automatically using [Netlify](https://netlify.com) whenever changes are merged to the `master` branch. 8 | 9 | ## Setup 10 | 11 | In order to build the site, you'll need to have [Yarn](https://yarnpkg.com) and [Hugo](https://gohugo.io) (version 0.46 or later) installed and the OpenMetrics repo cloned locally: 12 | 13 | ```bash 14 | git clone https://github.com/OpenObservability/OpenMetrics 15 | cd OpenMetrics/website 16 | ``` 17 | 18 | ## Building 19 | 20 | In order to build the site, first install Bulma using Yarn: 21 | 22 | ```bash 23 | yarn 24 | ``` 25 | 26 | Then you can build the site using Hugo: 27 | 28 | ```bash 29 | hugo 30 | ``` 31 | 32 | ## Running the site locally 33 | 34 | To run the site in development mode: 35 | 36 | ```bash 37 | hugo server 38 | ``` 39 | 40 | Then open your browser to http://localhost:1313. Whenever you make changes to the site's assets, Hugo will trigger auto-reload in the browser. 41 | -------------------------------------------------------------------------------- /website/assets/sass/style.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | @import "sass/utilities/initial-variables" 4 | @import "sass/utilities/functions" 5 | 6 | @font-face 7 | font-family: "Gotham" 8 | src: url(/fonts/Gotham-Book.otf) 9 | 10 | $navbar-base-height: 5rem 11 | 12 | $red: #c42227 13 | $primary: $red 14 | $cncf-blue: #426cab 15 | $family-sans-serif: "Gotham", sans-serif 16 | $navbar-burger-color: $primary !important 17 | $navbar-height: $navbar-base-height 18 | $navbar-item-img-max-height: $navbar-base-height * .7 19 | $link: $primary 20 | $strong-color: $cncf-blue 21 | 22 | @import "sass/utilities/derived-variables" 23 | 24 | @import "bulma" 25 | 26 | %logo 27 | +desktop 28 | width: 30% 29 | +touch 30 | width: 70% 31 | 32 | .is-cncf-logo 33 | @extend %logo 34 | margin-top: 1.5rem 35 | 36 | .is-main-logo 37 | @extend %logo 38 | 39 | .has-text-cncf-blue 40 | color: $cncf-blue 41 | 42 | =bg-image($url) 43 | background-image: url($url) 44 | 45 | .page 46 | &.home 47 | .has-background-image 48 | background-color: $white-ter 49 | +bg-image("/images/hero-bg.png") 50 | 51 | .hero-foot 52 | margin: 1rem 4rem 53 | -------------------------------------------------------------------------------- /website/config.yaml: -------------------------------------------------------------------------------- 1 | title: The OpenMetrics project — Creating a standard for exposing metrics data 2 | baseurl: https://openmetrics.io 3 | languagecode: en 4 | disableKinds: [taxonomy, taxonomyTerm] 5 | 6 | params: 7 | description: | 8 | OpenMetrics is the official standard for metrics in the [Prometheus](https://prometheus.io/) ecosystem. With its support for examplars, it ties metrics and traces as closely and efficiently as never seen before. The [specification](https://github.com/OpenObservability/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md) covers semantics, data model, and wire format for cloud-native metrics at scale, with support for both text representation and Protocol Buffers. 9 | subdescription: | 10 | You can track the project's progress on the [OpenMetrics mailing list](https://groups.google.com/forum/m/#!forum/openmetrics). 11 | favicon: /images/logo/logo.png 12 | -------------------------------------------------------------------------------- /website/content/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/content/.gitkeep -------------------------------------------------------------------------------- /website/layouts/_default/baseof.html: -------------------------------------------------------------------------------- 1 | {{- $pageType := cond (.IsHome) "home" .Section }} 2 | 3 | 4 | 5 | {{- partial "meta.html" . }} 6 | {{ block "title" . }}{{ .Site.Title }}{{ end }} 7 | {{- partial "css.html" . }} 8 | 9 | 10 | {{ block "main" . }} 11 | {{ partial "hero.html" . }} 12 | {{ partial "cncf.html" . }} 13 | {{ end }} 14 | 15 | 16 | -------------------------------------------------------------------------------- /website/layouts/index.html: -------------------------------------------------------------------------------- 1 | {{ define "main" }} 2 | {{ end }} 3 | -------------------------------------------------------------------------------- /website/layouts/partials/cncf.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 | OpenMetrics is a Cloud Native Computing Foundation incubating project 6 |

7 | 8 | 9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /website/layouts/partials/css.html: -------------------------------------------------------------------------------- 1 | {{- $inServerMode := .Site.IsServer }} 2 | {{- $sass := "sass/style.sass" }} 3 | {{- $target := "css/style.css" }} 4 | {{- $bulma := "node_modules/bulma" }} 5 | {{- $template := "sass/style.sass" }} 6 | {{- $cssDevOpts := (dict "targetPath" $target "enableSourceMap" true "includePaths" (slice $bulma)) }} 7 | {{- $cssProdOpts := (dict "targetPath" $target "outputMode" "compressed" "includePaths" (slice $bulma)) }} 8 | {{- $cssOpts := cond $inServerMode $cssDevOpts $cssProdOpts }} 9 | {{- $css := resources.Get $sass | resources.ExecuteAsTemplate $template . | toCSS $cssOpts }} 10 | {{- if $inServerMode }} 11 | 12 | {{- else }} 13 | {{- $prodCss := $css | minify | fingerprint }} 14 | 15 | {{- end }} 16 | {{- $favicon := .Site.Params.favicon }} 17 | 18 | -------------------------------------------------------------------------------- /website/layouts/partials/hero.html: -------------------------------------------------------------------------------- 1 | {{- $description := .Site.Params.description }} 2 | {{- $subdescription := .Site.Params.subdescription }} 3 |
4 |
5 |
6 | 7 | 8 |

9 | {{ $description | markdownify }} 10 |

11 |
12 |
13 | 14 |
15 |
16 | 17 | {{ $subdescription | markdownify }} 18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /website/layouts/partials/meta.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "bulma": "^0.7.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /website/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/favicon.png -------------------------------------------------------------------------------- /website/static/fonts/Gotham-Book.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/fonts/Gotham-Book.otf -------------------------------------------------------------------------------- /website/static/images/hero-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/hero-bg.png -------------------------------------------------------------------------------- /website/static/images/logo/cncf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 13 | 14 | 18 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 36 | 38 | 41 | 43 | 44 | 45 | 47 | 50 | 51 | 55 | 57 | 58 | 61 | 62 | 63 | 64 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /website/static/images/logo/logo-rgb.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-rgb.eps -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text-rgb.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text-rgb.eps -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text.ai -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text.eps -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text.jpg -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text.pdf -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text.png -------------------------------------------------------------------------------- /website/static/images/logo/logo-with-text.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo-with-text.psd -------------------------------------------------------------------------------- /website/static/images/logo/logo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo.ai -------------------------------------------------------------------------------- /website/static/images/logo/logo.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo.eps -------------------------------------------------------------------------------- /website/static/images/logo/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo.jpg -------------------------------------------------------------------------------- /website/static/images/logo/logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo.pdf -------------------------------------------------------------------------------- /website/static/images/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo.png -------------------------------------------------------------------------------- /website/static/images/logo/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prometheus/OpenMetrics/3bb328ab04d26b25ac548d851619f90d15090e5d/website/static/images/logo/logo.psd -------------------------------------------------------------------------------- /website/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | bulma@^0.7.1: 6 | version "0.7.1" 7 | resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.7.1.tgz#73c2e3b2930c90cc272029cbd19918b493fca486" 8 | --------------------------------------------------------------------------------