@intentius/chant-lexicon-otel 0.124.45 → 0.124.48

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 (211) hide show
  1. package/README.md +2 -2
  2. package/dist/build/capability-plugin.d.ts +10 -0
  3. package/dist/build/capability-plugin.d.ts.map +1 -0
  4. package/dist/build/capability-plugin.js +19 -0
  5. package/dist/build/ocb-build.d.ts +38 -0
  6. package/dist/build/ocb-build.d.ts.map +1 -0
  7. package/dist/build/ocb-build.js +49 -0
  8. package/dist/clickhouse-tables.d.ts +73 -0
  9. package/dist/clickhouse-tables.d.ts.map +1 -0
  10. package/dist/clickhouse-tables.js +199 -0
  11. package/dist/codegen/docs.d.ts.map +1 -1
  12. package/dist/codegen/docs.js +4 -2
  13. package/dist/codegen/generate.d.ts +29 -10
  14. package/dist/codegen/generate.d.ts.map +1 -1
  15. package/dist/codegen/generate.js +82 -17
  16. package/dist/components/common.d.ts +3 -1
  17. package/dist/components/common.d.ts.map +1 -1
  18. package/dist/components/common.js +2 -0
  19. package/dist/components/connectors.d.ts +25 -90
  20. package/dist/components/connectors.d.ts.map +1 -1
  21. package/dist/components/connectors.js +3 -0
  22. package/dist/components/exporters.d.ts +78 -34
  23. package/dist/components/exporters.d.ts.map +1 -1
  24. package/dist/components/exporters.js +26 -1
  25. package/dist/components/extensions.d.ts +16 -33
  26. package/dist/components/extensions.d.ts.map +1 -1
  27. package/dist/components/filtering.d.ts +13 -60
  28. package/dist/components/filtering.d.ts.map +1 -1
  29. package/dist/components/k8s-receivers.d.ts +5 -53
  30. package/dist/components/k8s-receivers.d.ts.map +1 -1
  31. package/dist/components/overlay.d.ts +25 -0
  32. package/dist/components/overlay.d.ts.map +1 -0
  33. package/dist/components/overlay.js +19 -0
  34. package/dist/components/processors.d.ts +18 -79
  35. package/dist/components/processors.d.ts.map +1 -1
  36. package/dist/components/receivers.d.ts +17 -71
  37. package/dist/components/receivers.d.ts.map +1 -1
  38. package/dist/components/receivers.js +3 -1
  39. package/dist/components/sampling.d.ts +19 -35
  40. package/dist/components/sampling.d.ts.map +1 -1
  41. package/dist/config-hygiene.d.ts +10 -8
  42. package/dist/config-hygiene.d.ts.map +1 -1
  43. package/dist/config-hygiene.js +36 -13
  44. package/dist/coverage.d.ts +50 -0
  45. package/dist/coverage.d.ts.map +1 -0
  46. package/dist/coverage.js +92 -0
  47. package/dist/define.d.ts +8 -5
  48. package/dist/define.d.ts.map +1 -1
  49. package/dist/define.js +10 -6
  50. package/dist/distribution.d.ts +125 -0
  51. package/dist/distribution.d.ts.map +1 -0
  52. package/dist/distribution.js +227 -0
  53. package/dist/generated/index.d.ts +4234 -0
  54. package/dist/generated/index.d.ts.map +1 -0
  55. package/dist/generated/index.js +23 -0
  56. package/dist/index.d.ts +7 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +9 -1
  59. package/dist/init-templates.js +2 -2
  60. package/dist/integrity.json +11 -9
  61. package/dist/lint/audit-catalog.d.ts +3 -0
  62. package/dist/lint/audit-catalog.d.ts.map +1 -1
  63. package/dist/lint/audit-catalog.js +5 -0
  64. package/dist/lint/post-synth/index.d.ts.map +1 -1
  65. package/dist/lint/post-synth/index.js +4 -0
  66. package/dist/lint/post-synth/otel-helpers.d.ts +2 -1
  67. package/dist/lint/post-synth/otel-helpers.d.ts.map +1 -1
  68. package/dist/lint/post-synth/otel-helpers.js +1 -1
  69. package/dist/lint/post-synth/otel119.d.ts +1 -1
  70. package/dist/lint/post-synth/otel119.js +1 -1
  71. package/dist/lint/post-synth/otel125.d.ts +1 -1
  72. package/dist/lint/post-synth/otel125.js +1 -1
  73. package/dist/lint/post-synth/otel126.d.ts +1 -1
  74. package/dist/lint/post-synth/otel126.js +1 -1
  75. package/dist/lint/post-synth/otel127.d.ts +1 -1
  76. package/dist/lint/post-synth/otel127.js +1 -1
  77. package/dist/lint/post-synth/otel128.d.ts +8 -0
  78. package/dist/lint/post-synth/otel128.d.ts.map +1 -0
  79. package/dist/lint/post-synth/otel128.js +17 -0
  80. package/dist/lint/post-synth/otel129.d.ts +15 -0
  81. package/dist/lint/post-synth/otel129.d.ts.map +1 -0
  82. package/dist/lint/post-synth/otel129.js +92 -0
  83. package/dist/lsp/completions.d.ts +10 -1
  84. package/dist/lsp/completions.d.ts.map +1 -1
  85. package/dist/lsp/completions.js +29 -1
  86. package/dist/lsp/hover.d.ts +5 -1
  87. package/dist/lsp/hover.d.ts.map +1 -1
  88. package/dist/lsp/hover.js +16 -3
  89. package/dist/lsp/properties.d.ts +34 -0
  90. package/dist/lsp/properties.d.ts.map +1 -0
  91. package/dist/lsp/properties.js +135 -0
  92. package/dist/manifest.json +1 -1
  93. package/dist/meta.json +5 -0
  94. package/dist/metric-names.d.ts +36 -8
  95. package/dist/metric-names.d.ts.map +1 -1
  96. package/dist/metric-names.js +42 -9
  97. package/dist/model.d.ts +1 -1
  98. package/dist/model.js +1 -1
  99. package/dist/okf/index.md +3 -0
  100. package/dist/okf/rules/OTEL128.md +11 -0
  101. package/dist/okf/rules/OTEL129.md +11 -0
  102. package/dist/okf/types/ClickHouseExporter.md +9 -0
  103. package/dist/op/activities/collector-audit.d.ts +18 -6
  104. package/dist/op/activities/collector-audit.d.ts.map +1 -1
  105. package/dist/op/activities/collector-audit.js +37 -21
  106. package/dist/plugin.d.ts.map +1 -1
  107. package/dist/plugin.js +51 -8
  108. package/dist/rules/otel-helpers.ts +1 -1
  109. package/dist/rules/otel119.ts +1 -1
  110. package/dist/rules/otel125.ts +1 -1
  111. package/dist/rules/otel126.ts +1 -1
  112. package/dist/rules/otel127.ts +1 -1
  113. package/dist/rules/otel128.ts +22 -0
  114. package/dist/rules/otel129.ts +99 -0
  115. package/dist/serializer.d.ts +3 -0
  116. package/dist/serializer.d.ts.map +1 -1
  117. package/dist/serializer.js +12 -2
  118. package/dist/spec/builtins.d.ts +17 -0
  119. package/dist/spec/builtins.d.ts.map +1 -0
  120. package/dist/spec/builtins.js +45 -0
  121. package/dist/spec/fetch.d.ts +120 -0
  122. package/dist/spec/fetch.d.ts.map +1 -0
  123. package/dist/spec/fetch.js +282 -0
  124. package/dist/spec/parse.d.ts +77 -0
  125. package/dist/spec/parse.d.ts.map +1 -0
  126. package/dist/spec/parse.js +337 -0
  127. package/dist/spec/pin.d.ts +82 -0
  128. package/dist/spec/pin.d.ts.map +1 -0
  129. package/dist/spec/pin.js +126 -0
  130. package/dist/spec/snapshot-cli.d.ts +13 -0
  131. package/dist/spec/snapshot-cli.d.ts.map +1 -0
  132. package/dist/spec/snapshot-cli.js +31 -0
  133. package/dist/spec/snapshot.d.ts +9 -0
  134. package/dist/spec/snapshot.d.ts.map +1 -0
  135. package/dist/spec/snapshot.js +14 -0
  136. package/dist/types/index.d.ts +3 -2
  137. package/dist/validate-config.d.ts +1 -1
  138. package/dist/validate-config.d.ts.map +1 -1
  139. package/dist/validate.d.ts.map +1 -1
  140. package/dist/validate.js +1 -0
  141. package/dist/workspace-links.d.ts +25 -0
  142. package/dist/workspace-links.d.ts.map +1 -0
  143. package/dist/workspace-links.js +49 -0
  144. package/package.json +3 -2
  145. package/src/build/capability-plugin.ts +30 -0
  146. package/src/build/ocb-build.ts +73 -0
  147. package/src/clickhouse-exporter.e2e.test.ts +208 -0
  148. package/src/clickhouse-tables.test.ts +216 -0
  149. package/src/clickhouse-tables.ts +223 -0
  150. package/src/codegen/docs.ts +4 -2
  151. package/src/codegen/generate.ts +95 -19
  152. package/src/components/common.ts +4 -2
  153. package/src/components/connectors.ts +30 -77
  154. package/src/components/exporters.ts +128 -61
  155. package/src/components/extensions.ts +22 -36
  156. package/src/components/filtering.ts +17 -58
  157. package/src/components/k8s-receivers.test.ts +1 -1
  158. package/src/components/k8s-receivers.ts +3 -45
  159. package/src/components/overlay.ts +24 -0
  160. package/src/components/processors.ts +18 -63
  161. package/src/components/receivers.ts +20 -60
  162. package/src/components/sampling.ts +24 -37
  163. package/src/config-hygiene.ts +36 -13
  164. package/src/coverage.test.ts +37 -0
  165. package/src/coverage.ts +121 -0
  166. package/src/define.test.ts +2 -0
  167. package/src/define.ts +10 -6
  168. package/src/distribution.test.ts +250 -0
  169. package/src/distribution.ts +305 -0
  170. package/src/generated/index.ts +4576 -0
  171. package/src/generated/lexicon-otel.json +5 -0
  172. package/src/generated/properties.json +1 -0
  173. package/src/import/roundtrip.test.ts +16 -0
  174. package/src/import/testdata/clickhouse.yaml +37 -0
  175. package/src/import/testdata/fixtures.ts +17 -2
  176. package/src/import/testdata/upstream/clickhouse-exporter.yaml +60 -0
  177. package/src/index.ts +69 -0
  178. package/src/init-templates.ts +2 -2
  179. package/src/lint/audit-catalog.ts +15 -0
  180. package/src/lint/post-synth/index.ts +4 -0
  181. package/src/lint/post-synth/otel-helpers.ts +1 -1
  182. package/src/lint/post-synth/otel119.ts +1 -1
  183. package/src/lint/post-synth/otel125.ts +1 -1
  184. package/src/lint/post-synth/otel126.ts +1 -1
  185. package/src/lint/post-synth/otel127.ts +1 -1
  186. package/src/lint/post-synth/otel128.ts +22 -0
  187. package/src/lint/post-synth/otel129.ts +99 -0
  188. package/src/lsp/completions.ts +30 -1
  189. package/src/lsp/hover.ts +14 -3
  190. package/src/lsp/properties.test.ts +72 -0
  191. package/src/lsp/properties.ts +141 -0
  192. package/src/metric-names.test.ts +11 -0
  193. package/src/metric-names.ts +64 -16
  194. package/src/model.ts +1 -1
  195. package/src/op/activities/collector-audit.test.ts +29 -22
  196. package/src/op/activities/collector-audit.ts +38 -18
  197. package/src/plugin.test.ts +2 -0
  198. package/src/plugin.ts +57 -6
  199. package/src/serializer.ts +11 -2
  200. package/src/spec/builtins.ts +56 -0
  201. package/src/spec/fetch.ts +332 -0
  202. package/src/spec/otel-schemas.snapshot.json +13932 -0
  203. package/src/spec/parse.ts +364 -0
  204. package/src/spec/pin.ts +155 -0
  205. package/src/spec/snapshot-cli.ts +32 -0
  206. package/src/spec/snapshot.ts +19 -0
  207. package/src/spec/spec.test.ts +144 -0
  208. package/src/validate-config.ts +4 -3
  209. package/src/validate.ts +1 -0
  210. package/src/workspace-links.e2e.test.ts +91 -0
  211. package/src/workspace-links.ts +50 -0
@@ -3,22 +3,13 @@
3
3
  */
4
4
 
5
5
  import { defineBuiltin } from "../define";
6
- import type { Duration, GRPCServerSettings, HTTPServerSettings, TLSClientSettings } from "./common";
6
+ import type { Overlay, Require } from "./overlay";
7
+ import type { FileLogReceiverSchemaConfig, HostMetricsReceiverSchemaConfig, OtlpReceiverSchemaConfig, PrometheusReceiverSchemaConfig } from "../generated/index";
8
+ import type { Duration } from "./common";
7
9
 
8
10
  // ── otlp ─────────────────────────────────────────────────────────────
9
11
 
10
- export interface OtlpReceiverConfig {
11
- protocols?: {
12
- grpc?: GRPCServerSettings | null;
13
- http?:
14
- | (HTTPServerSettings & {
15
- traces_url_path?: string;
16
- metrics_url_path?: string;
17
- logs_url_path?: string;
18
- })
19
- | null;
20
- };
21
- }
12
+ export type OtlpReceiverConfig = OtlpReceiverSchemaConfig;
22
13
 
23
14
  /** Receives OTLP over gRPC (default port 4317) and HTTP (default port 4318). */
24
15
  export const OtlpReceiver = defineBuiltin<OtlpReceiverConfig, "receiver", "otlp">({
@@ -154,21 +145,8 @@ export interface PrometheusScrapeConfig extends PrometheusProxySettings {
154
145
  metric_name_escaping_scheme?: "allow-utf-8" | "underscores" | "dots" | "values";
155
146
  }
156
147
 
157
- export interface PrometheusReceiverConfig {
158
- config: {
159
- global?: { scrape_interval?: Duration; scrape_timeout?: Duration; evaluation_interval?: Duration; external_labels?: Record<string, string> };
160
- scrape_configs: PrometheusScrapeConfig[];
161
- };
162
- trim_metric_suffixes?: boolean;
163
- use_start_time_metric?: boolean;
164
- start_time_metric_regex?: string;
165
- target_allocator?: {
166
- endpoint: string;
167
- interval?: Duration;
168
- collector_id?: string;
169
- tls?: TLSClientSettings;
170
- };
171
- }
148
+ /** The receiver refuses to start without a Prometheus `config`. */
149
+ export type PrometheusReceiverConfig = Require<PrometheusReceiverSchemaConfig, "config">;
172
150
 
173
151
  /** Scrapes Prometheus endpoints with Prometheus's own scrape config. */
174
152
  export const PrometheusReceiver = defineBuiltin<PrometheusReceiverConfig, "receiver", "prometheus">({
@@ -179,6 +157,7 @@ export const PrometheusReceiver = defineBuiltin<PrometheusReceiverConfig, "recei
179
157
  const problems: string[] = [];
180
158
  const seen = new Set<string>();
181
159
  for (const job of c.config?.scrape_configs ?? []) {
160
+ if (job.job_name === undefined) continue;
182
161
  if (seen.has(job.job_name)) problems.push(`scrape job "${job.job_name}" is declared twice`);
183
162
  seen.add(job.job_name);
184
163
  }
@@ -188,7 +167,7 @@ export const PrometheusReceiver = defineBuiltin<PrometheusReceiverConfig, "recei
188
167
  return problems;
189
168
  },
190
169
  endpoints: (c) =>
191
- (c.config?.scrape_configs ?? []).flatMap((job) => (job.static_configs ?? []).flatMap((s) => s.targets)),
170
+ (c.config?.scrape_configs ?? []).flatMap((job) => (job.static_configs ?? []).flatMap((s) => s.targets ?? [])),
192
171
  });
193
172
 
194
173
  // ── hostmetrics ──────────────────────────────────────────────────────
@@ -205,14 +184,16 @@ export type HostMetricsScraper =
205
184
  | "process"
206
185
  | "system";
207
186
 
208
- export interface HostMetricsReceiverConfig {
209
- collection_interval?: Duration;
210
- initial_delay?: Duration;
211
- /** Host root when the collector runs in a container, e.g. `/hostfs`. */
212
- root_path?: string;
213
- /** Scraper name to its settings; `{}` enables a scraper with its defaults. */
214
- scrapers: Partial<Record<HostMetricsScraper, Record<string, unknown>>>;
215
- }
187
+ /**
188
+ * Upstream publishes no schema for the scraper packages
189
+ * (`internal/scraper/*scraper`), so `scrapers` is written here: scraper name
190
+ * to its settings, `{}` for a scraper's defaults. The receiver refuses to
191
+ * start with none.
192
+ */
193
+ export type HostMetricsReceiverConfig = Overlay<
194
+ HostMetricsReceiverSchemaConfig,
195
+ { scrapers: Partial<Record<HostMetricsScraper, Record<string, unknown>>> }
196
+ >;
216
197
 
217
198
  /** Scrapes CPU, memory, disk, filesystem, network and process metrics from the host. */
218
199
  export const HostMetricsReceiver = defineBuiltin<HostMetricsReceiverConfig, "receiver", "hostmetrics">({
@@ -232,29 +213,8 @@ export interface FileLogOperator {
232
213
  [key: string]: unknown;
233
214
  }
234
215
 
235
- export interface FileLogReceiverConfig {
236
- include: string[];
237
- exclude?: string[];
238
- start_at?: "beginning" | "end";
239
- include_file_name?: boolean;
240
- include_file_path?: boolean;
241
- include_file_name_resolved?: boolean;
242
- include_file_path_resolved?: boolean;
243
- poll_interval?: Duration;
244
- max_concurrent_files?: number;
245
- max_log_size?: string;
246
- fingerprint_size?: string;
247
- encoding?: string;
248
- force_flush_period?: Duration;
249
- delete_after_read?: boolean;
250
- /** The id of a storage extension, so offsets survive a restart. */
251
- storage?: string;
252
- multiline?: { line_start_pattern?: string; line_end_pattern?: string; omit_pattern?: boolean };
253
- operators?: FileLogOperator[];
254
- attributes?: Record<string, string>;
255
- resource?: Record<string, string>;
256
- retry_on_failure?: { enabled?: boolean; initial_interval?: Duration; max_interval?: Duration; max_elapsed_time?: Duration };
257
- }
216
+ /** The receiver refuses to start with no `include` pattern. */
217
+ export type FileLogReceiverConfig = Require<FileLogReceiverSchemaConfig, "include">;
258
218
 
259
219
  /** Tails log files and parses them with stanza operators. */
260
220
  export const FileLogReceiver = defineBuiltin<FileLogReceiverConfig, "receiver", "filelog">({
@@ -9,6 +9,8 @@
9
9
  */
10
10
 
11
11
  import { defineBuiltin } from "../define";
12
+ import type { Overlay } from "./overlay";
13
+ import type { LoadBalancingExporterSchemaConfig, ProbabilisticSamplerProcessorSchemaConfig, TailSamplingProcessorSchemaConfig } from "../generated/index";
12
14
  import type { Duration, ExporterHelperSettings, GRPCClientSettings } from "./common";
13
15
 
14
16
  // ── tail_sampling ────────────────────────────────────────────────────
@@ -167,19 +169,21 @@ export type TailSamplingPolicy = TailSamplingLeafPolicy | AndPolicy | DropPolicy
167
169
 
168
170
  export type TailSamplingPolicyType = TailSamplingPolicy["type"];
169
171
 
170
- export interface TailSamplingProcessorConfig {
171
- /** How long after a trace's first span the decision is made. The collector's default is 30s; chant asks for it explicitly. */
172
- decision_wait: Duration;
173
- /** Policies, evaluated for every trace. A trace is sampled when any policy samples it and no `drop` policy drops it. */
174
- policies: TailSamplingPolicy[];
175
- num_traces?: number;
176
- expected_new_traces_per_sec?: number;
177
- decision_cache?: {
178
- sampled_cache_size?: number;
179
- non_sampled_cache_size?: number;
180
- };
181
- sample_on_first_match?: boolean;
182
- }
172
+ /**
173
+ * Upstream writes a policy as one struct with every policy kind's settings as
174
+ * optional members beside `type`. Here a policy is a union tagged by `type`,
175
+ * so the settings the type needs are required and the checks below narrow on
176
+ * it. chant also asks for `decision_wait` explicitly.
177
+ */
178
+ export type TailSamplingProcessorConfig = Overlay<
179
+ TailSamplingProcessorSchemaConfig,
180
+ {
181
+ /** How long after a trace's first span the decision is made. The collector's default is 30s; chant asks for it explicitly. */
182
+ decision_wait: Duration;
183
+ /** Policies, evaluated for every trace. A trace is sampled when any policy samples it and no `drop` policy drops it. */
184
+ policies: TailSamplingPolicy[];
185
+ }
186
+ >;
183
187
 
184
188
  /**
185
189
  * Holds each trace for `decision_wait`, then samples it when a policy says so.
@@ -327,23 +331,7 @@ function subPolicyProblems(subs: ReadonlyArray<TailSamplingPolicy> | undefined,
327
331
 
328
332
  // ── probabilistic_sampler ────────────────────────────────────────────
329
333
 
330
- export interface ProbabilisticSamplerProcessorConfig {
331
- /** Percent of traces or logs kept, 0 to 100. The collector's default is 0, which keeps nothing, so chant asks for it. */
332
- sampling_percentage: number;
333
- /** Salt for `hash_seed` mode. Collectors that sample the same data must share it. */
334
- hash_seed?: number;
335
- /** `hash_seed` (the default for logs), `proportional` (the default for traces) or `equalizing`. */
336
- mode?: "hash_seed" | "proportional" | "equalizing";
337
- /** Default true: an item without usable randomness is dropped. */
338
- fail_closed?: boolean;
339
- /** Hex digits of threshold precision, 1 to 14; default 4. */
340
- sampling_precision?: number;
341
- /** Logs only: sample on the trace id (default) or on `from_attribute` of the record. */
342
- attribute_source?: "traceID" | "record";
343
- from_attribute?: string;
344
- /** Logs only: an attribute whose value overrides the sampling percentage for its record. */
345
- sampling_priority?: string;
346
- }
334
+ export type ProbabilisticSamplerProcessorConfig = ProbabilisticSamplerProcessorSchemaConfig;
347
335
 
348
336
  /** Head sampling: keeps a fixed percentage of traces or logs, decided per item without waiting for the rest of the trace. */
349
337
  export const ProbabilisticSamplerProcessor = defineBuiltin<
@@ -449,13 +437,12 @@ export type LoadBalancingRoutingKey = "traceID" | "service" | "attributes" | "re
449
437
  /** The otlp exporter settings used for every backend. The endpoint comes from the resolver, so it is not set here. */
450
438
  export type LoadBalancingOtlpConfig = Omit<GRPCClientSettings, "endpoint"> & ExporterHelperSettings;
451
439
 
452
- export type LoadBalancingExporterConfig = ExporterHelperSettings & {
453
- protocol?: { otlp: LoadBalancingOtlpConfig };
454
- resolver: LoadBalancingResolver;
455
- routing_key?: LoadBalancingRoutingKey;
456
- /** With `routing_key: attributes`, the span attributes to route on. */
457
- routing_attributes?: string[];
458
- };
440
+ /**
441
+ * Upstream writes the resolver as one struct with each resolver optional. The
442
+ * collector takes exactly one, so here the resolver is a union of the four,
443
+ * and it is required.
444
+ */
445
+ export type LoadBalancingExporterConfig = Overlay<LoadBalancingExporterSchemaConfig, { resolver: LoadBalancingResolver }>;
459
446
 
460
447
  const RESOLVER_KEYS = ["static", "dns", "k8s", "aws_cloud_map"] as const;
461
448
 
@@ -5,8 +5,8 @@
5
5
  * so it runs on emitted YAML, on an imported file and on a config inside a
6
6
  * ConfigMap alike. `validateCollectorConfig` calls `configHygieneIssues`.
7
7
  *
8
- * Every list and version here is read from collector or collector-contrib
9
- * v0.130.0 (`COLLECTOR_PIN`); the lint rules page cites the file for each.
8
+ * Every list and version here is read from collector or collector-contrib at
9
+ * `COLLECTOR_PIN` (v0.162.0); the lint rules page cites the file for each.
10
10
  */
11
11
 
12
12
  import { parseComponentId, type CollectorConfig } from "./model";
@@ -85,10 +85,12 @@ function invertMatchPaths(value: unknown, path: string[], out: string[]): string
85
85
 
86
86
  /**
87
87
  * OTEL119: a field deprecated at or before the pin. The collector still
88
- * reads each of these at v0.130.0, and a later release drops them.
88
+ * parses each of these at v0.162.0 (`COLLECTOR_PIN`), and a later release
89
+ * drops them.
89
90
  *
90
91
  * - `invert_match: true` in a `tail_sampling` policy: inverted decisions are
91
- * deprecated in contrib v0.126.0 (#39833) for a `drop` policy.
92
+ * deprecated in contrib v0.126.0 (#39833) for a `drop` policy, and v0.155.0
93
+ * removed the gate that kept them (#48976).
92
94
  * - `service.telemetry.metrics.address`: deprecated in core v0.111.0
93
95
  * (#11205) for `readers`.
94
96
  * - `dimensions_cache_size` on `spanmetrics`: deprecated in contrib v0.125.0
@@ -107,7 +109,7 @@ function deprecatedFieldIssues(config: CollectorConfig): CollectorIssue[] {
107
109
  code: "OTEL119",
108
110
  severity: "warning",
109
111
  component: id,
110
- message: `processor "${id}" policy ${name} sets ${path}; inverted decisions are deprecated since collector-contrib v0.126.0. Use a drop policy to keep the traces out instead`,
112
+ message: `processor "${id}" policy ${name} sets ${path}; inverted decisions are deprecated since collector-contrib v0.126.0, and v0.155.0 removed the gate that kept them. Use a drop policy to keep the traces out instead`,
111
113
  });
112
114
  }
113
115
  });
@@ -315,8 +317,9 @@ function deliveryIssues(config: CollectorConfig): CollectorIssue[] {
315
317
  /**
316
318
  * The exporters OTEL125 knows send one request per incoming batch unless
317
319
  * told otherwise: `otlp` and `otlphttp`, whose default `sending_queue` at
318
- * v0.130.0 has no `batch` (`exporterhelper/internal/queue_sender.go`,
319
- * `NewDefaultQueueConfig`). Other exporters may batch on their own, so they
320
+ * v0.162.0 has no `batch` (`exporterhelper/internal/queue_sender.go`,
321
+ * `NewDefaultQueueConfig`, while the alpha `pkg.exporterhelper.queueBatchEnabled`
322
+ * gate is off). Other exporters may batch on their own, so they
320
323
  * are not checked.
321
324
  */
322
325
  const UNBATCHED_EXPORTERS = new Set(["otlp", "otlphttp"]);
@@ -353,9 +356,9 @@ function batchIssues(config: CollectorConfig): CollectorIssue[] {
353
356
  // ── OTEL126, OTEL127: names checked against a fixed list ─────────────
354
357
 
355
358
  /**
356
- * The fields `k8sattributes` can extract at v0.130.0: the cases of
357
- * `Config.Validate` (`processor/k8sattributesprocessor/config.go`), with
358
- * the semconv v1.6.1 keys and `options.go` constants they name.
359
+ * The fields `k8sattributes` can extract at v0.162.0 (`COLLECTOR_PIN`): the
360
+ * cases of `Config.Validate` (`processor/k8sattributesprocessor/config.go`),
361
+ * with the semconv keys and `options.go` constants they name.
359
362
  */
360
363
  export const K8S_ATTRIBUTES_METADATA: readonly string[] = Object.freeze([
361
364
  "k8s.namespace.name",
@@ -375,12 +378,14 @@ export const K8S_ATTRIBUTES_METADATA: readonly string[] = Object.freeze([
375
378
  "k8s.job.name",
376
379
  "k8s.job.uid",
377
380
  "k8s.cronjob.name",
381
+ "k8s.cronjob.uid",
378
382
  "k8s.node.name",
379
383
  "k8s.node.uid",
380
384
  "k8s.container.name",
381
385
  "container.id",
382
386
  "container.image.name",
383
387
  "container.image.tag",
388
+ "container.image.tags",
384
389
  "service.namespace",
385
390
  "service.name",
386
391
  "service.version",
@@ -390,14 +395,22 @@ export const K8S_ATTRIBUTES_METADATA: readonly string[] = Object.freeze([
390
395
  ]);
391
396
 
392
397
  /**
393
- * The detectors `resourcedetection` knows at v0.130.0: the keys of the map
394
- * in `NewFactory` (`processor/resourcedetectionprocessor/factory.go`), as
395
- * each detector's `TypeStr` spells them.
398
+ * The detectors `resourcedetection` knows at v0.162.0 (`COLLECTOR_PIN`): the
399
+ * keys of the map in `NewFactory`
400
+ * (`processor/resourcedetectionprocessor/factory.go`), as each detector's
401
+ * `TypeStr` spells them. `k8snode` is the deprecated alias of `k8s_api`
402
+ * (v0.154.0); both still build.
396
403
  */
397
404
  export const RESOURCE_DETECTORS: readonly string[] = Object.freeze([
405
+ "akamai",
406
+ "alibaba_ecs",
398
407
  "aks",
399
408
  "azure",
409
+ "azureappservice",
410
+ "azurecontainerapps",
411
+ "azurefunctions",
400
412
  "consul",
413
+ "digitalocean",
401
414
  "docker",
402
415
  "ec2",
403
416
  "ecs",
@@ -407,11 +420,21 @@ export const RESOURCE_DETECTORS: readonly string[] = Object.freeze([
407
420
  "env",
408
421
  "gcp",
409
422
  "heroku",
423
+ "hetzner",
424
+ "ibmcloud_classic",
425
+ "ibmcloud_vpc",
426
+ "scaleway",
410
427
  "system",
411
428
  "openshift",
429
+ "nova",
430
+ "oraclecloud",
431
+ "k8s_api",
412
432
  "k8snode",
413
433
  "kubeadm",
414
434
  "dynatrace",
435
+ "tencent_cvm",
436
+ "upcloud",
437
+ "vultr",
415
438
  ]);
416
439
 
417
440
  /** OTEL126: `k8sattributes` `extract.metadata` names a field the processor can't extract, so the collector refuses the config. */
@@ -0,0 +1,37 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { coverageReport, formatCoverage } from "./coverage";
3
+ import { otelPlugin } from "./plugin";
4
+ import { loadSnapshot } from "./spec/snapshot";
5
+
6
+ describe("coverageReport against the distribution manifests", () => {
7
+ const report = coverageReport();
8
+
9
+ test("every built-in is in otelcol-contrib, and every one with a schema is generated", async () => {
10
+ expect(report.unaccountedKinds).toEqual([]);
11
+ expect(await otelPlugin.coverageReport!()).toMatchObject({ unaccountedKinds: [] });
12
+ expect(report.generated).toHaveLength(35);
13
+ expect(report.handWritten).toEqual(["ForwardConnector"]);
14
+ });
15
+
16
+ test("reports each distribution's components and what reaches them", () => {
17
+ const contrib = report.distributions.find((d) => d.distribution === "otelcol-contrib")!;
18
+ expect(contrib.components).toBe(242);
19
+ expect(contrib.withSchema).toBe(213);
20
+ expect(contrib.builtinMissing).toEqual([]);
21
+ expect(contrib.builtin.length + contrib.schemaNotBuiltin.length + contrib.noSchemaNotBuiltin.length).toBe(contrib.components);
22
+ const k8s = report.distributions.find((d) => d.distribution === "otelcol-k8s")!;
23
+ expect(k8s.components).toBe(69);
24
+ // The k8s distribution leaves out the cloud and vendor exporters.
25
+ expect(k8s.builtinMissing).toContain("exporter/googlecloud");
26
+ expect(formatCoverage(report)).toContain("otelcol-contrib v0.162.0: 242 components, 213 with a schema");
27
+ });
28
+
29
+ test("a built-in the distribution does not ship is unaccounted", () => {
30
+ const snapshot = loadSnapshot();
31
+ const without = {
32
+ ...snapshot,
33
+ distributions: { ...snapshot.distributions, "otelcol-contrib": snapshot.distributions["otelcol-contrib"].filter((c) => c.type !== "pprof" || c.kind !== "extension") },
34
+ };
35
+ expect(coverageReport(without).unaccountedKinds).toEqual([expect.stringContaining('PprofExtension: extension "pprof" is not in otelcol-contrib')]);
36
+ });
37
+ });
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Coverage of the otel lexicon against a distribution manifest (#3361).
3
+ *
4
+ * The question a collector lexicon answers is "which components of the binary
5
+ * I run does chant type?". The committed snapshot holds the `otelcol-contrib`
6
+ * and `otelcol-k8s` manifests' component index at the pinned releases, with
7
+ * each component's type and whether upstream publishes a `config.schema.yaml`
8
+ * for it. Each component is in one of three places:
9
+ *
10
+ * - a built-in, with its config type generated from the schema (or
11
+ * hand-written when upstream publishes none);
12
+ * - not built in, reached through `defineComponent`, which carries its own pin;
13
+ * - a built-in the distribution does not ship, which is a lexicon defect.
14
+ *
15
+ * `unaccountedKinds` (what `check-lexicon` gates on) lists the defects: a
16
+ * built-in missing from the contrib manifest, or a built-in whose upstream
17
+ * schema exists but whose config type is not generated from it. Everything
18
+ * here is read from the snapshot, offline.
19
+ */
20
+
21
+ import { BUILTIN_SPECS } from "./spec/builtins";
22
+ import { loadSnapshot } from "./spec/snapshot";
23
+ import { DISTRIBUTIONS, type DistributionName, type IndexedComponent, type OtelSpecSnapshot } from "./spec/fetch";
24
+ import type { ComponentKind } from "./model";
25
+
26
+ export interface DistributionCoverage {
27
+ distribution: DistributionName;
28
+ version: string;
29
+ /** Components the manifest lists. */
30
+ components: number;
31
+ /** Of those, how many ship a `config.schema.yaml`. */
32
+ withSchema: number;
33
+ /** Built-ins in this distribution, as `kind/type`. */
34
+ builtin: string[];
35
+ /** Built-ins this distribution does not ship, as `kind/type`. */
36
+ builtinMissing: string[];
37
+ /** Components with a schema chant does not build in, as `kind/type`; `defineComponent` reaches them. */
38
+ schemaNotBuiltin: string[];
39
+ /** Components without a schema chant does not build in, as `kind/type` (or the module when it has no type). */
40
+ noSchemaNotBuiltin: string[];
41
+ }
42
+
43
+ export interface OtelCoverageReport {
44
+ /** Built-ins whose config type is generated from upstream, as class names. */
45
+ generated: string[];
46
+ /** Built-ins with a hand-written config type, because upstream publishes no schema, as class names. */
47
+ handWritten: string[];
48
+ distributions: DistributionCoverage[];
49
+ /** The defects, for `check-lexicon`. */
50
+ unaccountedKinds: string[];
51
+ }
52
+
53
+ function label(c: { kind: ComponentKind; type?: string; module?: string }): string {
54
+ return `${c.kind}/${c.type ?? c.module}`;
55
+ }
56
+
57
+ function find(index: IndexedComponent[], kind: ComponentKind, type: string): IndexedComponent | undefined {
58
+ return index.find((c) => c.kind === kind && (c.type === type || c.deprecatedType === type));
59
+ }
60
+
61
+ /** The coverage report for a snapshot (the committed one by default). */
62
+ export function coverageReport(snapshot: OtelSpecSnapshot = loadSnapshot()): OtelCoverageReport {
63
+ const contrib = snapshot.distributions["otelcol-contrib"];
64
+ const generated: string[] = [];
65
+ const handWritten: string[] = [];
66
+ const unaccounted: string[] = [];
67
+ for (const b of BUILTIN_SPECS) {
68
+ const hit = find(contrib, b.kind, b.type);
69
+ if (!hit) {
70
+ unaccounted.push(`${b.className}: ${b.kind} "${b.type}" is not in otelcol-contrib ${snapshot.versions["otelcol-contrib"]}`);
71
+ continue;
72
+ }
73
+ if (hit.schema && snapshot.schemas[hit.schema] !== undefined) generated.push(b.className);
74
+ else if (hit.schema) unaccounted.push(`${b.className}: upstream ships ${hit.schema} but the snapshot does not carry it; run \`just snapshot\``);
75
+ else handWritten.push(b.className);
76
+ }
77
+
78
+ const distributions = DISTRIBUTIONS.map((distribution): DistributionCoverage => {
79
+ const index = snapshot.distributions[distribution];
80
+ const builtinHits = new Set<IndexedComponent>();
81
+ const builtin: string[] = [];
82
+ const builtinMissing: string[] = [];
83
+ for (const b of BUILTIN_SPECS) {
84
+ const hit = find(index, b.kind, b.type);
85
+ if (hit) {
86
+ builtinHits.add(hit);
87
+ builtin.push(`${b.kind}/${b.type}`);
88
+ } else builtinMissing.push(`${b.kind}/${b.type}`);
89
+ }
90
+ const others = index.filter((c) => !builtinHits.has(c));
91
+ return {
92
+ distribution,
93
+ version: snapshot.versions[distribution],
94
+ components: index.length,
95
+ withSchema: index.filter((c) => c.schema).length,
96
+ builtin,
97
+ builtinMissing,
98
+ schemaNotBuiltin: others.filter((c) => c.schema).map(label),
99
+ noSchemaNotBuiltin: others.filter((c) => !c.schema).map(label),
100
+ };
101
+ });
102
+
103
+ return { generated, handWritten, distributions, unaccountedKinds: unaccounted };
104
+ }
105
+
106
+ /** The report as `coverage()` prints it. */
107
+ export function formatCoverage(report: OtelCoverageReport): string {
108
+ const lines = [
109
+ `otel: ${report.generated.length + report.handWritten.length} built-in components, ${report.generated.length} with config types generated from upstream config.schema.yaml`,
110
+ ];
111
+ if (report.handWritten.length > 0) lines.push(` hand-written (no upstream schema): ${report.handWritten.join(", ")}`);
112
+ for (const d of report.distributions) {
113
+ lines.push(
114
+ `${d.distribution} ${d.version}: ${d.components} components, ${d.withSchema} with a schema; ` +
115
+ `${d.builtin.length} built in, ${d.schemaNotBuiltin.length + d.noSchemaNotBuiltin.length} through defineComponent`,
116
+ );
117
+ if (d.builtinMissing.length > 0) lines.push(` built-ins this distribution does not ship: ${d.builtinMissing.join(", ")}`);
118
+ }
119
+ for (const u of report.unaccountedKinds) lines.push(` unaccounted: ${u}`);
120
+ return lines.join("\n");
121
+ }
@@ -94,12 +94,14 @@ describe("defineComponent", () => {
94
94
 
95
95
  test("sending_queue.blocking is reported; the collector reads block_on_overflow", () => {
96
96
  const otlp = new OtlpReceiver({ protocols: { grpc: {} } });
97
+ // @ts-expect-error: `blocking` is not an upstream field, which is what the check reports
97
98
  const old = new OtlpExporter({ endpoint: "backend:4317", sending_queue: { blocking: true } });
98
99
  const r = build([otlp, old, new Pipeline({ signal: "traces", receivers: [otlp], exporters: [old] })]);
99
100
  expect(r.diags.filter((d) => d.checkId === "OTEL107").map((d) => d.message)).toEqual([
100
101
  'exporter "otlp": sending_queue.blocking is not a collector setting; use sending_queue.block_on_overflow',
101
102
  ]);
102
103
 
104
+ // @ts-expect-error: `blocking` is not an upstream field, which is what the check reports
103
105
  const both = new OtlpExporter({ endpoint: "backend:4317", sending_queue: { blocking: true, block_on_overflow: true } });
104
106
  const r2 = build([otlp, both, new Pipeline({ signal: "traces", receivers: [otlp], exporters: [both] })]);
105
107
  expect(r2.diags.filter((d) => d.checkId === "OTEL107")).toHaveLength(1);
package/src/define.ts CHANGED
@@ -12,9 +12,9 @@
12
12
  * ## Schema pinning
13
13
  *
14
14
  * Every definition carries a `pin`: the source its config type was written
15
- * against and the version of that source. Built-ins share `COLLECTOR_PIN`,
16
- * which moves only when this package does, so the chant lexicon version pins
17
- * them. A custom definition must name its own pin, typically the npm package
15
+ * against and the version of that source. Built-ins share `COLLECTOR_PIN`:
16
+ * their config types are generated from upstream `config.schema.yaml` at that
17
+ * release (`src/spec/`, #3361), so the chant lexicon version pins them. A custom definition must name its own pin, typically the npm package
18
18
  * (or Go module) that ships the component and the release its type follows,
19
19
  * optionally with a digest of the schema document. chant records the pin; it
20
20
  * does not fetch or verify the schema. The pin shows up in three places:
@@ -35,6 +35,7 @@
35
35
  import { createResource } from "@intentius/chant/runtime";
36
36
  import type { Declarable } from "@intentius/chant/declarable";
37
37
  import { canonicalComponentType, componentId, type ComponentKind, type ConnectorSignalPair } from "./model";
38
+ import { OTELCOL_CONTRIB_VERSION } from "./spec/pin";
38
39
 
39
40
  /** Where a component's config schema comes from, and which version of it the type follows. */
40
41
  export interface SchemaPin {
@@ -47,12 +48,15 @@ export interface SchemaPin {
47
48
  }
48
49
 
49
50
  /**
50
- * The collector distribution the built-in config types follow. Bumping it is a
51
- * lexicon change like any other, released with this package.
51
+ * The collector distribution the built-in config types follow: the
52
+ * `otelcol-contrib` release whose manifest scopes them and whose component
53
+ * schemas they are generated from (`OTELCOL_CONTRIB_VERSION` in
54
+ * `src/spec/pin.ts`). Bumping it is a lexicon change like any other, released
55
+ * with this package, and it moves `COLLECTOR_IMAGE` with it.
52
56
  */
53
57
  export const COLLECTOR_PIN: SchemaPin = Object.freeze({
54
58
  source: "github.com/open-telemetry/opentelemetry-collector-contrib",
55
- version: "v0.130.0",
59
+ version: OTELCOL_CONTRIB_VERSION,
56
60
  });
57
61
 
58
62
  /**