cloudflare/pint
Publicmirrored from https://github.com/cloudflare/pintAvailable
docs/configuration.md
358lines · modecode
| 1 | --- |
| 2 | layout: default |
| 3 | title: Configuration |
| 4 | parent: Documentation |
| 5 | nav_order: 2 |
| 6 | --- |
| 7 | |
| 8 | # Configuration syntax |
| 9 | |
| 10 | ## Table of contents |
| 11 | {: .no_toc .text-delta } |
| 12 | |
| 13 | 1. TOC |
| 14 | {:toc} |
| 15 | |
| 16 | ## Regexp matchers |
| 17 | |
| 18 | All regexp patterns use [Go regexp](https://pkg.go.dev/regexp) module and are fully anchored. |
| 19 | This means that when you pass `.*` regexp expression internally it will be represented as |
| 20 | `^.*$`, where `^` indicates beginning of a string and `$` is the end of string. |
| 21 | This follows [PromQL behavior](https://prometheus.io/docs/prometheus/latest/querying/basics/) |
| 22 | for consistency with Prometheus. |
| 23 | If you have a string `alice bob john` and you want to match a substring `bob`, then be sure to use |
| 24 | `.*bob.*`. |
| 25 | |
| 26 | When using regexp matcher in checks configuration you can reference alerting and recording rule |
| 27 | fields in the regexp using [Go text/template](https://pkg.go.dev/text/template) syntax. |
| 28 | Rule fields are exposed as: |
| 29 | |
| 30 | - `$alert` - rule `alert` field |
| 31 | - `$record` - rule `record` field |
| 32 | - `$expr` - rule `expr` field |
| 33 | - `$for` - rule `for` field |
| 34 | - `$labels` - rule `labels` map, individual labels can be accessed as `$labels.foo` |
| 35 | - `$annotations` - rule `annotations` map, individual annotations can be accessed as `$annotations.foo` |
| 36 | |
| 37 | Accessing a field that's not present in the rule will return an empty string. |
| 38 | |
| 39 | ## Parser |
| 40 | |
| 41 | Configure how pint parses Prometheus rule files. |
| 42 | |
| 43 | Syntax: |
| 44 | |
| 45 | ```js |
| 46 | parser { |
| 47 | relaxed = [ "(.*)", ... ] |
| 48 | } |
| 49 | ``` |
| 50 | |
| 51 | - `relaxed` - by default pint will now parse all files in strict mode, where |
| 52 | all rule files must have the exact syntax Prometheus expects: |
| 53 | |
| 54 | ```yaml |
| 55 | groups: |
| 56 | - name: example |
| 57 | rules: |
| 58 | - record: ... |
| 59 | expr: ... |
| 60 | ``` |
| 61 | |
| 62 | If you're using pint to lint rules that are embedded inside a different structure |
| 63 | you can set this option to allow fuzzy parsing, which will try to find rule |
| 64 | definitions anywhere in the file, without requiring `groups -> rules -> rule` |
| 65 | structure to be present. |
| 66 | This option takes a list of file patterns, all files matching those regexp rules |
| 67 | will be parsed in relaxed mode. |
| 68 | |
| 69 | ## CI |
| 70 | |
| 71 | Configure continuous integration environments. |
| 72 | |
| 73 | Syntax: |
| 74 | |
| 75 | ```js |
| 76 | ci { |
| 77 | include = [ "(.*)", ... ] |
| 78 | maxCommits = 20 |
| 79 | baseBranch = "master" |
| 80 | } |
| 81 | ``` |
| 82 | |
| 83 | - `include` - list of file patterns to check when running checks. Only files |
| 84 | matching those regexp rules will be checked, other modified files will be ignored. |
| 85 | - `maxCommits` - by default pint will try to find all commits on the current branch, |
| 86 | this requires full git history to be present, if we have a shallow clone this |
| 87 | might fail to find only current branch commits and give us a huge list. |
| 88 | If the number of commits returned by branch discovery is more than `maxCommits` |
| 89 | then pint will fail to run. |
| 90 | - `baseBranch` - base branch to compare `HEAD` commit with when calculating the list |
| 91 | of commits to check. |
| 92 | |
| 93 | ## Repository |
| 94 | |
| 95 | Configure supported code hosting repository, used for reporting PR checks from CI |
| 96 | back to the repository, to be displayed in the PR UI. |
| 97 | Currently it only supports [BitBucket](https://bitbucket.org/) and [GitHub](https://github.com/). |
| 98 | |
| 99 | **NOTE**: BitBucket integration requires `BITBUCKET_AUTH_TOKEN` environment variable |
| 100 | to be set. It should contain a personal access token used to authenticate with the API. |
| 101 | |
| 102 | **NOTE**: GitHub integration requires `GITHUB_AUTH_TOKEN` environment variable |
| 103 | to be set to a personal access key that can access your repository. |
| 104 | |
| 105 | **NOTE** Pull request number must be known to pint so it can add comments if it detects any problems. |
| 106 | If pint is run as part of GitHub actions workflow then this number will be detected from `GITHUB_REF` |
| 107 | environment variable. For other use cases `GITHUB_PULL_REQUEST_NUMBER` environment variable must be set |
| 108 | with the pull request number. |
| 109 | |
| 110 | Syntax: |
| 111 | |
| 112 | ```js |
| 113 | repository { |
| 114 | bitbucket { |
| 115 | uri = "https://..." |
| 116 | timeout = "1m" |
| 117 | project = "..." |
| 118 | repository = "..." |
| 119 | } |
| 120 | } |
| 121 | ``` |
| 122 | |
| 123 | - `bitbucket:uri` - base URI of this repository, will be used for HTTP |
| 124 | requests to the BitBucket API. |
| 125 | - `bitbucket:timeout` - timeout to be used for API requests, defaults to 1 minute. |
| 126 | - `bitbucket:project` - name of the BitBucket project for this repository. |
| 127 | - `bitbucket:repository` - name of the BitBucket repository. |
| 128 | |
| 129 | ```js |
| 130 | repository { |
| 131 | github { |
| 132 | baseuri = "https://..." |
| 133 | uploaduri = "https://..." |
| 134 | timeout = "1m" |
| 135 | owner = "..." |
| 136 | repo = "..." |
| 137 | } |
| 138 | } |
| 139 | ``` |
| 140 | |
| 141 | - `github:baseuri` - base URI of GitHub or GitHub enterprise, will be used for HTTP requests to the GitHub API. |
| 142 | If not set `pint` will try to use `GITHUB_API_URL` environment variable instead (if set). |
| 143 | - `github:uploaduri` - upload URI of GitHub or GitHub enterprise, will be used for HTTP requests to the GitHub API. |
| 144 | If not set `pint` will try to use `GITHUB_API_URL` environment variable instead (if set). |
| 145 | |
| 146 | If `github:baseuri` _or_ `github:uploaduri` are not specified then [GitHub](https://github.com) will be used. |
| 147 | |
| 148 | - `github:timeout` - timeout to be used for API requests, defaults to 1 minute. |
| 149 | - `github:owner` - name of the GitHub owner i.e. the first part that comes before the repository's name in the URI. |
| 150 | If not set `pint` will try to use `GITHUB_REPOSITORY` environment variable instead (if set). |
| 151 | - `github:repo` - name of the GitHub repository (e.g. `monitoring`). |
| 152 | If not set `pint` will try to use `GITHUB_REPOSITORY` environment variable instead (if set). |
| 153 | |
| 154 | Most GitHub settings can be detected from environment variables that are set inside GitHub Actions |
| 155 | environment. The only exception is `GITHUB_AUTH_TOKEN` environment variable that must be set |
| 156 | manually. |
| 157 | |
| 158 | ## Prometheus servers |
| 159 | |
| 160 | Some checks work by querying a running Prometheus instance to verify if |
| 161 | metrics used in rules are present. If you want to use those checks then you |
| 162 | first need to define one or more Prometheus servers. |
| 163 | |
| 164 | Syntax: |
| 165 | |
| 166 | ```js |
| 167 | prometheus "$name" { |
| 168 | uri = "https://..." |
| 169 | failover = ["https://...", ...] |
| 170 | headers = { "...": "..." } |
| 171 | timeout = "2m" |
| 172 | concurrency = 16 |
| 173 | rateLimit = 100 |
| 174 | cache = 50000 |
| 175 | required = true|false |
| 176 | include = ["...", ...] |
| 177 | exclude = ["...", ...] |
| 178 | } |
| 179 | ``` |
| 180 | |
| 181 | - `$name` - each defined server should have a unique name that can be used in check |
| 182 | definitions. |
| 183 | - `uri` - base URI of this Prometheus server, used for API requests and queries. |
| 184 | - `failover` - list of URIs to try (in order they are specified) if `uri` doesn't respond |
| 185 | to requests or returns an error. This allows to configure failover Prometheus servers |
| 186 | to avoid CI failures in case main Prometheus server is unreachable. |
| 187 | Failover URIs are not used if Prometheus returns an error caused by the query, like |
| 188 | `many-to-many matching not allowed`. |
| 189 | It's highly recommended that all URIs point to Prometheus servers with identical |
| 190 | configuration, otherwise pint checks might return unreliable results and potential |
| 191 | false positives. |
| 192 | - `headers` - a list of HTTP headers that will be set on all requests for this Prometheus |
| 193 | server. |
| 194 | - `timeout` - timeout to be used for API requests. Defaults to 2 minutes. |
| 195 | - `concurrency` - how many concurrent requests can pint send to this Prometheus server. |
| 196 | Optional, defaults to 16. |
| 197 | - `rateLimit` - per second rate limit for all API requests send to this Prometheus server. |
| 198 | Setting it to `1000` would allow for up to 1000 requests per each wall clock second. |
| 199 | Optional, default to 100 requests per second. |
| 200 | - `cache` - the maximum number of cached time series, defaults to 50000. |
| 201 | - `uptime` - metric selector used to detect gaps in Prometheus uptime. |
| 202 | Since some checks are sending queries to validate if given metric always present in Prometheus |
| 203 | they might find gaps when Prometheus itself was down. Pint tries to detect that by querying |
| 204 | metrics that are always guarnateed to be present when Prometheus is running. |
| 205 | By default metric used for this is `up`, which is generated by Prometheus itself, see |
| 206 | [Prometheus docs](https://prometheus.io/docs/concepts/jobs_instances/#automatically-generated-labels-and-time-series) |
| 207 | for details. |
| 208 | Uptime gap detection works by running a range query `count(up)` and checking for any gaps |
| 209 | in the response. |
| 210 | Since `up` metric can have a lot of time series `count(up)` might be slow and expensive. |
| 211 | An alternative is to use one of metrics exposed by Prometheus itself, like `prometheus_build_info`, but |
| 212 | those metrics are only present if Prometheus is configured to scrape itself, so `up` is used by default |
| 213 | since it's guaranteed to work in every setup. |
| 214 | If your Prometheus has a lot of time series and it's configured to scrape itself then |
| 215 | it is recommeded to set `uptime` field to `prometheus_build_info`. |
| 216 | - `required` - decides how pint will report errors if it's unable to get a valid response |
| 217 | from this Prometheus server. If `required` is `true` and all API calls to this Prometheus |
| 218 | fail pint will report those as `bug` level problem. If it's set to `false` pint will |
| 219 | report those with `warning` level. |
| 220 | Default value for `required` is `false`. Set it to `true` if you want to hard fail |
| 221 | in case of remote Prometheus issues. Note that setting it to `true` might block |
| 222 | PRs when running `pint ci` until pint is able to talk to Prometheus again. |
| 223 | - `include` - optional path filter, if specified only paths matching one of listed regexp |
| 224 | patterns will use this Prometheus server for checks. |
| 225 | - `exclude` - optional path filter, if specified any path matching one of listed regexp |
| 226 | patterns will never use this Prometheus server for checks. |
| 227 | `exclude` takes precedence over `include. |
| 228 | |
| 229 | Example: |
| 230 | |
| 231 | ```js |
| 232 | prometheus "prod" { |
| 233 | uri = "https://prometheus-prod.example.com" |
| 234 | headers = { |
| 235 | "X-Auth": "secret" |
| 236 | } |
| 237 | concurrency = 40 |
| 238 | } |
| 239 | |
| 240 | prometheus "staging" { |
| 241 | uri = "https://prometheus-staging.example.com" |
| 242 | uptime = "prometheus_build_info" |
| 243 | } |
| 244 | |
| 245 | prometheus "dev" { |
| 246 | uri = "https://prometheus-dev.example.com" |
| 247 | timeout = "30s" |
| 248 | include = [ "alerts/test/.*" ] |
| 249 | exclude = [ "alerts/test/docs/.*" ] |
| 250 | } |
| 251 | ``` |
| 252 | |
| 253 | ## Matching rules to checks |
| 254 | |
| 255 | Most checks, except basic syntax verification, requires some configuration to decide |
| 256 | which checks to run against which files and rules. |
| 257 | |
| 258 | Syntax: |
| 259 | |
| 260 | ```js |
| 261 | rule { |
| 262 | match { |
| 263 | path = "(.+)" |
| 264 | name = "(.+)" |
| 265 | kind = "alerting|recording" |
| 266 | command = "ci|lint|watch" |
| 267 | annotation "(.*)" { |
| 268 | value = "(.*)" |
| 269 | } |
| 270 | label "(.*)" { |
| 271 | value = "(.*)" |
| 272 | } |
| 273 | for = "..." |
| 274 | } |
| 275 | match { ... } |
| 276 | match { ... } |
| 277 | ignore { |
| 278 | path = "(.+)" |
| 279 | name = "(.+)" |
| 280 | kind = "alerting|recording" |
| 281 | command = "ci|lint|watch" |
| 282 | annotation "(.*)" { |
| 283 | value = "(.*)" |
| 284 | } |
| 285 | label "(.*)" { |
| 286 | value = "(.*)" |
| 287 | } |
| 288 | for = "..." |
| 289 | } |
| 290 | ignore { ... } |
| 291 | ignore { ... } |
| 292 | |
| 293 | [ check definition ] |
| 294 | ... |
| 295 | [ check definition ] |
| 296 | } |
| 297 | ``` |
| 298 | |
| 299 | - `match:path` - only files matching this pattern will be checked by this rule |
| 300 | - `match:name` - only rules with names (`record` for recording rules and `alert` for alerting |
| 301 | rules) matching this pattern will be checked rule |
| 302 | - `match:kind` - optional rule type filter, only rule of this type will be checked |
| 303 | - `match:command` - optional command type filter, this allows to include or ignore rules |
| 304 | based on the command pint is run with `pint ci`, `pint lint` or `pint watch`. |
| 305 | - `match:annotation` - optional annotation filter, only alert rules with at least one |
| 306 | annotation matching this pattern will be checked by this rule. |
| 307 | - `match:label` - optional annotation filter, only rules with at least one label |
| 308 | matching this pattern will be checked by this rule. For recording rules only static |
| 309 | labels set on the recording rule are considered. |
| 310 | - `match:for` - optional alerting rule `for` filter. If set only alerting rules with `for` |
| 311 | field present and matching provided value will be checked by this rule. Recording rules |
| 312 | will never match it as they don't have `for` field. |
| 313 | Syntax is `OP DURATION` where `OP` can be any of `=`, `!=`, `>`, `>=`, `<`, `<=`. |
| 314 | - `ignore` - works exactly like `match` but does the opposite - any alerting or recording rule |
| 315 | matching all conditions defined on `ignore` will not be checked by this `rule` block. |
| 316 | |
| 317 | Note: both `match` and `ignore` require all defined filters to be satisfied to work. |
| 318 | If multiple `match` and/or `ignore` rules are present any of them needs to match for the rule to |
| 319 | be matched / ignored. |
| 320 | |
| 321 | Examples: |
| 322 | |
| 323 | ```js |
| 324 | rule { |
| 325 | match { |
| 326 | path = "rules/.*" |
| 327 | kind = "alerting" |
| 328 | label "severity" { |
| 329 | value = "(warning|critical)" |
| 330 | } |
| 331 | } |
| 332 | ignore { |
| 333 | command = "watch" |
| 334 | } |
| 335 | [ check applied only to severity="critical" and severity="warning" alerts in "ci" or "lint" command is run ] |
| 336 | } |
| 337 | ``` |
| 338 | |
| 339 | ```js |
| 340 | rule { |
| 341 | ignore { |
| 342 | command = "watch" |
| 343 | } |
| 344 | ignore { |
| 345 | command = "lint" |
| 346 | } |
| 347 | [ check applied unless "watch" or "lint" command is run ] |
| 348 | } |
| 349 | ``` |
| 350 | |
| 351 | ```js |
| 352 | rule { |
| 353 | match { |
| 354 | for = ">= 5m" |
| 355 | } |
| 356 | [ check applied only to alerting rules with "for" field value that is >= 5m ] |
| 357 | } |
| 358 | ``` |
| 359 | |