@intentius/chant-lexicon-otel 0.100.0 → 0.102.0

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 (131) hide show
  1. package/README.md +8 -6
  2. package/dist/codegen/docs.d.ts.map +1 -1
  3. package/dist/components/common.d.ts +2 -0
  4. package/dist/components/common.d.ts.map +1 -1
  5. package/dist/components/connectors.d.ts +109 -1
  6. package/dist/components/connectors.d.ts.map +1 -1
  7. package/dist/components/exporters.d.ts.map +1 -1
  8. package/dist/components/extensions.d.ts +26 -2
  9. package/dist/components/extensions.d.ts.map +1 -1
  10. package/dist/components/processors.d.ts +15 -2
  11. package/dist/components/processors.d.ts.map +1 -1
  12. package/dist/components/receivers.d.ts.map +1 -1
  13. package/dist/composites/catalog.d.ts +3 -0
  14. package/dist/composites/catalog.d.ts.map +1 -0
  15. package/dist/composites/index.d.ts +6 -0
  16. package/dist/composites/index.d.ts.map +1 -0
  17. package/dist/composites/node-agent.d.ts +111 -0
  18. package/dist/composites/node-agent.d.ts.map +1 -0
  19. package/dist/configmap.d.ts +35 -0
  20. package/dist/configmap.d.ts.map +1 -0
  21. package/dist/define.d.ts +9 -0
  22. package/dist/define.d.ts.map +1 -1
  23. package/dist/genai.d.ts +145 -2
  24. package/dist/genai.d.ts.map +1 -1
  25. package/dist/import/generator.d.ts.map +1 -1
  26. package/dist/import/parser.d.ts.map +1 -1
  27. package/dist/index.d.ts +3 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/init-templates.d.ts +24 -0
  30. package/dist/init-templates.d.ts.map +1 -0
  31. package/dist/integrity.json +10 -5
  32. package/dist/lint/audit-catalog.d.ts +1 -1
  33. package/dist/lint/audit-catalog.d.ts.map +1 -1
  34. package/dist/lint/post-synth/index.d.ts.map +1 -1
  35. package/dist/lint/post-synth/otel-helpers.d.ts +32 -9
  36. package/dist/lint/post-synth/otel-helpers.d.ts.map +1 -1
  37. package/dist/lint/post-synth/otel113.d.ts +8 -0
  38. package/dist/lint/post-synth/otel113.d.ts.map +1 -0
  39. package/dist/lint/post-synth/otel114.d.ts +8 -0
  40. package/dist/lint/post-synth/otel114.d.ts.map +1 -0
  41. package/dist/lint/post-synth/otel115.d.ts +8 -0
  42. package/dist/lint/post-synth/otel115.d.ts.map +1 -0
  43. package/dist/lint/post-synth/otel116.d.ts +8 -0
  44. package/dist/lint/post-synth/otel116.d.ts.map +1 -0
  45. package/dist/lint/post-synth/otel117.d.ts +8 -0
  46. package/dist/lint/post-synth/otel117.d.ts.map +1 -0
  47. package/dist/manifest.json +1 -1
  48. package/dist/meta.json +15 -0
  49. package/dist/model.d.ts.map +1 -1
  50. package/dist/okf/index.md +8 -0
  51. package/dist/okf/rules/OTEL113.md +11 -0
  52. package/dist/okf/rules/OTEL114.md +11 -0
  53. package/dist/okf/rules/OTEL115.md +11 -0
  54. package/dist/okf/rules/OTEL116.md +11 -0
  55. package/dist/okf/rules/OTEL117.md +11 -0
  56. package/dist/okf/types/DeltaToCumulativeProcessor.md +9 -0
  57. package/dist/okf/types/K8sLeaderElectorExtension.md +9 -0
  58. package/dist/okf/types/SignalToMetricsConnector.md +9 -0
  59. package/dist/platform.d.ts +6 -2
  60. package/dist/platform.d.ts.map +1 -1
  61. package/dist/plugin.d.ts.map +1 -1
  62. package/dist/rules/otel-helpers.ts +43 -11
  63. package/dist/rules/otel113.ts +17 -0
  64. package/dist/rules/otel114.ts +17 -0
  65. package/dist/rules/otel115.ts +17 -0
  66. package/dist/rules/otel116.ts +17 -0
  67. package/dist/rules/otel117.ts +17 -0
  68. package/dist/skill-defs.d.ts +1 -1
  69. package/dist/skill-defs.d.ts.map +1 -1
  70. package/dist/skills/chant-otel.md +11 -5
  71. package/dist/topology.d.ts +5 -0
  72. package/dist/topology.d.ts.map +1 -1
  73. package/dist/validate-config.d.ts +14 -2
  74. package/dist/validate-config.d.ts.map +1 -1
  75. package/dist/validate.d.ts.map +1 -1
  76. package/package.json +3 -3
  77. package/src/codegen/docs.ts +9 -4
  78. package/src/components/common.ts +17 -0
  79. package/src/components/connectors.ts +209 -1
  80. package/src/components/exporters.ts +2 -0
  81. package/src/components/extensions.test.ts +70 -0
  82. package/src/components/extensions.ts +60 -2
  83. package/src/components/processors.test.ts +54 -0
  84. package/src/components/processors.ts +41 -2
  85. package/src/components/receivers.ts +5 -0
  86. package/src/composites/catalog.test.ts +38 -0
  87. package/src/composites/catalog.ts +81 -0
  88. package/src/composites/composites.test.ts +138 -0
  89. package/src/composites/index.ts +6 -0
  90. package/src/composites/node-agent.ts +220 -0
  91. package/src/configmap.ts +67 -0
  92. package/src/connectors.test.ts +197 -1
  93. package/src/define.ts +9 -0
  94. package/src/genai.test.ts +301 -6
  95. package/src/genai.ts +323 -8
  96. package/src/generated/lexicon-otel.json +15 -0
  97. package/src/import/roundtrip.test.ts +21 -1
  98. package/src/import/testdata/fixtures.ts +37 -5
  99. package/src/import/testdata/k8s-leader-elector.yaml +35 -0
  100. package/src/import/testdata/signaltometrics.yaml +83 -0
  101. package/src/index.ts +16 -0
  102. package/src/init-templates.test.ts +72 -0
  103. package/src/init-templates.ts +148 -0
  104. package/src/lint/audit-catalog.ts +41 -1
  105. package/src/lint/post-synth/connector-graph.test.ts +207 -0
  106. package/src/lint/post-synth/index.ts +10 -0
  107. package/src/lint/post-synth/otel-helpers.ts +43 -11
  108. package/src/lint/post-synth/otel113.ts +17 -0
  109. package/src/lint/post-synth/otel114.ts +17 -0
  110. package/src/lint/post-synth/otel115.ts +17 -0
  111. package/src/lint/post-synth/otel116.ts +17 -0
  112. package/src/lint/post-synth/otel117.ts +17 -0
  113. package/src/lint/post-synth/post-synth.test.ts +236 -1
  114. package/src/lint/post-synth/testdata/otel113-fail.yaml +23 -0
  115. package/src/lint/post-synth/testdata/otel113-pass.yaml +21 -0
  116. package/src/lint/post-synth/testdata/otel114-fail.yaml +25 -0
  117. package/src/lint/post-synth/testdata/otel114-pass.yaml +23 -0
  118. package/src/lint/post-synth/testdata/otel115-fail.yaml +29 -0
  119. package/src/lint/post-synth/testdata/otel115-pass.yaml +29 -0
  120. package/src/platform.test.ts +26 -0
  121. package/src/platform.ts +17 -13
  122. package/src/plugin.test.ts +18 -0
  123. package/src/plugin.ts +22 -0
  124. package/src/skills/chant-otel.md +11 -5
  125. package/src/testdata/genai-configured.yaml +108 -0
  126. package/src/testdata/genai-default.yaml +92 -0
  127. package/src/topology.test.ts +12 -0
  128. package/src/topology.ts +16 -0
  129. package/src/typecheck.test.ts +112 -0
  130. package/src/validate-config.ts +426 -2
  131. package/src/validate.ts +17 -0
@@ -0,0 +1,11 @@
1
+ ---
2
+ type: post-synth-check
3
+ title: OTEL115
4
+ description: A routing connector routes to a pipeline that does not receive from it
5
+ id: OTEL115
6
+ severity: error
7
+ category: post-synth
8
+ lexicon: otel
9
+ docs: https://intentius.io/chant/lexicons/otel/rules/
10
+ ---
11
+ A routing connector routes to a pipeline that does not receive from it
@@ -0,0 +1,11 @@
1
+ ---
2
+ type: post-synth-check
3
+ title: OTEL116
4
+ description: A connector splits metrics by a high-cardinality GenAI attribute
5
+ id: OTEL116
6
+ severity: error
7
+ category: post-synth
8
+ lexicon: otel
9
+ docs: https://intentius.io/chant/lexicons/otel/rules/
10
+ ---
11
+ A connector splits metrics by a high-cardinality GenAI attribute
@@ -0,0 +1,11 @@
1
+ ---
2
+ type: post-synth-check
3
+ title: OTEL117
4
+ description: Two components the collector starts listen on the same address
5
+ id: OTEL117
6
+ severity: error
7
+ category: post-synth
8
+ lexicon: otel
9
+ docs: https://intentius.io/chant/lexicons/otel/rules/
10
+ ---
11
+ Two components the collector starts listen on the same address
@@ -0,0 +1,9 @@
1
+ ---
2
+ type: resource-type
3
+ title: DeltaToCumulativeProcessor
4
+ description: otel resource type OTel::Processor::deltatocumulative
5
+ name: DeltaToCumulativeProcessor
6
+ lexicon: otel
7
+ resource_type: OTel::Processor::deltatocumulative
8
+ ---
9
+ `OTel::Processor::deltatocumulative`, a resource type of the otel lexicon.
@@ -0,0 +1,9 @@
1
+ ---
2
+ type: resource-type
3
+ title: K8sLeaderElectorExtension
4
+ description: otel resource type OTel::Extension::k8s_leader_elector
5
+ name: K8sLeaderElectorExtension
6
+ lexicon: otel
7
+ resource_type: OTel::Extension::k8s_leader_elector
8
+ ---
9
+ `OTel::Extension::k8s_leader_elector`, a resource type of the otel lexicon.
@@ -0,0 +1,9 @@
1
+ ---
2
+ type: resource-type
3
+ title: SignalToMetricsConnector
4
+ description: otel resource type OTel::Connector::signaltometrics
5
+ name: SignalToMetricsConnector
6
+ lexicon: otel
7
+ resource_type: OTel::Connector::signaltometrics
8
+ ---
9
+ `OTel::Connector::signaltometrics`, a resource type of the otel lexicon.
@@ -49,9 +49,13 @@ export interface CollectorEndpoints {
49
49
  };
50
50
  }
51
51
  /**
52
- * The ports a built collector config listens on: every receiver `endpoint`,
52
+ * The ports a built collector config listens on: the endpoint of every
53
+ * receiver that listens (otlp, zipkin, jaeger; the receivers OTEL117 knows),
53
54
  * named after the receiver and the protocol key above it (`otlp-grpc`,
54
- * `otlp-http`), and the `health_check` port if the service enables it.
55
+ * `otlp-http`), and the `health_check` port if the service enables it. A
56
+ * receiver whose `endpoint` is a server it connects to, such as
57
+ * kubeletstats' kubelet, adds no port, and neither does a receiver type the
58
+ * table doesn't list.
55
59
  */
56
60
  export declare function collectorEndpoints(config: CollectorConfig): CollectorEndpoints;
57
61
  //# sourceMappingURL=platform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAM7D,OAAO,EAA6B,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAEvF,4FAA4F;AAC5F,eAAO,MAAM,eAAe,QAAoF,CAAC;AAEjH,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,SAAS,CAAC,EAAE,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;IACrD,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,UAAU,EAAE,CAoB9E;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AA8BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CA6B9E"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAM7D,OAAO,EAA6B,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAGvF,4FAA4F;AAC5F,eAAO,MAAM,eAAe,QAAoF,CAAC;AAEjH,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,SAAS,CAAC,EAAE,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;IACrD,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,UAAU,EAAE,CAoB9E;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AA+BD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CA2B9E"}
@@ -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;AA4B9D;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,aAyFxB,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;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,aA4GxB,CAAC"}
@@ -8,16 +8,32 @@ import type { SerializerResult } from "@intentius/chant/serializer";
8
8
  import { loadAll } from "js-yaml";
9
9
  import type { Declarable } from "@intentius/chant/declarable";
10
10
  import { looksLikeCollectorConfig, type CollectorConfig } from "../../model";
11
+ import { configMapCollectorConfigs, describeConfigMapConfig } from "../../configmap";
11
12
  import { validateCollectorConfig, validateCollectorEntities, type CollectorIssueCode, type CollectorIssue } from "../../validate-config";
12
13
 
14
+ /** Where a collector config was found in the build output. */
15
+ export interface FoundCollectorConfig {
16
+ /** The lexicon output, or the output file, the config came from. */
17
+ source: string;
18
+ config: CollectorConfig;
19
+ /** Set when the config is a value in a Kubernetes ConfigMap (chant #2930). */
20
+ configMap?: { namespace: string; name: string; key: string };
21
+ }
22
+
13
23
  /**
14
- * Every collector config in the output: the otel lexicon's own, and any YAML
15
- * document shaped like one. Parsed with js-yaml rather than `ctx.docs`,
16
- * because collector configs are written with flow lists (`[otlp, batch]`)
17
- * that core's small YAML reader keeps as strings.
24
+ * Every collector config in the output: the otel lexicon's own, any YAML
25
+ * document shaped like one, and any ConfigMap data value that parses as one
26
+ * (how `OtelCollector`, `OtelCollectorGateway` and `GkeOtelCollector` carry
27
+ * theirs). Parsed with js-yaml rather than `ctx.docs`, because collector
28
+ * configs are written with flow lists (`[otlp, batch]`) that core's small
29
+ * YAML reader keeps as strings.
30
+ *
31
+ * `chant build` hands each lexicon's checks only that lexicon's output, so
32
+ * the otel checks see ConfigMaps only in a context that includes k8s output.
33
+ * The k8s lexicon's WK8604 runs the same config checks over its own output.
18
34
  */
19
- export function collectorConfigs(ctx: PostSynthContext): Array<{ source: string; config: CollectorConfig }> {
20
- const out: Array<{ source: string; config: CollectorConfig }> = [];
35
+ export function collectorConfigs(ctx: PostSynthContext): FoundCollectorConfig[] {
36
+ const out: FoundCollectorConfig[] = [];
21
37
  for (const [lexicon, output] of ctx.outputs) {
22
38
  const texts: Array<[string, string]> =
23
39
  typeof output === "string"
@@ -35,6 +51,10 @@ export function collectorConfigs(ctx: PostSynthContext): Array<{ source: string;
35
51
  if (typeof doc !== "object" || doc === null || Array.isArray(doc)) continue;
36
52
  if ((lexicon === "otel" && source === lexicon) || looksLikeCollectorConfig(doc)) {
37
53
  out.push({ source, config: doc as CollectorConfig });
54
+ continue;
55
+ }
56
+ for (const { config, ...configMap } of configMapCollectorConfigs(doc)) {
57
+ out.push({ source, config, configMap });
38
58
  }
39
59
  }
40
60
  }
@@ -42,22 +62,34 @@ export function collectorConfigs(ctx: PostSynthContext): Array<{ source: string;
42
62
  return out;
43
63
  }
44
64
 
45
- function toDiagnostic(issue: CollectorIssue, source?: string): PostSynthDiagnostic {
65
+ function toDiagnostic(issue: CollectorIssue, found?: Omit<FoundCollectorConfig, "config">): PostSynthDiagnostic {
66
+ const where = found?.configMap ? describeConfigMapConfig(found.configMap) : found && found.source !== "otel" ? found.source : undefined;
46
67
  return {
47
68
  checkId: issue.code,
48
69
  severity: issue.severity,
49
- message: source && source !== "otel" ? `${source}: ${issue.message}` : issue.message,
70
+ message: where ? `${where}: ${issue.message}` : issue.message,
50
71
  ...(issue.component ? { entity: issue.component } : issue.pipeline ? { entity: issue.pipeline } : {}),
51
72
  lexicon: "otel",
52
73
  };
53
74
  }
54
75
 
55
- /** Diagnostics for one config-level code (OTEL101-OTEL106, OTEL112) across every collector config in the output. */
76
+ /**
77
+ * Every config-level diagnostic (OTEL101-OTEL106, OTEL112-OTEL117 and any later
78
+ * config check) over the collector configs in the output. `configMapsOnly`
79
+ * keeps the configs held in ConfigMaps, which is what WK8604 reads.
80
+ */
81
+ export function collectorConfigDiagnostics(ctx: PostSynthContext, opts: { configMapsOnly?: boolean } = {}): PostSynthDiagnostic[] {
82
+ return collectorConfigs(ctx)
83
+ .filter((found) => !opts.configMapsOnly || found.configMap)
84
+ .flatMap(({ config, ...found }) => validateCollectorConfig(config).map((i) => toDiagnostic(i, found)));
85
+ }
86
+
87
+ /** Diagnostics for one config-level code (OTEL101-OTEL106, OTEL112-OTEL117) across every collector config in the output. */
56
88
  export function configDiagnostics(ctx: PostSynthContext, code: CollectorIssueCode): PostSynthDiagnostic[] {
57
- return collectorConfigs(ctx).flatMap(({ source, config }) =>
89
+ return collectorConfigs(ctx).flatMap(({ config, ...found }) =>
58
90
  validateCollectorConfig(config)
59
91
  .filter((i) => i.code === code)
60
- .map((i) => toDiagnostic(i, source)),
92
+ .map((i) => toDiagnostic(i, found)),
61
93
  );
62
94
  }
63
95
 
@@ -0,0 +1,17 @@
1
+ /**
2
+ * OTEL113: Pipelines form a cycle through connectors
3
+ *
4
+ * A connector carries data from the pipeline that lists it as an exporter to the pipeline that lists it as a receiver. When those hops lead back to a pipeline already on the path (traces/a feeds traces/b through one connector and traces/b feeds traces/a through another, or one pipeline lists the same `forward` connector on both sides), the collector refuses to start. The check walks the `edges` `collectorTopology()` returns and names one cycle per group of pipelines caught in it.
5
+ */
6
+
7
+ import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
8
+ import { configDiagnostics } from "./otel-helpers";
9
+
10
+ export const otel113: PostSynthCheck = {
11
+ id: "OTEL113",
12
+ description: "Pipelines form a cycle through connectors",
13
+
14
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
15
+ return configDiagnostics(ctx, "OTEL113");
16
+ },
17
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * OTEL114: A connector id is also declared as a receiver or exporter
3
+ *
4
+ * A pipeline names a connector the same way it names a receiver or an exporter, so the collector refuses a config where a connector id is also declared under `receivers` or `exporters`, whether or not any pipeline uses it.
5
+ */
6
+
7
+ import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
8
+ import { configDiagnostics } from "./otel-helpers";
9
+
10
+ export const otel114: PostSynthCheck = {
11
+ id: "OTEL114",
12
+ description: "A connector id is also declared as a receiver or exporter",
13
+
14
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
15
+ return configDiagnostics(ctx, "OTEL114");
16
+ },
17
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * OTEL115: A routing connector routes to a pipeline that does not receive from it
3
+ *
4
+ * Every pipeline a `routing` connector names in `table[].pipelines` or `default_pipelines` must list that connector in its receivers. The connector can only hand data to the pipelines it feeds, and the collector refuses to start when a route names any other pipeline or one that does not exist.
5
+ */
6
+
7
+ import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
8
+ import { configDiagnostics } from "./otel-helpers";
9
+
10
+ export const otel115: PostSynthCheck = {
11
+ id: "OTEL115",
12
+ description: "A routing connector routes to a pipeline that does not receive from it",
13
+
14
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
15
+ return configDiagnostics(ctx, "OTEL115");
16
+ },
17
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * OTEL116: A connector splits metrics by a high-cardinality GenAI attribute
3
+ *
4
+ * `gen_ai.conversation.id`, `gen_ai.response.id`, `gen_ai.tool.call.id`, `session.id`, `user.id`, `enduser.id` and the other keys in `GENAI_HIGH_CARDINALITY_ATTRIBUTES` take a new value per response, conversation or user, and the content keys (`gen_ai.input.messages` and the rest of `GENAI_CONTENT_ATTRIBUTES`) are unbounded. Used as a metric attribute in `spanmetrics` or `servicegraph` dimensions, `sum` or `count` attributes, or `signaltometrics` attributes or `include_resource_attributes`, each value starts new time series. The collector accepts such a config without a warning.
5
+ */
6
+
7
+ import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
8
+ import { configDiagnostics } from "./otel-helpers";
9
+
10
+ export const otel116: PostSynthCheck = {
11
+ id: "OTEL116",
12
+ description: "A connector splits metrics by a high-cardinality GenAI attribute",
13
+
14
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
15
+ return configDiagnostics(ctx, "OTEL116");
16
+ },
17
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * OTEL117: Two components the collector starts listen on the same address
3
+ *
4
+ * A receiver or exporter a pipeline lists, an extension in `service.extensions`, and the collector's own metrics endpoint (`localhost:8888` unless `service.telemetry.metrics` says otherwise) each bind an address when the collector starts. Two on the same port, on the same host or with either on a wildcard host (`0.0.0.0`, `::`), make the second bind fail with "address already in use", and the collector exits. `otelcol validate` does not bind, so it accepts such a config. The listeners checked are the otlp, zipkin and jaeger receivers, the prometheus exporter, and the health_check, zpages and pprof extensions, with their defaults at the pinned collector release.
5
+ */
6
+
7
+ import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
8
+ import { configDiagnostics } from "./otel-helpers";
9
+
10
+ export const otel117: PostSynthCheck = {
11
+ id: "OTEL117",
12
+ description: "Two components the collector starts listen on the same address",
13
+
14
+ check(ctx: PostSynthContext): PostSynthDiagnostic[] {
15
+ return configDiagnostics(ctx, "OTEL117");
16
+ },
17
+ };
@@ -1,3 +1,3 @@
1
1
  /** The otel lexicon's AI skills, read from src/skills/. */
2
- export declare const otelSkills: () => import("packages/core/src").SkillDefinition[];
2
+ export declare const otelSkills: () => import("@intentius/chant").SkillDefinition[];
3
3
  //# sourceMappingURL=skill-defs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill-defs.d.ts","sourceRoot":"","sources":["../src/skill-defs.ts"],"names":[],"mappings":"AAEA,2DAA2D;AAC3D,eAAO,MAAM,UAAU,qDAgCrB,CAAC"}
1
+ {"version":3,"file":"skill-defs.d.ts","sourceRoot":"","sources":["../src/skill-defs.ts"],"names":[],"mappings":"AAEA,2DAA2D;AAC3D,eAAO,MAAM,UAAU,oDAgCrB,CAAC"}
@@ -15,6 +15,10 @@ The otel lexicon (`@intentius/chant-lexicon-otel`) types collector config. Each
15
15
  export default { lexicons: ["otel"] };
16
16
  ```
17
17
 
18
+ `chant init --lexicon otel` scaffolds a collector; `--template k8s-agent` scaffolds a per-node Kubernetes agent and `--template genai` a GenAI collector.
19
+
20
+ For a per-node Kubernetes agent, `NodeAgent({ exporters, metricExporters?, clusterName?, kubeletStats? })` declares the whole config: OTLP, host metrics, container logs, `k8sattributes` filtered to the node, and `memory_limiter` first and `batch` last on every pipeline. Pass `Object.values(agent.members)` wherever an entity list is taken, such as the k8s lexicon's `OtelCollector` `config`, which adds what the config reads from the node: `K8S_NODE_NAME` from `spec.nodeName`, the host root at `/hostfs` and `/var/log/pods` read-only, group 0 for the log files, and the RBAC.
21
+
18
22
  ## Declaring components
19
23
 
20
24
  Every component class takes the collector's own config keys (snake_case, as in the collector docs) plus an optional `name`. The id is `type`, or `type/name` when `name` is set.
@@ -41,10 +45,10 @@ Emits `receivers.otlp`, `processors.memory_limiter` and `processors.batch`, `exp
41
45
  | Kind | Types |
42
46
  |---|---|
43
47
  | receivers | otlp, prometheus, hostmetrics, filelog, k8s_cluster, kubeletstats |
44
- | processors | batch, memory_limiter, resource, attributes, k8sattributes, resourcedetection, filter, transform, redaction, tail_sampling, probabilistic_sampler |
48
+ | processors | batch, memory_limiter, resource, attributes, k8sattributes, resourcedetection, filter, transform, redaction, tail_sampling, probabilistic_sampler, deltatocumulative |
45
49
  | exporters | otlp, otlphttp, debug, prometheus, googlecloud, loadbalancing |
46
- | connectors | spanmetrics, servicegraph, routing, forward, count, sum |
47
- | extensions | health_check, pprof, zpages |
50
+ | connectors | spanmetrics, servicegraph, routing, forward, count, sum, signaltometrics |
51
+ | extensions | health_check, pprof, zpages, k8s_leader_elector |
48
52
 
49
53
  Anything else goes through `defineComponent`; see the `chant-otel-custom-components` skill.
50
54
 
@@ -58,7 +62,7 @@ export const traces = new Pipeline({ signal: "traces", receivers: [otlp], export
58
62
  export const red = new Pipeline({ signal: "metrics", name: "red", receivers: [spanmetrics], exporters: [prom] });
59
63
  ```
60
64
 
61
- `spanmetrics` and `servicegraph` turn traces into metrics, `count` and `sum` turn any signal into metrics (`sum` adds up a numeric attribute), `routing` and `forward` keep the signal. A connector on one side only fails OTEL101; a pipeline whose signal the connector can't pair fails OTEL112.
65
+ `spanmetrics` and `servicegraph` turn traces into metrics, `count` and `sum` turn any signal into metrics (`sum` adds up a numeric attribute), `signaltometrics` builds metrics you name, of any type, from any signal with OTTL values, `routing` and `forward` keep the signal. A connector on one side only fails OTEL101; a pipeline whose signal the connector can't pair fails OTEL112. Pipelines that feed each other in a loop through connectors fail OTEL113, a connector id that is also a receiver or exporter id fails OTEL114, and every pipeline a `routing` connector routes to must list it in `receivers` (OTEL115).
62
66
 
63
67
  ## GenAI workloads
64
68
 
@@ -68,7 +72,7 @@ For services that emit GenAI spans, start from the preset instead of writing the
68
72
  export const collector = genAiPipeline({ traceExporters: [tempo], metricExporters: [prom] });
69
73
  ```
70
74
 
71
- It deletes prompt, completion, system-instruction and tool-call content from spans, span events and logs, and derives call, error, duration and token metrics (`genai_calls_total`, `genai_duration_seconds`, `genai_tokens_input_total`, `genai_tokens_output_total`) from every GenAI span before sampling. Keep content only when asked, with `keepContent: true`. `genAiComponents()` returns the pieces for hand-built pipelines.
75
+ It deletes prompt, completion, system-instruction and tool-call content from spans, span events and logs, and derives call, error, duration and token metrics (`genai_calls_total`, `genai_duration_seconds`, `genai_tokens_input_total`, `genai_tokens_output_total`) from every GenAI span before sampling. Keep content only when asked, with `keepContent: true`. When a dashboard or backend expects the semantic conventions' names, add `clientMetrics: "derive"` for `gen_ai.client.operation.duration` and `gen_ai.client.token.usage` from spans, or `"passthrough"` when the SDK already records them; never both. Read metric names from `genAiMetrics(options)` (`.client` for the conventions' ones) instead of writing them out. `genAiComponents()` returns the pieces for hand-built pipelines. The token sums and derived client metrics are deltas: `deltaToCumulative: "auto"` puts a `deltatocumulative` processor in front of any metric exporter other than `prometheus` or `debug` (the default with `clientMetrics: "derive"`), `true` always, `false` never.
72
76
 
73
77
  ## Rules
74
78
 
@@ -76,6 +80,8 @@ It deletes prompt, completion, system-instruction and tool-call content from spa
76
80
  - Put `memory_limiter` first in `processors` (OTEL105).
77
81
  - Never write a credential literally. Use `"${env:NAME}"` and the collector reads it at start-up (OTEL002).
78
82
  - Every pipeline needs at least one receiver and one exporter (OTEL102). A declared component no pipeline uses is a warning (OTEL103).
83
+ - Don't split metrics by a per-request id (`gen_ai.conversation.id`, `gen_ai.response.id`, `gen_ai.tool.call.id`, `session.id`, `user.id`, `enduser.id`) or a content key: each value starts new time series (OTEL116).
84
+ - Give every listener its own port. The collector's own metrics already use localhost:8888, so a `prometheus` exporter there makes it exit with "address already in use" (OTEL117).
79
85
  - Declared extensions are enabled in declaration order unless a `Service` lists `extensions` itself.
80
86
 
81
87
  ## Starting from an existing config
@@ -36,6 +36,11 @@ export interface TopologyComponent {
36
36
  schema?: SchemaPin;
37
37
  /** Addresses it listens on or sends to, as the config states them. Empty when the config names none. */
38
38
  endpoints: string[];
39
+ /**
40
+ * The wire protocols it speaks, as OTLP SDKs name them (`grpc`, `http/protobuf`, `http/json`).
41
+ * Empty when its definition states none, which a protocol check reads as unknown.
42
+ */
43
+ protocols: string[];
39
44
  /** The pipelines that use it. For a connector, those on either side; for an extension, empty. */
40
45
  pipelines: string[];
41
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAgD,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAE5D,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kHAAkH;IAClH,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,wGAAwG;IACxG,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iGAAiG;IACjG,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,oFAAoF;IACpF,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B;;;;OAIG;IACH,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB;;;;OAIG;IACH,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAeD,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CA2D5E;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,iBAAiB,CAE/G"}
1
+ {"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAgD,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAE5D,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kHAAkH;IAClH,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,wGAAwG;IACxG,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;OAGG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iGAAiG;IACjG,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,oFAAoF;IACpF,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B;;;;OAIG;IACH,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB;;;;OAIG;IACH,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAyBD,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CA4D5E;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,iBAAiB,CAE/G"}
@@ -10,7 +10,7 @@
10
10
  import type { Declarable } from "@intentius/chant/declarable";
11
11
  import { type CollectorConfig } from "./model.js";
12
12
  import "./components/connectors.js";
13
- export type CollectorIssueCode = "OTEL101" | "OTEL102" | "OTEL103" | "OTEL104" | "OTEL105" | "OTEL106" | "OTEL107" | "OTEL108" | "OTEL109" | "OTEL112";
13
+ export type CollectorIssueCode = "OTEL101" | "OTEL102" | "OTEL103" | "OTEL104" | "OTEL105" | "OTEL106" | "OTEL107" | "OTEL108" | "OTEL109" | "OTEL112" | "OTEL113" | "OTEL114" | "OTEL115" | "OTEL116" | "OTEL117";
14
14
  export interface CollectorIssue {
15
15
  code: CollectorIssueCode;
16
16
  severity: "error" | "warning";
@@ -22,9 +22,21 @@ export interface CollectorIssue {
22
22
  }
23
23
  /**
24
24
  * Check a collector config's references and pipeline shape (OTEL101-OTEL106),
25
- * and each connector's signals against its definition (OTEL112).
25
+ * each connector's signals against its definition (OTEL112), cycles through
26
+ * connectors (OTEL113), connector ids shared with a receiver or exporter
27
+ * (OTEL114), `routing` connector targets (OTEL115), the attributes
28
+ * connectors split metrics by (OTEL116), and started components that listen
29
+ * on the same address (OTEL117).
26
30
  */
27
31
  export declare function validateCollectorConfig(config: CollectorConfig): CollectorIssue[];
32
+ /**
33
+ * The config key paths to the addresses a receiver of this type listens on,
34
+ * from the table OTEL117 checks. Empty for a type not in the table, whose
35
+ * `endpoint` may be a server the collector connects to. `collectorEndpoints`
36
+ * reads the receiver ports from here, so the ports a platform composite
37
+ * publishes and the listeners OTEL117 compares are the same set.
38
+ */
39
+ export declare function receiverListenerPaths(type: string): string[][];
28
40
  /**
29
41
  * Check declared entities for what only the declaration knows (OTEL107-OTEL109):
30
42
  * each component's own config rules, duplicate ids, and custom components'
@@ -1 +1 @@
1
- {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../src/validate-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,EAA4D,KAAK,eAAe,EAA4B,MAAM,SAAS,CAAC;AAGnI,OAAO,yBAAyB,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,EAAE,CA0JjF;AA2CD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,cAAc,EAAE,CAyDpH"}
1
+ {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../src/validate-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,EAA4D,KAAK,eAAe,EAA4B,MAAM,SAAS,CAAC;AAMnI,OAAO,yBAAyB,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAC1B,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,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,EAAE,CAkKjF;AA+RD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAE9D;AAuJD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,cAAc,EAAE,CAyDpH"}
@@ -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;AAMvF,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEvF,0DAA0D;AAC1D,eAAO,MAAM,cAAc,UA6B1B,CAAC;AAEF,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CA2CxD"}
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;AAMvF,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEvF,0DAA0D;AAC1D,eAAO,MAAM,cAAc,UAsC1B,CAAC;AAEF,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CAmDxD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-otel",
3
- "version": "0.100.0",
3
+ "version": "0.102.0",
4
4
  "description": "OpenTelemetry Collector lexicon for chant — typed receivers, processors, exporters, connectors, extensions and pipelines, serialized to collector YAML",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -56,7 +56,7 @@
56
56
  "validate": "tsx src/validate-cli.ts",
57
57
  "docs": "tsx src/codegen/docs-cli.ts",
58
58
  "prepack": "npm run generate && npm run bundle && npm run validate && npm run build",
59
- "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && find dist -type f \\( -name \"*.js\" -o -name \"*.js.map\" \\) -delete"
59
+ "build": "../../scripts/tsc7.sh -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && find dist -type f \\( -name \"*.js\" -o -name \"*.js.map\" \\) -delete"
60
60
  },
61
61
  "dependencies": {
62
62
  "js-yaml": "^4.3.1"
@@ -68,7 +68,7 @@
68
68
  "typescript": "^5.9.3"
69
69
  },
70
70
  "peerDependencies": {
71
- "@intentius/chant": "^0.100.0",
71
+ "@intentius/chant": "^0.102.0",
72
72
  "typescript": "^5.9.3"
73
73
  }
74
74
  }
@@ -35,10 +35,10 @@ export const traces = new Pipeline({
35
35
  The built-in component set is otlp, prometheus, hostmetrics, filelog,
36
36
  k8s_cluster and kubeletstats receivers; batch, memory_limiter, resource,
37
37
  attributes, k8sattributes, resourcedetection, filter, transform, redaction,
38
- tail_sampling and probabilistic_sampler processors; otlp, otlphttp, debug,
38
+ tail_sampling, probabilistic_sampler and deltatocumulative processors; otlp, otlphttp, debug,
39
39
  prometheus, googlecloud and loadbalancing exporters; spanmetrics,
40
- servicegraph, routing, forward, count and sum connectors; and the
41
- health_check, pprof and zpages extensions. \`genAiPipeline()\` is a preset for
40
+ servicegraph, routing, forward, count, sum and signaltometrics connectors; and the
41
+ health_check, pprof, zpages and k8s_leader_elector extensions. \`genAiPipeline()\` is a preset for
42
42
  GenAI workloads: it removes prompt and completion content and derives agent
43
43
  RED and token metrics.
44
44
  Their config types follow the collector-contrib release named on the
@@ -50,7 +50,12 @@ TypeScript (see Importing a Collector Config).
50
50
  Checks catch a pipeline that uses a component nobody declared (OTEL101), a
51
51
  pipeline with no receivers or exporters (OTEL102), a declared component no
52
52
  pipeline uses (OTEL103), a connector joining pipelines of signals it can't
53
- convert (OTEL112), and a literal credential in source (OTEL002).
53
+ convert (OTEL112), pipelines feeding each other in a cycle (OTEL113), a
54
+ connector id shared with a receiver or exporter (OTEL114), a \`routing\` route
55
+ to a pipeline that doesn't receive from it (OTEL115), a connector
56
+ splitting metrics by a per-request GenAI attribute such as
57
+ \`gen_ai.conversation.id\` (OTEL116), two started components listening
58
+ on the same address (OTEL117), and a literal credential in source (OTEL002).
54
59
  `;
55
60
 
56
61
  const outputFormat = `The otel lexicon serializes every otel entity in a build into **one
@@ -13,6 +13,23 @@
13
13
  */
14
14
  export type Duration = string | number;
15
15
 
16
+ const GO_DURATION_UNITS: Record<string, number> = { ns: 1e-6, us: 1e-3, "µs": 1e-3, "μs": 1e-3, ms: 1, s: 1e3, m: 60e3, h: 3600e3 };
17
+
18
+ /** A Go duration in milliseconds, `fallback` when unset, or undefined when it isn't one this can read. */
19
+ export function goDurationMs(d: Duration | undefined, fallback: number): number | undefined {
20
+ if (d === undefined) return fallback;
21
+ if (typeof d === "number") return d / 1e6;
22
+ // time.ParseDuration takes a bare "0" without a unit.
23
+ if (/^[+-]?0$/.test(d.trim())) return 0;
24
+ const m = d.trim().match(/^([+-]?)((?:\d+(?:\.\d*)?|\.\d+)(?:ns|us|µs|μs|ms|s|m|h))+$/);
25
+ if (!m) return undefined;
26
+ let total = 0;
27
+ for (const part of d.trim().matchAll(/(\d+(?:\.\d*)?|\.\d+)(ns|us|µs|μs|ms|s|m|h)/g)) {
28
+ total += Number(part[1]) * GO_DURATION_UNITS[part[2]];
29
+ }
30
+ return m[1] === "-" ? -total : total;
31
+ }
32
+
16
33
  export interface TLSClientSettings {
17
34
  insecure?: boolean;
18
35
  insecure_skip_verify?: boolean;