@intentius/chant-lexicon-prometheus 0.105.1 → 0.106.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +5 -2
  2. package/dist/build.d.ts +17 -0
  3. package/dist/build.d.ts.map +1 -1
  4. package/dist/catalog.d.ts +1 -1
  5. package/dist/catalog.d.ts.map +1 -1
  6. package/dist/composites/slo.d.ts +10 -0
  7. package/dist/composites/slo.d.ts.map +1 -1
  8. package/dist/config-model.d.ts +272 -0
  9. package/dist/config-model.d.ts.map +1 -0
  10. package/dist/detect.d.ts.map +1 -1
  11. package/dist/import/generator.d.ts +3 -1
  12. package/dist/import/generator.d.ts.map +1 -1
  13. package/dist/import/parser.d.ts +12 -2
  14. package/dist/import/parser.d.ts.map +1 -1
  15. package/dist/import/slo.d.ts.map +1 -1
  16. package/dist/index.d.ts +4 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/integrity.json +5 -4
  19. package/dist/lint/audit-catalog.d.ts.map +1 -1
  20. package/dist/lint/audit-lineage.d.ts +2 -0
  21. package/dist/lint/audit-lineage.d.ts.map +1 -1
  22. package/dist/lint/post-synth/index.d.ts.map +1 -1
  23. package/dist/lint/post-synth/prom-helpers.d.ts +7 -0
  24. package/dist/lint/post-synth/prom-helpers.d.ts.map +1 -1
  25. package/dist/lint/post-synth/prom225.d.ts +10 -0
  26. package/dist/lint/post-synth/prom225.d.ts.map +1 -0
  27. package/dist/manifest.json +1 -1
  28. package/dist/meta.json +10 -0
  29. package/dist/model.d.ts +1 -0
  30. package/dist/model.d.ts.map +1 -1
  31. package/dist/okf/index.md +3 -0
  32. package/dist/okf/rules/PROM225.md +11 -0
  33. package/dist/okf/types/PrometheusConfig.md +9 -0
  34. package/dist/okf/types/ScrapeConfig.md +9 -0
  35. package/dist/plugin.d.ts.map +1 -1
  36. package/dist/prometheus-config.d.ts +39 -0
  37. package/dist/prometheus-config.d.ts.map +1 -0
  38. package/dist/rules/prom-helpers.ts +10 -1
  39. package/dist/rules/prom225.ts +19 -0
  40. package/dist/serializer.d.ts +14 -10
  41. package/dist/serializer.d.ts.map +1 -1
  42. package/dist/tools.d.ts +9 -1
  43. package/dist/tools.d.ts.map +1 -1
  44. package/dist/validate-config.d.ts +1 -1
  45. package/dist/validate-config.d.ts.map +1 -1
  46. package/dist/validate-relabel.d.ts +14 -0
  47. package/dist/validate-relabel.d.ts.map +1 -0
  48. package/dist/validate.d.ts.map +1 -1
  49. package/package.json +2 -2
  50. package/src/build.ts +73 -0
  51. package/src/catalog.ts +14 -1
  52. package/src/composites/composites.test.ts +43 -1
  53. package/src/composites/slo.ts +22 -4
  54. package/src/config-model.ts +327 -0
  55. package/src/detect.ts +5 -4
  56. package/src/generated/lexicon-prometheus.json +10 -0
  57. package/src/import/generator.ts +120 -0
  58. package/src/import/parser.test.ts +2 -2
  59. package/src/import/parser.ts +72 -5
  60. package/src/import/prometheus-roundtrip.test.ts +148 -0
  61. package/src/import/slo.ts +15 -0
  62. package/src/import/testdata/prometheus-full.yml +149 -0
  63. package/src/index.ts +20 -2
  64. package/src/lint/audit-catalog.ts +7 -0
  65. package/src/lint/audit-lineage.test.ts +1 -1
  66. package/src/lint/audit-lineage.ts +2 -0
  67. package/src/lint/post-synth/checks.test.ts +34 -0
  68. package/src/lint/post-synth/index.ts +2 -0
  69. package/src/lint/post-synth/prom-helpers.ts +10 -1
  70. package/src/lint/post-synth/prom225.ts +19 -0
  71. package/src/model.ts +1 -0
  72. package/src/plugin.test.ts +1 -0
  73. package/src/plugin.ts +1 -0
  74. package/src/prometheus-config.test.ts +230 -0
  75. package/src/prometheus-config.ts +71 -0
  76. package/src/serializer.ts +31 -21
  77. package/src/tools.ts +31 -3
  78. package/src/validate-config.ts +2 -1
  79. package/src/validate-relabel.ts +53 -0
  80. package/src/validate.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"prom-helpers.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/prom-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAI9F,OAAO,EAAkD,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3H,OAAO,EAML,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IAC7D,YAAY,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,CAAC,CAAC;CACrE;AAED,8JAA8J;AAC9J,wBAAgB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,CAsB/D;AAYD,2HAA2H;AAC3H,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAM3G;AAED,uIAAuI;AACvI,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAM/G;AAED,yIAAyI;AACzI,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAE/E;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CA0BvF;AAED,0HAA0H;AAC1H,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAK/E"}
1
+ {"version":3,"file":"prom-helpers.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/prom-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAI9F,OAAO,EAA6B,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1F,OAAO,EAAkD,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3H,OAAO,EAML,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IAC7D,YAAY,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,CAAC,CAAC;IACpE,UAAU,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAC;CACrE;AAED,8JAA8J;AAC9J,wBAAgB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,CAuB/D;AAYD,2HAA2H;AAC3H,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAM3G;AAED,uIAAuI;AACvI,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAM/G;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAE/E;AAED,yIAAyI;AACzI,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAE/E;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CA0BvF;AAED,0HAA0H;AAC1H,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAK/E"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * PROM225: A labeldrop or labelkeep relabel step carries a field it does not take
3
+ *
4
+ * Both actions match regex against label names, so source_labels, separator,
5
+ * target_label, modulus and replacement do nothing, and Prometheus rejects the
6
+ * file at load. Reads every prometheus.yml in the output.
7
+ */
8
+ import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
9
+ export declare const prom225: PostSynthCheck;
10
+ //# sourceMappingURL=prom225.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prom225.d.ts","sourceRoot":"","sources":["../../../src/lint/post-synth/prom225.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,kCAAkC,CAAC;AAG9G,eAAO,MAAM,OAAO,EAAE,cAOrB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prometheus",
3
- "version": "0.105.1",
3
+ "version": "0.106.1",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Prometheus",
6
6
  "intrinsics": [],
package/dist/meta.json CHANGED
@@ -9,6 +9,11 @@
9
9
  "kind": "resource",
10
10
  "lexicon": "prometheus"
11
11
  },
12
+ "PrometheusConfig": {
13
+ "resourceType": "Prometheus::Config::PrometheusConfig",
14
+ "kind": "resource",
15
+ "lexicon": "prometheus"
16
+ },
12
17
  "Receiver": {
13
18
  "resourceType": "Prometheus::Alertmanager::Receiver",
14
19
  "kind": "resource",
@@ -24,6 +29,11 @@
24
29
  "kind": "resource",
25
30
  "lexicon": "prometheus"
26
31
  },
32
+ "ScrapeConfig": {
33
+ "resourceType": "Prometheus::Config::ScrapeConfig",
34
+ "kind": "resource",
35
+ "lexicon": "prometheus"
36
+ },
27
37
  "TimeInterval": {
28
38
  "resourceType": "Prometheus::Alertmanager::TimeInterval",
29
39
  "kind": "resource",
package/dist/model.d.ts CHANGED
@@ -62,6 +62,7 @@ export declare function isAlertingRuleConfig(rule: unknown): rule is AlertingRul
62
62
  /** The rule's name: `record` for a recording rule, `alert` for an alerting rule. */
63
63
  export declare function ruleName(rule: RuleConfig): string;
64
64
  export * from "./integrations.js";
65
+ export * from "./config-model.js";
65
66
  /** One entry under `receivers:`. */
66
67
  export interface ReceiverConfig {
67
68
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
package/dist/okf/index.md CHANGED
@@ -6,9 +6,11 @@ okf_version: '0.2'
6
6
 
7
7
  * [AlertmanagerSettings](/types/AlertmanagerSettings.md) - Prometheus::Alertmanager::Settings
8
8
  * [InhibitRule](/types/InhibitRule.md) - Prometheus::Alertmanager::InhibitRule
9
+ * [PrometheusConfig](/types/PrometheusConfig.md) - Prometheus::Config::PrometheusConfig
9
10
  * [Receiver](/types/Receiver.md) - Prometheus::Alertmanager::Receiver
10
11
  * [Route](/types/Route.md) - Prometheus::Alertmanager::Route
11
12
  * [RuleGroup](/types/RuleGroup.md) - Prometheus::Rules::RuleGroup
13
+ * [ScrapeConfig](/types/ScrapeConfig.md) - Prometheus::Config::ScrapeConfig
12
14
  * [TimeInterval](/types/TimeInterval.md) - Prometheus::Alertmanager::TimeInterval
13
15
 
14
16
  # Rules
@@ -47,4 +49,5 @@ okf_version: '0.2'
47
49
  * [PROM222](/rules/PROM222.md) - Credentials sent to an http:// receiver URL
48
50
  * [PROM223](/rules/PROM223.md) - repeat_interval is shorter than group_interval
49
51
  * [PROM224](/rules/PROM224.md) - An inhibit rule matches one alert as source and target, with no equal
52
+ * [PROM225](/rules/PROM225.md) - A labeldrop or labelkeep relabel step carries a field it does not take
50
53
  * [PROM301](/rules/PROM301.md) - A rule reads a connector metric no collector in the build emits
@@ -0,0 +1,11 @@
1
+ ---
2
+ type: post-synth-check
3
+ title: PROM225
4
+ description: A labeldrop or labelkeep relabel step carries a field it does not take
5
+ id: PROM225
6
+ severity: error
7
+ category: post-synth
8
+ lexicon: prometheus
9
+ docs: https://intentius.io/chant/lexicons/prometheus/rules/
10
+ ---
11
+ A labeldrop or labelkeep relabel step carries a field it does not take
@@ -0,0 +1,9 @@
1
+ ---
2
+ type: resource-type
3
+ title: PrometheusConfig
4
+ description: prometheus resource type Prometheus::Config::PrometheusConfig
5
+ name: PrometheusConfig
6
+ lexicon: prometheus
7
+ resource_type: Prometheus::Config::PrometheusConfig
8
+ ---
9
+ `Prometheus::Config::PrometheusConfig`, a resource type of the prometheus lexicon.
@@ -0,0 +1,9 @@
1
+ ---
2
+ type: resource-type
3
+ title: ScrapeConfig
4
+ description: prometheus resource type Prometheus::Config::ScrapeConfig
5
+ name: ScrapeConfig
6
+ lexicon: prometheus
7
+ resource_type: Prometheus::Config::ScrapeConfig
8
+ ---
9
+ `Prometheus::Config::ScrapeConfig`, a resource type of the prometheus lexicon.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA+B9D;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,aAwH9B,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA+B9D;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,aAyH9B,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `PrometheusConfig` and `ScrapeConfig`: the entities that serialize to
3
+ * `prometheus.yml`.
4
+ *
5
+ * A `ScrapeConfig` is one scrape job. `PrometheusConfig` holds the rest of the
6
+ * file (`global`, `alerting`, `rule_files`, `remote_write`, `remote_read`,
7
+ * `otlp`) and is optional: a build that declares only `ScrapeConfig`s still
8
+ * writes a `prometheus.yml`. A project that declares neither writes none, so
9
+ * a project that builds only rule files sees no change.
10
+ */
11
+ import type { Declarable } from "@intentius/chant/declarable";
12
+ import type { PrometheusConfigSections, ScrapeJobConfig } from "./model.js";
13
+ export declare const SCRAPE_CONFIG_TYPE = "Prometheus::Config::ScrapeConfig";
14
+ export declare const PROMETHEUS_CONFIG_TYPE = "Prometheus::Config::PrometheusConfig";
15
+ type Ctor<P, E> = new (props: P) => E;
16
+ export type ScrapeConfigProps = ScrapeJobConfig;
17
+ export interface ScrapeConfigEntity extends Declarable {
18
+ readonly props: ScrapeConfigProps;
19
+ }
20
+ /**
21
+ * One scrape job: where its targets come from (`static_configs` or a service
22
+ * discovery list), how to scrape them, and how to relabel what comes back.
23
+ */
24
+ export declare const ScrapeConfig: Ctor<ScrapeJobConfig, ScrapeConfigEntity>;
25
+ export interface PrometheusConfigProps extends PrometheusConfigSections {
26
+ /** Scrape jobs written inline, as plain objects. Merged with the declared `ScrapeConfig`s. */
27
+ scrape_configs?: Array<ScrapeConfigEntity | ScrapeConfigProps>;
28
+ }
29
+ export interface PrometheusConfigEntity extends Declarable {
30
+ readonly props: PrometheusConfigProps;
31
+ }
32
+ /** The sections of `prometheus.yml` other than the scrape jobs. Declare at most one. */
33
+ export declare const PrometheusConfig: Ctor<PrometheusConfigProps, PrometheusConfigEntity>;
34
+ export declare const isScrapeConfig: (value: unknown) => value is ScrapeConfigEntity;
35
+ export declare const isPrometheusConfig: (value: unknown) => value is PrometheusConfigEntity;
36
+ /** True for an entity that goes into `prometheus.yml`. */
37
+ export declare function isPrometheusConfigEntity(value: unknown): boolean;
38
+ export {};
39
+ //# sourceMappingURL=prometheus-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prometheus-config.d.ts","sourceRoot":"","sources":["../src/prometheus-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEzE,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AACrE,eAAO,MAAM,sBAAsB,yCAAyC,CAAC;AAE7E,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;AAatC,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEhD,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;CACnC;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,2CAAyF,CAAC;AAInH,MAAM,WAAW,qBAAsB,SAAQ,wBAAwB;IACrE,8FAA8F;IAC9F,cAAc,CAAC,EAAE,KAAK,CAAC,kBAAkB,GAAG,iBAAiB,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,sBAAuB,SAAQ,UAAU;IACxD,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;CACvC;AAED,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,qDAAyG,CAAC;AASvI,eAAO,MAAM,cAAc,UAJV,OAAO,gCAIoD,CAAC;AAC7E,eAAO,MAAM,kBAAkB,UALd,OAAO,oCAKgE,CAAC;AAEzF,0DAA0D;AAC1D,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEhE"}
@@ -14,6 +14,8 @@ import type { PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lin
14
14
  import type { SerializerResult } from "@intentius/chant/serializer";
15
15
  import { loadAll } from "js-yaml";
16
16
  import { buildCollectorConfigs, collectorMetricIssues, collectorMetrics } from "../../collector-metrics";
17
+ import { looksLikePrometheusConfig, type PrometheusConfigFile } from "../../config-model";
18
+ import { validateRelabelFields } from "../../validate-relabel";
17
19
  import { looksLikeAlertmanagerConfig, looksLikeRuleFile, type AlertmanagerConfig, type RuleFileConfig } from "../../model";
18
20
  import {
19
21
  validateAlertmanagerConfig,
@@ -27,11 +29,12 @@ import {
27
29
  export interface FoundDocs {
28
30
  ruleFiles: Array<{ source: string; config: RuleFileConfig }>;
29
31
  alertmanager: Array<{ source: string; config: AlertmanagerConfig }>;
32
+ prometheus: Array<{ source: string; config: PrometheusConfigFile }>;
30
33
  }
31
34
 
32
35
  /** Every rule file and Alertmanager config in the output. Parsed with js-yaml rather than `ctx.docs`, which keeps block scalars and flow lists as strings. */
33
36
  export function prometheusDocs(ctx: PostSynthContext): FoundDocs {
34
- const found: FoundDocs = { ruleFiles: [], alertmanager: [] };
37
+ const found: FoundDocs = { ruleFiles: [], alertmanager: [], prometheus: [] };
35
38
  for (const [lexicon, output] of ctx.outputs) {
36
39
  const texts: Array<[string, string]> =
37
40
  typeof output === "string"
@@ -48,6 +51,7 @@ export function prometheusDocs(ctx: PostSynthContext): FoundDocs {
48
51
  for (const doc of docs) {
49
52
  if (looksLikeRuleFile(doc)) found.ruleFiles.push({ source, config: doc });
50
53
  else if (looksLikeAlertmanagerConfig(doc)) found.alertmanager.push({ source, config: doc });
54
+ else if (looksLikePrometheusConfig(doc)) found.prometheus.push({ source, config: doc });
51
55
  }
52
56
  }
53
57
  }
@@ -82,6 +86,11 @@ export function alertmanagerDiagnostics(ctx: PostSynthContext, code: PrometheusI
82
86
  );
83
87
  }
84
88
 
89
+ /** PROM225 across every `prometheus.yml` in the output. */
90
+ export function relabelDiagnostics(ctx: PostSynthContext): PostSynthDiagnostic[] {
91
+ return prometheusDocs(ctx).prometheus.flatMap(({ source, config }) => validateRelabelFields(config).map((i) => toDiagnostic(i, source)));
92
+ }
93
+
85
94
  /** PROM212 across every rule file in the output. Opt-in: the lexicon's `recommended` lint preset leaves it out (see ../../plugin.ts). */
86
95
  export function runbookDiagnostics(ctx: PostSynthContext): PostSynthDiagnostic[] {
87
96
  return prometheusDocs(ctx).ruleFiles.flatMap(({ source, config }) => validateRunbookUrls(config).map((i) => toDiagnostic(i, source)));
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PROM225: A labeldrop or labelkeep relabel step carries a field it does not take
3
+ *
4
+ * Both actions match regex against label names, so source_labels, separator,
5
+ * target_label, modulus and replacement do nothing, and Prometheus rejects the
6
+ * file at load. Reads every prometheus.yml in the output.
7
+ */
8
+
9
+ import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
10
+ import { relabelDiagnostics } from "./prom-helpers";
11
+
12
+ export const prom225: PostSynthCheck = {
13
+ id: "PROM225",
14
+ description: "A labeldrop or labelkeep relabel step carries a field it does not take",
15
+
16
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
17
+ return relabelDiagnostics(ctx);
18
+ },
19
+ };
@@ -1,26 +1,30 @@
1
1
  /**
2
2
  * Prometheus serializer.
3
3
  *
4
- * Emits the two files a Prometheus setup reads:
4
+ * Emits the files a Prometheus setup reads:
5
5
  *
6
6
  * - the rule file (`groups:`), from every `RuleGroup` in the build, the file
7
7
  * `rule_files:` points at and `promtool check rules` reads;
8
+ * - `prometheus.yml`, from the `PrometheusConfig` and `ScrapeConfig`
9
+ * entities, the file `promtool check config` reads;
8
10
  * - `alertmanager.yml`, from the `Route`, `Receiver`, `InhibitRule`,
9
11
  * `TimeInterval` and `AlertmanagerSettings` entities, the file
10
12
  * `amtool check-config` reads.
11
13
  *
12
- * The rule file is the primary output when the build declares any rule
13
- * groups, and `alertmanager.yml` is written beside it when the build also
14
- * declares Alertmanager entities. A build with only Alertmanager entities
15
- * emits `alertmanager.yml` as the primary output. Rules inside a group and
16
- * child routes keep the order they are written in, which is the order that
17
- * matters to Prometheus and Alertmanager; groups, receivers and time
18
- * intervals, whose order means nothing, are sorted by name.
14
+ * The first of those a build produces, in that order, is the primary output
15
+ * and the others are written beside it: the rule file, then `prometheus.yml`
16
+ * (`PROMETHEUS_FILE`), then `alertmanager.yml`. A project that declares only
17
+ * rule groups, or only Alertmanager entities, sees no change. Rules inside a
18
+ * group and child routes keep the order they are written in, which is the
19
+ * order that matters to Prometheus and Alertmanager; groups, scrape jobs,
20
+ * receivers and time intervals, whose order means nothing, are sorted by name.
19
21
  *
20
- * Neither file has a metadata channel, so there is no ownership marker to
21
- * stamp.
22
+ * None of these files has a metadata channel, so there is no ownership marker
23
+ * to stamp.
22
24
  */
23
25
  import type { Serializer } from "@intentius/chant/serializer";
26
+ /** The filename `prometheus.yml` is written under when it sits beside a rule file or `alertmanager.yml`. */
27
+ export declare const PROMETHEUS_FILE = "prometheus.yml";
24
28
  /** The filename `alertmanager.yml` is written under when it sits beside a rule file. */
25
29
  export declare const ALERTMANAGER_FILE = "alertmanager.yml";
26
30
  export declare const prometheusSerializer: Serializer;
@@ -1 +1 @@
1
- {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,6BAA6B,CAAC;AAIhF,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD,eAAO,MAAM,oBAAoB,EAAE,UAuBlC,CAAC"}
1
+ {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,6BAA6B,CAAC;AAIhF,4GAA4G;AAC5G,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAEhD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD,eAAO,MAAM,oBAAoB,EAAE,UA4BlC,CAAC"}
package/dist/tools.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `promtool check rules` and `amtool check-config`, when they are installed.
2
+ * `promtool check rules`, `promtool check config` and `amtool check-config`, when they are installed.
3
3
  *
4
4
  * The lexicon's own checks cover structure, references and PromQL syntax.
5
5
  * The upstream tools add what only Prometheus and Alertmanager know (PromQL
@@ -19,6 +19,14 @@ export interface ToolResult {
19
19
  export declare function hasTool(bin: string): boolean;
20
20
  /** Run `promtool check rules` over rule file YAML. `bin` defaults to `promtool` on PATH. */
21
21
  export declare function promtoolCheckRules(yaml: string, bin?: string): ToolResult;
22
+ /**
23
+ * Run `promtool check config` over `prometheus.yml` text. The config is written
24
+ * as `prometheus.yml` in a directory of its own, and `files` (path relative to
25
+ * that directory to contents) are written beside it: `check config` also reads
26
+ * the rule files, certificates and credentials files the config names, so a
27
+ * config that names any needs them here. `bin` defaults to `promtool` on PATH.
28
+ */
29
+ export declare function promtoolCheckConfig(yaml: string, files?: Record<string, string>, bin?: string): ToolResult;
22
30
  /**
23
31
  * Run `promtool test rules` over rule file YAML and a unit-test file for it.
24
32
  * The test file's `rule_files:` should name `rules.yml`, which is where the
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,GAAG,EAAE,OAAO,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG5C;AAeD,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAqC,GAAG,UAAU,CAErG;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAqC,GAAG,UAAU,CAW3H;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAiC,GAAG,UAAU,CAEhG"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,GAAG,EAAE,OAAO,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG5C;AAeD,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAqC,GAAG,UAAU,CAErG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAClC,GAAG,SAAqC,GACvC,UAAU,CAeZ;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAqC,GAAG,UAAU,CAW3H;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAiC,GAAG,UAAU,CAEhG"}
@@ -7,7 +7,7 @@
7
7
  * `PrometheusRule`'s groups, or on a file parsed by some other tool.
8
8
  */
9
9
  import { type AlertmanagerConfig, type RuleFileConfig } from "./model.js";
10
- export type PrometheusIssueCode = "PROM101" | "PROM102" | "PROM103" | "PROM104" | "PROM105" | "PROM106" | "PROM107" | "PROM201" | "PROM202" | "PROM203" | "PROM204" | "PROM205" | "PROM206" | "PROM207" | "PROM208" | "PROM209" | "PROM210" | "PROM211" | "PROM212" | "PROM213" | "PROM214" | "PROM215" | "PROM216" | "PROM217" | "PROM218" | "PROM219" | "PROM220" | "PROM221" | "PROM222" | "PROM223" | "PROM224";
10
+ export type PrometheusIssueCode = "PROM101" | "PROM102" | "PROM103" | "PROM104" | "PROM105" | "PROM106" | "PROM107" | "PROM201" | "PROM202" | "PROM203" | "PROM204" | "PROM205" | "PROM206" | "PROM207" | "PROM208" | "PROM209" | "PROM210" | "PROM211" | "PROM212" | "PROM213" | "PROM214" | "PROM215" | "PROM216" | "PROM217" | "PROM218" | "PROM219" | "PROM220" | "PROM221" | "PROM222" | "PROM223" | "PROM224" | "PROM225";
11
11
  export interface PrometheusIssue {
12
12
  code: PrometheusIssueCode;
13
13
  severity: "error" | "warning";
@@ -1 +1 @@
1
- {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../src/validate-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAGL,KAAK,kBAAkB,EAIvB,KAAK,cAAc,EAEpB,MAAM,SAAS,CAAC;AAiBjB,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAwID,4HAA4H;AAC5H,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,EAAE,CAmIxE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,EAAE,CAU3E;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAa9E;AAkGD,0FAA0F;AAC1F,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAsHxF;AAYD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,kBAAkB,GAAG,eAAe,EAAE,CA6BlH"}
1
+ {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../src/validate-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAGL,KAAK,kBAAkB,EAIvB,KAAK,cAAc,EAEpB,MAAM,SAAS,CAAC;AAiBjB,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAwID,4HAA4H;AAC5H,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,EAAE,CAmIxE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,EAAE,CAU3E;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAa9E;AAkGD,0FAA0F;AAC1F,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAsHxF;AAYD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,kBAAkB,GAAG,eAAe,EAAE,CA6BlH"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * PROM225: a `labeldrop` or `labelkeep` relabel step carries a field the
3
+ * action does not take.
4
+ *
5
+ * Both actions match `regex` against label names, so `source_labels`,
6
+ * `separator`, `target_label`, `modulus` and `replacement` have nothing to
7
+ * act on. Prometheus rejects the file when it loads it (the importer's
8
+ * fixture was fixed for the same reason, #3537).
9
+ */
10
+ import type { PrometheusConfigFile } from "./config-model.js";
11
+ import type { PrometheusIssue } from "./validate-config.js";
12
+ /** PROM225 over one `prometheus.yml`. */
13
+ export declare function validateRelabelFields(config: PrometheusConfigFile): PrometheusIssue[];
14
+ //# sourceMappingURL=validate-relabel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-relabel.d.ts","sourceRoot":"","sources":["../src/validate-relabel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAwBzD,yCAAyC;AACzC,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,GAAG,eAAe,EAAE,CAgBrF"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAOvF,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEvF,0DAA0D;AAC1D,eAAO,MAAM,cAAc,UAA4F,CAAC;AAExH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CA+CxD"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAOvF,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEvF,0DAA0D;AAC1D,eAAO,MAAM,cAAc,UAAgI,CAAC;AAE5J,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CA+CxD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-prometheus",
3
- "version": "0.105.1",
3
+ "version": "0.106.1",
4
4
  "description": "Prometheus lexicon for chant — typed recording and alerting rule groups and Alertmanager routing, serialized to a rule file and alertmanager.yml",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -72,7 +72,7 @@
72
72
  "typescript": "^5.9.3"
73
73
  },
74
74
  "peerDependencies": {
75
- "@intentius/chant": "^0.105.1",
75
+ "@intentius/chant": "^0.106.1",
76
76
  "typescript": "^5.9.3"
77
77
  }
78
78
  }
package/src/build.ts CHANGED
@@ -30,6 +30,14 @@ import type {
30
30
  TimeIntervalConfig,
31
31
  } from "./model";
32
32
  import { isRuleGroup, ruleGroupConfig, type RuleGroupEntity } from "./rules";
33
+ import {
34
+ isPrometheusConfig,
35
+ isScrapeConfig,
36
+ type PrometheusConfigEntity,
37
+ type ScrapeConfigEntity,
38
+ type ScrapeConfigProps,
39
+ } from "./prometheus-config";
40
+ import { PROMETHEUS_CONFIG_SECTIONS, type PrometheusConfigFile, type ScrapeJobConfig } from "./model";
33
41
 
34
42
  function byName(a: unknown, b: unknown): number {
35
43
  return String(a ?? "").localeCompare(String(b ?? ""));
@@ -183,6 +191,66 @@ export function buildAlertmanagerConfig(entities: Iterable<Declarable> | Map<str
183
191
  return { config, warnings, count };
184
192
  }
185
193
 
194
+ // ── prometheus.yml ──────────────────────────────────────────────────
195
+
196
+ export interface BuiltPrometheusConfig {
197
+ config: PrometheusConfigFile;
198
+ /** Non-fatal problems, e.g. two scrape jobs with one name. */
199
+ warnings: string[];
200
+ /** Every `PrometheusConfig` and `ScrapeConfig` that took part. */
201
+ count: number;
202
+ }
203
+
204
+ /**
205
+ * The `prometheus.yml` for a set of declared entities. Entities that aren't
206
+ * `PrometheusConfig`s or `ScrapeConfig`s are ignored. Sections come out in the
207
+ * order Prometheus documents them, and scrape jobs are sorted by name: the
208
+ * jobs are independent, so their order carries no meaning.
209
+ */
210
+ export function buildPrometheusConfig(entities: Iterable<Declarable> | Map<string, Declarable>): BuiltPrometheusConfig {
211
+ const warnings: string[] = [];
212
+ const jobs: ScrapeJobConfig[] = [];
213
+ const seen = new Set<unknown>();
214
+ let main: PrometheusConfigEntity | undefined;
215
+ let count = 0;
216
+
217
+ const addJob = (job: ScrapeConfigEntity | ScrapeConfigProps) => {
218
+ if (seen.has(job)) return;
219
+ seen.add(job);
220
+ jobs.push(plain(isScrapeConfig(job) ? job.props : job) as ScrapeJobConfig);
221
+ };
222
+
223
+ for (const e of entityList(entities)) {
224
+ if (isScrapeConfig(e)) {
225
+ addJob(e);
226
+ count++;
227
+ } else if (isPrometheusConfig(e)) {
228
+ if (main) warnings.push("prometheus: more than one PrometheusConfig is declared; the first one is used");
229
+ else main = e;
230
+ count++;
231
+ }
232
+ }
233
+ for (const job of main?.props.scrape_configs ?? []) addJob(job);
234
+
235
+ const names = new Map<string, number>();
236
+ for (const j of jobs) names.set(j.job_name, (names.get(j.job_name) ?? 0) + 1);
237
+ for (const [name, n] of names) {
238
+ if (n > 1) warnings.push(`prometheus: ${n} scrape configs are named "${name}"; Prometheus rejects a file with a repeated job_name`);
239
+ }
240
+ jobs.sort((a, b) => byName(a.job_name, b.job_name));
241
+
242
+ const sections = (plain(main?.props ?? {}) ?? {}) as Record<string, unknown>;
243
+ const config: Record<string, unknown> = {};
244
+ for (const key of PROMETHEUS_CONFIG_SECTIONS) {
245
+ if (key === "scrape_configs") {
246
+ if (jobs.length > 0) config.scrape_configs = jobs;
247
+ } else if (sections[key] !== undefined) {
248
+ config[key] = sections[key];
249
+ }
250
+ }
251
+ return { config: config as PrometheusConfigFile, warnings, count };
252
+ }
253
+
186
254
  // ── YAML ────────────────────────────────────────────────────────────
187
255
 
188
256
  /** Print a rule file or Alertmanager config as YAML, keys in the order given. */
@@ -199,3 +267,8 @@ export function ruleFileYaml(entities: Iterable<Declarable> | Map<string, Declar
199
267
  export function alertmanagerYaml(entities: Iterable<Declarable> | Map<string, Declarable>): string {
200
268
  return emitYaml(buildAlertmanagerConfig(entities).config);
201
269
  }
270
+
271
+ /** The `prometheus.yml` text for a set of declared entities, exactly as the serializer emits it. */
272
+ export function prometheusConfigYaml(entities: Iterable<Declarable> | Map<string, Declarable>): string {
273
+ return emitYaml(buildPrometheusConfig(entities).config);
274
+ }
package/src/catalog.ts CHANGED
@@ -6,13 +6,14 @@
6
6
 
7
7
  import type { LexiconEntry } from "@intentius/chant/lsp/lexicon-providers";
8
8
  import { RULE_GROUP_TYPE } from "./rules";
9
+ import { PROMETHEUS_CONFIG_TYPE, SCRAPE_CONFIG_TYPE } from "./prometheus-config";
9
10
  import { INHIBIT_RULE_TYPE, RECEIVER_TYPE, ROUTE_TYPE, SETTINGS_TYPE, TIME_INTERVAL_TYPE } from "./alertmanager";
10
11
 
11
12
  export interface CatalogEntry {
12
13
  className: string;
13
14
  entityType: string;
14
15
  /** The file the entity serializes into. */
15
- file: "rule file" | "alertmanager.yml";
16
+ file: "rule file" | "prometheus.yml" | "alertmanager.yml";
16
17
  description: string;
17
18
  }
18
19
 
@@ -23,6 +24,18 @@ export const CATALOG: CatalogEntry[] = [
23
24
  file: "rule file",
24
25
  description: "A group of recording and alerting rules, evaluated together on one interval",
25
26
  },
27
+ {
28
+ className: "ScrapeConfig",
29
+ entityType: SCRAPE_CONFIG_TYPE,
30
+ file: "prometheus.yml",
31
+ description: "One scrape job: static or discovered targets, scrape settings, and relabelling",
32
+ },
33
+ {
34
+ className: "PrometheusConfig",
35
+ entityType: PROMETHEUS_CONFIG_TYPE,
36
+ file: "prometheus.yml",
37
+ description: "The global, alerting, rule_files, remote_write, remote_read and otlp sections of prometheus.yml",
38
+ },
26
39
  {
27
40
  className: "Route",
28
41
  entityType: ROUTE_TYPE,
@@ -9,6 +9,7 @@ import { ruleGroupConfig } from "../rules";
9
9
  import { ruleFileYaml } from "../build";
10
10
  import { validateRuleFile, validateSeverityRouting } from "../validate-config";
11
11
  import { hasTool, promtoolCheckRules } from "../tools";
12
+ import { RuleEvaluator } from "../rule-eval";
12
13
  import type { AlertingRuleConfig, RecordingRuleConfig, RuleFileConfig } from "../model";
13
14
 
14
15
  const PROMTOOL = process.env.PROMTOOL ?? "promtool";
@@ -179,11 +180,52 @@ describe("the rules an Slo builds", () => {
179
180
  expect(alertsOf(direct)).toEqual([]);
180
181
  const rec = recordings(direct);
181
182
  expect(rec.map((r) => r.record)).toEqual(["slo:sli_error:ratio_rate28d", "slo:objective:ratio", "slo:error_budget:remaining"]);
182
- expect(rec[0].expr).toBe("(sum(rate(e_total[28d])))\n/\n(sum(rate(t_total[28d])))");
183
+ expect(rec[0].expr).toBe(
184
+ "((sum(rate(e_total[28d]))) or 0 * ((sum(rate(t_total[28d]))) > 0))\n/\n((sum(rate(t_total[28d]))) > 0)",
185
+ );
183
186
  expect(sloMetrics(direct).group).toBe("slo-direct");
184
187
  expect(sloMetrics(direct).burnRates).toEqual([]);
185
188
  });
186
189
 
190
+ test("a window with no events records nothing, so a sparse SLI keeps a finite budget", () => {
191
+ const sparseProps: SloProps = {
192
+ name: "sparse",
193
+ objective: 0.9,
194
+ window: "1h",
195
+ sli: { errors: "sum(increase(e_total[{{window}}]))", total: "sum(increase(t_total[{{window}}]))" },
196
+ alerting: { page: { burnRates: [{ long: "30m", short: "5m", factor: 2 }] }, ticket: false },
197
+ };
198
+ const sparse = Slo(sparseProps);
199
+ const ratio = recordings(sparse)[0].expr;
200
+ expect(ratio).toBe("((sum(increase(e_total[5m]))) or 0 * ((sum(increase(t_total[5m]))) > 0))\n/\n((sum(increase(t_total[5m]))) > 0)");
201
+ const good = Slo({ ...sparseProps, name: "sparse-good", sli: { good: "sum(increase(g_total[{{window}}]))", total: "sum(increase(t_total[{{window}}]))" } });
202
+ expect(recordings(good)[0].expr).toBe(
203
+ "1 - (\n ((sum(increase(g_total[5m]))) or 0 * ((sum(increase(t_total[5m]))) > 0))\n /\n ((sum(increase(t_total[5m]))) > 0)\n)",
204
+ );
205
+
206
+ // Counters that sit still except for two events at minute 20, one of them bad.
207
+ // Sampled every minute: the evaluator's range is (t - range, t], so a 5m range
208
+ // over 5m samples holds one point and increase() has nothing to subtract.
209
+ const ev = new RuleEvaluator([ruleGroupConfig(sparse.rules)]);
210
+ const MIN = 60_000;
211
+ let t = 0;
212
+ let e = 0;
213
+ for (let minute = 0; minute <= 50; minute += 1) {
214
+ if (minute === 20) {
215
+ t = 2;
216
+ e = 1;
217
+ }
218
+ ev.add({ __name__: "e_total" }, minute * MIN, e);
219
+ ev.add({ __name__: "t_total" }, minute * MIN, t);
220
+ ev.step(minute * MIN);
221
+ }
222
+ const at = (name: string) => ev.query(`${name}{slo="sparse"}`, 50 * MIN);
223
+ expect(at("slo:sli_error:ratio_rate5m")).toEqual([]); // minutes 30 to 50 saw no events
224
+ const budget = at("slo:error_budget:remaining");
225
+ expect(budget).toHaveLength(1);
226
+ expect(Number.isFinite(budget[0].value)).toBe(true);
227
+ });
228
+
187
229
  test.skipIf(!hasPromtool)("the same Slo renders inside the rule file promtool accepts", () => {
188
230
  const r = promtoolCheckRules(ruleFileYaml([slo.rules]), PROMTOOL);
189
231
  expect(r.ran).toBe(true);