{"id":19546296,"url":"https://github.com/hewlettpackard/prometheus-parser-rs","last_synced_at":"2025-04-26T19:32:33.710Z","repository":{"id":45871720,"uuid":"249842774","full_name":"HewlettPackard/prometheus-parser-rs","owner":"HewlettPackard","description":"a Rust library for parsing and validating Prometheus query expressions","archived":false,"fork":false,"pushed_at":"2024-04-25T10:12:19.000Z","size":53,"stargazers_count":12,"open_issues_count":3,"forks_count":4,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-25T11:30:52.616Z","etag":null,"topics":["linter","parser","prometheus","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HewlettPackard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-24T23:43:50.000Z","updated_at":"2024-03-09T16:38:35.000Z","dependencies_parsed_at":"2024-10-30T23:29:53.096Z","dependency_job_id":null,"html_url":"https://github.com/HewlettPackard/prometheus-parser-rs","commit_stats":{"total_commits":7,"total_committers":3,"mean_commits":"2.3333333333333335","dds":0.2857142857142857,"last_synced_commit":"ee10f7932daed9340c802bd50b11ef2afa18d22e"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HewlettPackard%2Fprometheus-parser-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HewlettPackard%2Fprometheus-parser-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HewlettPackard%2Fprometheus-parser-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HewlettPackard%2Fprometheus-parser-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HewlettPackard","download_url":"https://codeload.github.com/HewlettPackard/prometheus-parser-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251041593,"owners_count":21527223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linter","parser","prometheus","rust"],"created_at":"2024-11-11T03:44:13.446Z","updated_at":"2025-04-26T19:32:28.701Z","avatar_url":"https://github.com/HewlettPackard.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# prometheus-parser-rs\n\n[![docs.rs](https://docs.rs/prometheus-parser/badge.svg)](https://docs.rs/prometheus-parser/)\n\nprometheus-parser parses arbitrary Prometheus expressions into a syntax tree\nappropriate for syntax checking, linting, and general static analysis. It does\nnot depend on a Prometheus server and works entirely offline.\n\nThis library is implemented in pure Rust (using [pest]) with no knowledge of\nthe underlying Prometheus server implementation. It's been validated against\nthe public Prometheus syntax documentation and various publicly available alert\ncollections (e.g. [kubernetes-mixin]).\n\nNote that this crate doesn't try to _evaluate_ Prometheus expressions; consider\nusing [`promtool`'s unit testing][unit] for this purpose.\n\n[pest]: https://pest.rs/\n[unit]: https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/\n[kubernetes-mixin]: https://github.com/kubernetes-monitoring/kubernetes-mixin\n\n## Use cases\n\nThis library can be used to implement custom linting and static analysis tools,\nfor example:\n\n * Offline syntax checking with useful error messages (thanks to [pest])\n * Automatic code formatting\n * Various AST inspections:\n   * Ensuring expressions don't drop required labels for e.g. alert routing\n     (namespace, service, etc)\n   * Ensuring expressions don't make common mistakes that can cause spurious\n     alerts, e.g. division by zero with counters\n\n## Limitations\n\n * It doesn't try to evaluate expressions at all\n * It doesn't validate function calls or argument types, so `foo(bar, baz, qux)`\n   is considered at least _syntactically_ valid. Each function argument still\n   needs to parse to a real expression, though.\n   * The `return_value()` utility will raise soft errors on certain type errors\n     (via `ReturnKind::Unknown`)\n   * Note that Prometheus performs some extra query validation based on runtime\n     data and will return errors on e.g. label mismatches that we can't catch.\n * It properly parses most obscure elements of Prometheus syntax, however it's\n   not entirely lossless; equivalent expressions (e.g. `sum by (a) (foo{})` and\n   `sum (foo) by (a)`) will be evaluated identically, so expect minor output\n   differences if you use this to implement a formatter.\n * It probably doesn't parse entirely the same as the real Prometheus parser,\n   though care was taken to match it as closely as possible. That is, this\n   parser may consider expressions valid that Prometheus won't, or vice versa.\n   Please consider filing bugs for any differences.\n\n## Return value prediction\n\nThe library has a utility for predicting the return types of expressions based\nonly on the syntax tree. This may be useful for rough static analysis.\n\n * `Expression::return_value()` recursively computes an expected return type\n   (scalar, instant vector, range vector, etc) along with a set of label\n   operations. If for some reason this fails, `ReturnKind::Unknown` is returned\n   with a message explaining why.\n * `ReturnValue::passthrough(input_labels: \u0026[\u0026str])` can then be used predict\n   which output labels should be present for a given query. It accepts a list of\n   initial label names assumed to be present on the metrics (e.g. expected\n   metrics like `namespace`) and returns a set of expected output labels.\n\n   Note that additional labels may be returned: if expressions explicitly select\n   for labels, they'll be returned as well; an empty list of initial labels can be\n   used to see what extra labels an expression will query for.\n\n * `ReturnValue::drops(label: \u0026str)` determines which AST node, if any, dropped\n   the given input label.\n\n## Examples\n\n### [`examples/parse.rs`](./examples/parse.rs)\n\nThis can be used to dump the (slightly reduced) syntax tree for a given\nexpression.\n\nTry `cargo run --example parse 'foo'`:\n\n```bash\n$ cargo run --example parse 'count_values\n  by(service) (\"config_hash\", alertmanager_config_hash{job=\"alertmanager-main\",namespace=\"monitoring\"})\n  / on(service) group_left() label_replace(max by(name, job, namespace, controller)\n  (prometheus_operator_spec_replicas{controller=\"alertmanager\",job=\"prometheus-operator\",namespace=\"monitoring\"}),\n  \"service\", \"alertmanager-$1\", \"name\", \"(.*)\") !=\n  1'\n\nOperator {\n    kind: NotEqual,\n    lhs: Operator {\n        kind: Divide,\n        lhs: Function {\n            name: \"count_values\",\n            args: [\n                # ... snip ...\n            ],\n            aggregation: Some(\n                Aggregation {\n                    op: By,\n                    labels: [\n                        \"service\",\n                    ],\n                },\n            ),\n        },\n        rhs: Function {\n            name: \"label_replace\",\n            args: [\n                # ... snip ...\n            ],\n            aggregation: None,\n        },\n        matching: Some(\n            Matching {\n                op: On,\n                labels: [\n                    \"service\",\n                ],\n                group: Some(\n                    MatchingGroup {\n                        op: Left,\n                        labels: [],\n                    },\n                ),\n            },\n        ),\n    },\n    rhs: 1.0,\n    matching: None,\n}\n```\n\nNote that `Expression` has a `Debug` impl that somewhat reduces boilerplate\noutput. It makes debug output more readable, but the displayed object structure\nwon't exactly match the in-memory version. Specifically, if constructing your\nown AST objects, use the `.wrap()` utility functions present on most\n`Expression` subtypes to convert them to an `Expression`.\n\n### [`examples/reformat.rs`](./examples/reformat.rs)\n\nParses the input expression and reformats it using the default `Display` impl.\n\n```bash\n$ cargo run --example reformat 'sum by(bar)(foo)'\nsum(foo) by (bar)\n```\n\n### [`examples/return_value.rs`](./examples/return_value.rs)\n\nDisplays the raw `ReturnValue` computed for a given expression.\n\n```bash\n$ cargo run --example return_value 'foo(sum(foo))'\nReturnValue {\n    kind: InstantVector,\n    label_ops: [\n        LabelSetOpTuple {\n            op: Clear,\n            expression: Function {\n                name: \"sum\",\n                # ... snip ...\n            },\n            span: Some(\n                Span {\n                    start: 4,\n                    end: 12,\n                },\n            ),\n        },\n    ],\n}\n\n```\n\n### [`examples/label_drop.rs`](./examples/label_drop.rs)\n\nShows where a label is dropped in an expression, if at all.\n\n```bash\n$ cargo run --example label_drop 'foo(sum(foo))' namespace\nlabel 'namespace' is dropped:\n\nfoo(sum(foo))\n    --------\n\nparent expression: sum(foo)\n```\n\nIf an expression is invalid and has an unknown return type, a message will be\nprinted:\n\n```bash\n$ cargo run --example label_drop 'foo(sum(foo)) / bar[5m:]' namespace\nnote: expression return type is unknown, result may be inaccurate\n  reason:     rhs return type (RangeVector) is not valid in an operator\n  expression: foo(sum(foo)) / bar[5m:]\n\nlabel 'namespace' is not dropped\n```\n\n### [`examples/label_passthrough.rs`](./examples/label_passthrough.rs)\n\nShows the expected output labels for a given expression. Arguments after the\nexpression are labels that exist on all input metrics.\n\nAdditional labels may be returned that were not present in the input list; these\nwere inferred based on labels referenced in the expression.\n\n\n```bash\n$ cargo run --example label_passthrough 'sum by(bar)(foo)' baz\n{\n    \"bar\",\n}\n```\n\n## Contributing\n\nBug reports, feature requests, and pull requests are welcome! Be sure to read\nthough the [code of conduct] for some pointers to get started.\n\nNote that - as mentioned in the code of conduct - code contributions must\nindicate that you accept the [Developer Certificate of Origin][dco],\nessentially asserting you have the necessary rights to submit the code you're\ncontributing under the project's license (MIT). If you agree, simply pass `-s`\nto `git commit`:\n\n```bash\ngit commit -s [...]\n```\n\n... and Git will automatically append the required `Signed-off-by: ...` to the\nend of your commit message.\n\n[code of conduct]: ./CODE_OF_CONDUCT.md\n[dco]: https://developercertificate.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhewlettpackard%2Fprometheus-parser-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhewlettpackard%2Fprometheus-parser-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhewlettpackard%2Fprometheus-parser-rs/lists"}