@intentius/chant-lexicon-otel 0.124.46 → 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.
- package/README.md +2 -2
- package/dist/build/capability-plugin.d.ts +10 -0
- package/dist/build/capability-plugin.d.ts.map +1 -0
- package/dist/build/capability-plugin.js +19 -0
- package/dist/build/ocb-build.d.ts +38 -0
- package/dist/build/ocb-build.d.ts.map +1 -0
- package/dist/build/ocb-build.js +49 -0
- package/dist/clickhouse-tables.d.ts +73 -0
- package/dist/clickhouse-tables.d.ts.map +1 -0
- package/dist/clickhouse-tables.js +199 -0
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/docs.js +4 -2
- package/dist/codegen/generate.d.ts +29 -10
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/generate.js +82 -17
- package/dist/components/common.d.ts +3 -1
- package/dist/components/common.d.ts.map +1 -1
- package/dist/components/common.js +2 -0
- package/dist/components/connectors.d.ts +25 -90
- package/dist/components/connectors.d.ts.map +1 -1
- package/dist/components/connectors.js +3 -0
- package/dist/components/exporters.d.ts +78 -34
- package/dist/components/exporters.d.ts.map +1 -1
- package/dist/components/exporters.js +26 -1
- package/dist/components/extensions.d.ts +16 -33
- package/dist/components/extensions.d.ts.map +1 -1
- package/dist/components/filtering.d.ts +13 -60
- package/dist/components/filtering.d.ts.map +1 -1
- package/dist/components/k8s-receivers.d.ts +5 -53
- package/dist/components/k8s-receivers.d.ts.map +1 -1
- package/dist/components/overlay.d.ts +25 -0
- package/dist/components/overlay.d.ts.map +1 -0
- package/dist/components/overlay.js +19 -0
- package/dist/components/processors.d.ts +18 -79
- package/dist/components/processors.d.ts.map +1 -1
- package/dist/components/receivers.d.ts +17 -71
- package/dist/components/receivers.d.ts.map +1 -1
- package/dist/components/receivers.js +3 -1
- package/dist/components/sampling.d.ts +19 -35
- package/dist/components/sampling.d.ts.map +1 -1
- package/dist/config-hygiene.d.ts +10 -8
- package/dist/config-hygiene.d.ts.map +1 -1
- package/dist/config-hygiene.js +36 -13
- package/dist/coverage.d.ts +50 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +92 -0
- package/dist/define.d.ts +8 -5
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +10 -6
- package/dist/distribution.d.ts +125 -0
- package/dist/distribution.d.ts.map +1 -0
- package/dist/distribution.js +227 -0
- package/dist/generated/index.d.ts +4234 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +23 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/init-templates.js +2 -2
- package/dist/integrity.json +11 -9
- package/dist/lint/audit-catalog.d.ts +3 -0
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/audit-catalog.js +5 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/index.js +4 -0
- package/dist/lint/post-synth/otel-helpers.d.ts +2 -1
- package/dist/lint/post-synth/otel-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/otel-helpers.js +1 -1
- package/dist/lint/post-synth/otel119.d.ts +1 -1
- package/dist/lint/post-synth/otel119.js +1 -1
- package/dist/lint/post-synth/otel125.d.ts +1 -1
- package/dist/lint/post-synth/otel125.js +1 -1
- package/dist/lint/post-synth/otel126.d.ts +1 -1
- package/dist/lint/post-synth/otel126.js +1 -1
- package/dist/lint/post-synth/otel127.d.ts +1 -1
- package/dist/lint/post-synth/otel127.js +1 -1
- package/dist/lint/post-synth/otel128.d.ts +8 -0
- package/dist/lint/post-synth/otel128.d.ts.map +1 -0
- package/dist/lint/post-synth/otel128.js +17 -0
- package/dist/lint/post-synth/otel129.d.ts +15 -0
- package/dist/lint/post-synth/otel129.d.ts.map +1 -0
- package/dist/lint/post-synth/otel129.js +92 -0
- package/dist/lsp/completions.d.ts +10 -1
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +29 -1
- package/dist/lsp/hover.d.ts +5 -1
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +16 -3
- package/dist/lsp/properties.d.ts +34 -0
- package/dist/lsp/properties.d.ts.map +1 -0
- package/dist/lsp/properties.js +135 -0
- package/dist/manifest.json +1 -1
- package/dist/meta.json +5 -0
- package/dist/metric-names.d.ts +36 -8
- package/dist/metric-names.d.ts.map +1 -1
- package/dist/metric-names.js +42 -9
- package/dist/model.d.ts +1 -1
- package/dist/model.js +1 -1
- package/dist/okf/index.md +3 -0
- package/dist/okf/rules/OTEL128.md +11 -0
- package/dist/okf/rules/OTEL129.md +11 -0
- package/dist/okf/types/ClickHouseExporter.md +9 -0
- package/dist/op/activities/collector-audit.d.ts +18 -6
- package/dist/op/activities/collector-audit.d.ts.map +1 -1
- package/dist/op/activities/collector-audit.js +37 -21
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +51 -8
- package/dist/rules/otel-helpers.ts +1 -1
- package/dist/rules/otel119.ts +1 -1
- package/dist/rules/otel125.ts +1 -1
- package/dist/rules/otel126.ts +1 -1
- package/dist/rules/otel127.ts +1 -1
- package/dist/rules/otel128.ts +22 -0
- package/dist/rules/otel129.ts +99 -0
- package/dist/serializer.d.ts +3 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +12 -2
- package/dist/spec/builtins.d.ts +17 -0
- package/dist/spec/builtins.d.ts.map +1 -0
- package/dist/spec/builtins.js +45 -0
- package/dist/spec/fetch.d.ts +120 -0
- package/dist/spec/fetch.d.ts.map +1 -0
- package/dist/spec/fetch.js +282 -0
- package/dist/spec/parse.d.ts +77 -0
- package/dist/spec/parse.d.ts.map +1 -0
- package/dist/spec/parse.js +337 -0
- package/dist/spec/pin.d.ts +82 -0
- package/dist/spec/pin.d.ts.map +1 -0
- package/dist/spec/pin.js +126 -0
- package/dist/spec/snapshot-cli.d.ts +13 -0
- package/dist/spec/snapshot-cli.d.ts.map +1 -0
- package/dist/spec/snapshot-cli.js +31 -0
- package/dist/spec/snapshot.d.ts +9 -0
- package/dist/spec/snapshot.d.ts.map +1 -0
- package/dist/spec/snapshot.js +14 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/validate-config.d.ts +1 -1
- package/dist/validate-config.d.ts.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +1 -0
- package/dist/workspace-links.d.ts +25 -0
- package/dist/workspace-links.d.ts.map +1 -0
- package/dist/workspace-links.js +49 -0
- package/package.json +3 -2
- package/src/build/capability-plugin.ts +30 -0
- package/src/build/ocb-build.ts +73 -0
- package/src/clickhouse-exporter.e2e.test.ts +208 -0
- package/src/clickhouse-tables.test.ts +216 -0
- package/src/clickhouse-tables.ts +223 -0
- package/src/codegen/docs.ts +4 -2
- package/src/codegen/generate.ts +95 -19
- package/src/components/common.ts +4 -2
- package/src/components/connectors.ts +30 -77
- package/src/components/exporters.ts +128 -61
- package/src/components/extensions.ts +22 -36
- package/src/components/filtering.ts +17 -58
- package/src/components/k8s-receivers.test.ts +1 -1
- package/src/components/k8s-receivers.ts +3 -45
- package/src/components/overlay.ts +24 -0
- package/src/components/processors.ts +18 -63
- package/src/components/receivers.ts +20 -60
- package/src/components/sampling.ts +24 -37
- package/src/config-hygiene.ts +36 -13
- package/src/coverage.test.ts +37 -0
- package/src/coverage.ts +121 -0
- package/src/define.test.ts +2 -0
- package/src/define.ts +10 -6
- package/src/distribution.test.ts +250 -0
- package/src/distribution.ts +305 -0
- package/src/generated/index.ts +4576 -0
- package/src/generated/lexicon-otel.json +5 -0
- package/src/generated/properties.json +1 -0
- package/src/import/roundtrip.test.ts +16 -0
- package/src/import/testdata/clickhouse.yaml +37 -0
- package/src/import/testdata/fixtures.ts +17 -2
- package/src/import/testdata/upstream/clickhouse-exporter.yaml +60 -0
- package/src/index.ts +69 -0
- package/src/init-templates.ts +2 -2
- package/src/lint/audit-catalog.ts +15 -0
- package/src/lint/post-synth/index.ts +4 -0
- package/src/lint/post-synth/otel-helpers.ts +1 -1
- package/src/lint/post-synth/otel119.ts +1 -1
- package/src/lint/post-synth/otel125.ts +1 -1
- package/src/lint/post-synth/otel126.ts +1 -1
- package/src/lint/post-synth/otel127.ts +1 -1
- package/src/lint/post-synth/otel128.ts +22 -0
- package/src/lint/post-synth/otel129.ts +99 -0
- package/src/lsp/completions.ts +30 -1
- package/src/lsp/hover.ts +14 -3
- package/src/lsp/properties.test.ts +72 -0
- package/src/lsp/properties.ts +141 -0
- package/src/metric-names.test.ts +11 -0
- package/src/metric-names.ts +64 -16
- package/src/model.ts +1 -1
- package/src/op/activities/collector-audit.test.ts +29 -22
- package/src/op/activities/collector-audit.ts +38 -18
- package/src/plugin.test.ts +2 -0
- package/src/plugin.ts +57 -6
- package/src/serializer.ts +11 -2
- package/src/spec/builtins.ts +56 -0
- package/src/spec/fetch.ts +332 -0
- package/src/spec/otel-schemas.snapshot.json +13932 -0
- package/src/spec/parse.ts +364 -0
- package/src/spec/pin.ts +155 -0
- package/src/spec/snapshot-cli.ts +32 -0
- package/src/spec/snapshot.ts +19 -0
- package/src/spec/spec.test.ts +144 -0
- package/src/validate-config.ts +4 -3
- package/src/validate.ts +1 -0
- package/src/workspace-links.e2e.test.ts +91 -0
- package/src/workspace-links.ts +50 -0
|
@@ -3,22 +3,13 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { defineBuiltin } from "../define";
|
|
6
|
-
import type {
|
|
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
|
|
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
|
-
|
|
158
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
236
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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
|
|
package/src/config-hygiene.ts
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
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.
|
|
319
|
-
* `NewDefaultQueueConfig
|
|
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.
|
|
357
|
-
* `Config.Validate` (`processor/k8sattributesprocessor/config.go`),
|
|
358
|
-
* the semconv
|
|
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.
|
|
394
|
-
* in `NewFactory`
|
|
395
|
-
* each detector's
|
|
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
|
+
});
|
package/src/coverage.ts
ADDED
|
@@ -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
|
+
}
|
package/src/define.test.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
51
|
-
*
|
|
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:
|
|
59
|
+
version: OTELCOL_CONTRIB_VERSION,
|
|
56
60
|
});
|
|
57
61
|
|
|
58
62
|
/**
|