@intentius/chant-lexicon-otel 0.95.1 → 0.96.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.
- package/README.md +30 -9
- package/dist/catalog.d.ts +2 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/collector.d.ts +4 -1
- package/dist/collector.d.ts.map +1 -1
- package/dist/components/connectors.d.ts +156 -0
- package/dist/components/connectors.d.ts.map +1 -0
- package/dist/components/filtering.d.ts +95 -0
- package/dist/components/filtering.d.ts.map +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/k8s-receivers.d.ts +74 -0
- package/dist/components/k8s-receivers.d.ts.map +1 -0
- package/dist/components/sampling.d.ts +260 -0
- package/dist/components/sampling.d.ts.map +1 -0
- package/dist/define.d.ts +31 -4
- package/dist/define.d.ts.map +1 -1
- package/dist/genai.d.ts +165 -0
- package/dist/genai.d.ts.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +8 -7
- package/dist/lint/audit-catalog.d.ts +2 -1
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/otel-helpers.d.ts +1 -1
- package/dist/lint/post-synth/otel-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/otel101.d.ts +1 -1
- package/dist/lint/post-synth/otel103.d.ts +1 -1
- package/dist/lint/post-synth/otel112.d.ts +8 -0
- package/dist/lint/post-synth/otel112.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/meta.json +70 -0
- package/dist/metric-names.d.ts +121 -0
- package/dist/metric-names.d.ts.map +1 -0
- package/dist/model.d.ts +23 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/okf/index.md +15 -0
- package/dist/okf/rules/OTEL112.md +11 -0
- package/dist/okf/types/CountConnector.md +9 -0
- package/dist/okf/types/FilterProcessor.md +9 -0
- package/dist/okf/types/ForwardConnector.md +9 -0
- package/dist/okf/types/K8sClusterReceiver.md +9 -0
- package/dist/okf/types/KubeletStatsReceiver.md +9 -0
- package/dist/okf/types/LoadBalancingExporter.md +9 -0
- package/dist/okf/types/ProbabilisticSamplerProcessor.md +9 -0
- package/dist/okf/types/RedactionProcessor.md +9 -0
- package/dist/okf/types/RoutingConnector.md +9 -0
- package/dist/okf/types/ServiceGraphConnector.md +9 -0
- package/dist/okf/types/SpanMetricsConnector.md +9 -0
- package/dist/okf/types/SumConnector.md +9 -0
- package/dist/okf/types/TailSamplingProcessor.md +9 -0
- package/dist/okf/types/TransformProcessor.md +9 -0
- package/dist/pipeline.d.ts +9 -3
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/rules/otel-helpers.ts +1 -1
- package/dist/rules/otel101.ts +1 -1
- package/dist/rules/otel103.ts +1 -1
- package/dist/rules/otel112.ts +17 -0
- package/dist/semconv.d.ts +33 -0
- package/dist/semconv.d.ts.map +1 -0
- package/dist/serializer.d.ts +1 -1
- package/dist/skills/chant-otel.md +28 -5
- package/dist/topology.d.ts +34 -5
- package/dist/topology.d.ts.map +1 -1
- package/dist/validate-config.d.ts +6 -2
- package/dist/validate-config.d.ts.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/catalog.ts +2 -1
- package/src/codegen/docs.ts +14 -8
- package/src/collector.ts +9 -1
- package/src/components/connectors.ts +276 -0
- package/src/components/filtering.test.ts +192 -0
- package/src/components/filtering.ts +192 -0
- package/src/components/index.ts +4 -0
- package/src/components/k8s-receivers.test.ts +123 -0
- package/src/components/k8s-receivers.ts +107 -0
- package/src/components/sampling.test.ts +464 -0
- package/src/components/sampling.ts +521 -0
- package/src/connectors.test.ts +388 -0
- package/src/define.ts +36 -4
- package/src/genai.test.ts +526 -0
- package/src/genai.ts +466 -0
- package/src/generated/lexicon-otel.json +70 -0
- package/src/index.ts +39 -0
- package/src/lint/audit-catalog.ts +11 -2
- package/src/lint/post-synth/index.ts +2 -0
- package/src/lint/post-synth/otel-helpers.ts +1 -1
- package/src/lint/post-synth/otel101.ts +1 -1
- package/src/lint/post-synth/otel103.ts +1 -1
- package/src/lint/post-synth/otel112.ts +17 -0
- package/src/metric-names.test.ts +80 -0
- package/src/metric-names.ts +176 -0
- package/src/model.ts +26 -4
- package/src/otelcol-validate.test.ts +143 -0
- package/src/pipeline.ts +9 -3
- package/src/plugin.test.ts +1 -0
- package/src/plugin.ts +1 -1
- package/src/semconv.ts +63 -0
- package/src/serializer.ts +1 -1
- package/src/skills/chant-otel.md +28 -5
- package/src/topology.ts +54 -8
- package/src/validate-config.ts +92 -4
- package/src/validate.ts +8 -0
package/src/skills/chant-otel.md
CHANGED
|
@@ -6,7 +6,7 @@ user-invocable: true
|
|
|
6
6
|
|
|
7
7
|
# OpenTelemetry Collector config with chant
|
|
8
8
|
|
|
9
|
-
The otel lexicon (`@intentius/chant-lexicon-otel`) types collector config. Each receiver, processor, exporter and extension is an entity, pipelines reference them, and `chant build` writes one collector config file.
|
|
9
|
+
The otel lexicon (`@intentius/chant-lexicon-otel`) types collector config. Each receiver, processor, exporter, connector and extension is an entity, pipelines reference them, and `chant build` writes one collector config file.
|
|
10
10
|
|
|
11
11
|
## Project setup
|
|
12
12
|
|
|
@@ -40,13 +40,36 @@ Emits `receivers.otlp`, `processors.memory_limiter` and `processors.batch`, `exp
|
|
|
40
40
|
|
|
41
41
|
| Kind | Types |
|
|
42
42
|
|---|---|
|
|
43
|
-
| receivers | otlp, prometheus, hostmetrics, filelog |
|
|
44
|
-
| processors | batch, memory_limiter, resource, attributes, k8sattributes, resourcedetection |
|
|
45
|
-
| exporters | otlp, otlphttp, debug, prometheus, googlecloud |
|
|
43
|
+
| receivers | otlp, prometheus, hostmetrics, filelog, k8s_cluster, kubeletstats |
|
|
44
|
+
| processors | batch, memory_limiter, resource, attributes, k8sattributes, resourcedetection, filter, transform, redaction, tail_sampling, probabilistic_sampler |
|
|
45
|
+
| exporters | otlp, otlphttp, debug, prometheus, googlecloud, loadbalancing |
|
|
46
|
+
| connectors | spanmetrics, servicegraph, routing, forward, count, sum |
|
|
46
47
|
| extensions | health_check, pprof, zpages |
|
|
47
48
|
|
|
48
49
|
Anything else goes through `defineComponent`; see the `chant-otel-custom-components` skill.
|
|
49
50
|
|
|
51
|
+
## Connectors
|
|
52
|
+
|
|
53
|
+
A connector joins two pipelines. List the same entity in `exporters` of the pipeline that feeds it and in `receivers` of the pipeline it feeds:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
export const spanmetrics = new SpanMetricsConnector({ dimensions: [{ name: "http.route" }] });
|
|
57
|
+
export const traces = new Pipeline({ signal: "traces", receivers: [otlp], exporters: [backend, spanmetrics] });
|
|
58
|
+
export const red = new Pipeline({ signal: "metrics", name: "red", receivers: [spanmetrics], exporters: [prom] });
|
|
59
|
+
```
|
|
60
|
+
|
|
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.
|
|
62
|
+
|
|
63
|
+
## GenAI workloads
|
|
64
|
+
|
|
65
|
+
For services that emit GenAI spans, start from the preset instead of writing the processors by hand:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
export const collector = genAiPipeline({ traceExporters: [tempo], metricExporters: [prom] });
|
|
69
|
+
```
|
|
70
|
+
|
|
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.
|
|
72
|
+
|
|
50
73
|
## Rules
|
|
51
74
|
|
|
52
75
|
- Reference components by entity where you can. A string id (`"otlp/backend"`) is allowed for a component declared elsewhere, and OTEL101 fails the build if nothing declares it.
|
|
@@ -57,4 +80,4 @@ Anything else goes through `defineComponent`; see the `chant-otel-custom-compone
|
|
|
57
80
|
|
|
58
81
|
## Reading the result
|
|
59
82
|
|
|
60
|
-
`collectorTopologyOf(entities)` returns the pipelines, each component's endpoints and schema pin,
|
|
83
|
+
`collectorTopologyOf(entities)` returns the pipelines, each component's endpoints and schema pin, for each exporter the signals it carries, the connector `edges` between pipelines, and under `semconv` the semantic-conventions version (`GENAI_SEMCONV_PIN`) the config's `gen_ai.` keys follow, as plain data.
|
package/src/topology.ts
CHANGED
|
@@ -3,16 +3,21 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `collectorTopology()` reads a collector config (declared, or parsed from a
|
|
5
5
|
* YAML file) and returns its pipelines, its components with their endpoints
|
|
6
|
-
* and schema pins,
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* and schema pins, for each exporter the pipelines and signals it carries,
|
|
7
|
+
* the edges connectors make from one pipeline to another, and the
|
|
8
|
+
* semantic-convention versions its attribute keys follow. It is the
|
|
9
|
+
* surface a reader such as `chant workspace graph` uses to say where a
|
|
10
|
+
* member's telemetry is sent, and what a declared telemetry endpoint link can
|
|
11
|
+
* point at.
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
import type { Declarable } from "@intentius/chant/declarable";
|
|
13
15
|
import { buildCollectorConfig } from "./collector";
|
|
14
16
|
import { definitionOf, type SchemaPin } from "./define";
|
|
15
17
|
import { parseComponentId, pipelineSignal, SECTION_OF, type CollectorConfig, type ComponentKind } from "./model";
|
|
18
|
+
import { semconvUsage, type SemconvUsage } from "./semconv";
|
|
19
|
+
|
|
20
|
+
export type { SemconvUsage } from "./semconv";
|
|
16
21
|
|
|
17
22
|
export interface TopologyPipeline {
|
|
18
23
|
/** The id under `service.pipelines`, e.g. `traces` or `traces/backend`. */
|
|
@@ -36,10 +41,24 @@ export interface TopologyComponent {
|
|
|
36
41
|
schema?: SchemaPin;
|
|
37
42
|
/** Addresses it listens on or sends to, as the config states them. Empty when the config names none. */
|
|
38
43
|
endpoints: string[];
|
|
39
|
-
/** The pipelines that use it. For an extension, empty. */
|
|
44
|
+
/** The pipelines that use it. For a connector, those on either side; for an extension, empty. */
|
|
40
45
|
pipelines: string[];
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
/** One hop from a pipeline to another through a connector. */
|
|
49
|
+
export interface TopologyEdge {
|
|
50
|
+
/** The connector's id. */
|
|
51
|
+
connector: string;
|
|
52
|
+
/** The pipeline that lists the connector as an exporter. */
|
|
53
|
+
from: string;
|
|
54
|
+
/** That pipeline's signal. */
|
|
55
|
+
fromSignal: string;
|
|
56
|
+
/** The pipeline that lists the connector as a receiver. */
|
|
57
|
+
to: string;
|
|
58
|
+
/** That pipeline's signal. */
|
|
59
|
+
toSignal: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
43
62
|
export interface TopologyExporter {
|
|
44
63
|
id: string;
|
|
45
64
|
type: string;
|
|
@@ -54,6 +73,18 @@ export interface CollectorTopology {
|
|
|
54
73
|
components: TopologyComponent[];
|
|
55
74
|
/** The exporters again, grouped for the question "where does this telemetry go". */
|
|
56
75
|
exporters: TopologyExporter[];
|
|
76
|
+
/**
|
|
77
|
+
* Pipeline-to-pipeline edges through connectors, one per (from, to) pair the
|
|
78
|
+
* connector supports. For a connector whose definition this process lacks,
|
|
79
|
+
* every pair.
|
|
80
|
+
*/
|
|
81
|
+
edges: TopologyEdge[];
|
|
82
|
+
/**
|
|
83
|
+
* The semantic-convention vocabularies the config's attribute keys come
|
|
84
|
+
* from, each with the pin this package follows for it (`GENAI_SEMCONV_PIN`
|
|
85
|
+
* for `gen_ai`) and the components that use it. Empty when none is used.
|
|
86
|
+
*/
|
|
87
|
+
semconv: SemconvUsage[];
|
|
57
88
|
}
|
|
58
89
|
|
|
59
90
|
function endpointsOf(kind: ComponentKind, type: string, config: Record<string, unknown> | null | undefined): string[] {
|
|
@@ -86,9 +117,12 @@ export function collectorTopology(config: CollectorConfig): CollectorTopology {
|
|
|
86
117
|
const parsed = parseComponentId(id);
|
|
87
118
|
const type = parsed?.type ?? id;
|
|
88
119
|
const def = definitionOf(kind, type);
|
|
89
|
-
const field = section as "receivers" | "processors" | "exporters" | "extensions";
|
|
90
120
|
const inPipelines =
|
|
91
|
-
|
|
121
|
+
section === "extensions"
|
|
122
|
+
? []
|
|
123
|
+
: section === "connectors"
|
|
124
|
+
? pipelines.filter((p) => p.receivers.includes(id) || p.exporters.includes(id)).map((p) => p.id)
|
|
125
|
+
: pipelines.filter((p) => p[section].includes(id)).map((p) => p.id);
|
|
92
126
|
components.push({
|
|
93
127
|
id,
|
|
94
128
|
kind,
|
|
@@ -113,7 +147,19 @@ export function collectorTopology(config: CollectorConfig): CollectorTopology {
|
|
|
113
147
|
return { id: c.id, type: c.type, endpoints: c.endpoints, pipelines: c.pipelines, signals };
|
|
114
148
|
});
|
|
115
149
|
|
|
116
|
-
|
|
150
|
+
const edges: TopologyEdge[] = [];
|
|
151
|
+
for (const c of components) {
|
|
152
|
+
if (c.kind !== "connector") continue;
|
|
153
|
+
const pairs = definitionOf("connector", c.type)?.connects;
|
|
154
|
+
for (const from of pipelines.filter((p) => p.exporters.includes(c.id))) {
|
|
155
|
+
for (const to of pipelines.filter((p) => p.receivers.includes(c.id))) {
|
|
156
|
+
if (pairs && pairs.length > 0 && !pairs.some((pair) => pair.from === from.signal && pair.to === to.signal)) continue;
|
|
157
|
+
edges.push({ connector: c.id, from: from.id, fromSignal: from.signal, to: to.id, toSignal: to.signal });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return { pipelines, components, exporters, edges, semconv: semconvUsage(config) };
|
|
117
163
|
}
|
|
118
164
|
|
|
119
165
|
/** The topology of declared entities, i.e. of the config the serializer would emit for them. */
|
package/src/validate-config.ts
CHANGED
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { Declarable } from "@intentius/chant/declarable";
|
|
12
|
-
import { definitionFor, isOTelComponent, isUsablePin, runValidator } from "./define";
|
|
12
|
+
import { definitionFor, definitionOf, isOTelComponent, isUsablePin, runValidator } from "./define";
|
|
13
13
|
import { componentConfig } from "./collector";
|
|
14
|
-
import { isComponentId, pipelineSignal, SIGNALS, type CollectorConfig } from "./model";
|
|
14
|
+
import { isComponentId, parseComponentId, pipelineSignal, SIGNALS, type CollectorConfig, type ConnectorSignalPair } from "./model";
|
|
15
15
|
import { isPipelineEntity } from "./pipeline";
|
|
16
|
+
// OTEL112 reads the built-in connectors' signal pairs from the registry.
|
|
17
|
+
import "./components/connectors";
|
|
16
18
|
|
|
17
19
|
export type CollectorIssueCode =
|
|
18
20
|
| "OTEL101"
|
|
@@ -23,7 +25,8 @@ export type CollectorIssueCode =
|
|
|
23
25
|
| "OTEL106"
|
|
24
26
|
| "OTEL107"
|
|
25
27
|
| "OTEL108"
|
|
26
|
-
| "OTEL109"
|
|
28
|
+
| "OTEL109"
|
|
29
|
+
| "OTEL112";
|
|
27
30
|
|
|
28
31
|
export interface CollectorIssue {
|
|
29
32
|
code: CollectorIssueCode;
|
|
@@ -41,7 +44,20 @@ function ids(section: Record<string, unknown> | undefined): Set<string> {
|
|
|
41
44
|
return new Set(Object.keys(section ?? {}));
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
/**
|
|
47
|
+
/** Where a connector appears: the pipelines it is an exporter in, and those it is a receiver in. */
|
|
48
|
+
interface ConnectorUse {
|
|
49
|
+
asExporter: string[];
|
|
50
|
+
asReceiver: string[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function describePairs(pairs: ReadonlyArray<ConnectorSignalPair>): string {
|
|
54
|
+
return pairs.map((p) => `${p.from} to ${p.to}`).join(", ");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check a collector config's references and pipeline shape (OTEL101-OTEL106),
|
|
59
|
+
* and each connector's signals against its definition (OTEL112).
|
|
60
|
+
*/
|
|
45
61
|
export function validateCollectorConfig(config: CollectorConfig): CollectorIssue[] {
|
|
46
62
|
const issues: CollectorIssue[] = [];
|
|
47
63
|
const receivers = ids(config.receivers);
|
|
@@ -52,6 +68,7 @@ export function validateCollectorConfig(config: CollectorConfig): CollectorIssue
|
|
|
52
68
|
const pipelines = config.service?.pipelines ?? {};
|
|
53
69
|
|
|
54
70
|
const used = { receivers: new Set<string>(), processors: new Set<string>(), exporters: new Set<string>() };
|
|
71
|
+
const connectorUse = new Map<string, ConnectorUse>();
|
|
55
72
|
|
|
56
73
|
for (const [pipelineId, pipeline] of Object.entries(pipelines)) {
|
|
57
74
|
const signal = pipelineSignal(pipelineId);
|
|
@@ -84,6 +101,11 @@ export function validateCollectorConfig(config: CollectorConfig): CollectorIssue
|
|
|
84
101
|
continue;
|
|
85
102
|
}
|
|
86
103
|
const viaConnector = field !== "processors" && connectors.has(id);
|
|
104
|
+
if (viaConnector) {
|
|
105
|
+
const use = connectorUse.get(id) ?? { asExporter: [], asReceiver: [] };
|
|
106
|
+
(field === "exporters" ? use.asExporter : use.asReceiver).push(pipelineId);
|
|
107
|
+
connectorUse.set(id, use);
|
|
108
|
+
}
|
|
87
109
|
if (!declared.has(id) && !viaConnector) {
|
|
88
110
|
issues.push({
|
|
89
111
|
code: "OTEL101",
|
|
@@ -124,10 +146,35 @@ export function validateCollectorConfig(config: CollectorConfig): CollectorIssue
|
|
|
124
146
|
}
|
|
125
147
|
}
|
|
126
148
|
|
|
149
|
+
// A connector joins two pipelines, so the collector refuses one that is
|
|
150
|
+
// listed on only one side.
|
|
151
|
+
for (const [id, use] of connectorUse) {
|
|
152
|
+
if (use.asReceiver.length === 0) {
|
|
153
|
+
issues.push({
|
|
154
|
+
code: "OTEL101",
|
|
155
|
+
severity: "error",
|
|
156
|
+
pipeline: use.asExporter[0],
|
|
157
|
+
component: id,
|
|
158
|
+
message: `connector "${id}" is an exporter in pipeline "${use.asExporter[0]}" but no pipeline lists it as a receiver; a connector must appear on both sides, and the collector refuses to start`,
|
|
159
|
+
});
|
|
160
|
+
} else if (use.asExporter.length === 0) {
|
|
161
|
+
issues.push({
|
|
162
|
+
code: "OTEL101",
|
|
163
|
+
severity: "error",
|
|
164
|
+
pipeline: use.asReceiver[0],
|
|
165
|
+
component: id,
|
|
166
|
+
message: `connector "${id}" is a receiver in pipeline "${use.asReceiver[0]}" but no pipeline lists it as an exporter; a connector must appear on both sides, and the collector refuses to start`,
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
issues.push(...connectorSignalIssues(id, use));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
127
173
|
const unused: Array<[Set<string>, Set<string>, string]> = [
|
|
128
174
|
[receivers, used.receivers, "receiver"],
|
|
129
175
|
[processors, used.processors, "processor"],
|
|
130
176
|
[exporters, used.exporters, "exporter"],
|
|
177
|
+
[connectors, new Set(connectorUse.keys()), "connector"],
|
|
131
178
|
];
|
|
132
179
|
for (const [declared, usedIds, noun] of unused) {
|
|
133
180
|
for (const id of declared) {
|
|
@@ -167,6 +214,47 @@ export function validateCollectorConfig(config: CollectorConfig): CollectorIssue
|
|
|
167
214
|
return issues;
|
|
168
215
|
}
|
|
169
216
|
|
|
217
|
+
/**
|
|
218
|
+
* OTEL112: every pipeline a connector joins must pair with a pipeline on the
|
|
219
|
+
* other side through a signal pair the connector supports. This is the
|
|
220
|
+
* collector's own rule: `spanmetrics` fed by a traces pipeline needs a metrics
|
|
221
|
+
* pipeline to receive from it, and cannot be the receiver of a traces
|
|
222
|
+
* pipeline. A connector whose definition this process doesn't have, or whose
|
|
223
|
+
* definition lists no pairs, is not checked.
|
|
224
|
+
*/
|
|
225
|
+
function connectorSignalIssues(id: string, use: ConnectorUse): CollectorIssue[] {
|
|
226
|
+
const type = parseComponentId(id)?.type ?? id;
|
|
227
|
+
const pairs = definitionOf("connector", type)?.connects;
|
|
228
|
+
if (!pairs || pairs.length === 0) return [];
|
|
229
|
+
const supported = (from: string, to: string) => pairs.some((p) => p.from === from && p.to === to);
|
|
230
|
+
const inSignals = use.asExporter.map(pipelineSignal);
|
|
231
|
+
const outSignals = use.asReceiver.map(pipelineSignal);
|
|
232
|
+
const issues: CollectorIssue[] = [];
|
|
233
|
+
for (const pipeline of use.asExporter) {
|
|
234
|
+
const from = pipelineSignal(pipeline);
|
|
235
|
+
if (outSignals.some((to) => supported(from, to))) continue;
|
|
236
|
+
issues.push({
|
|
237
|
+
code: "OTEL112",
|
|
238
|
+
severity: "error",
|
|
239
|
+
pipeline,
|
|
240
|
+
component: id,
|
|
241
|
+
message: `connector "${id}" is an exporter in ${from} pipeline "${pipeline}", but no pipeline it feeds carries a signal ${type} makes from ${from} (it supports ${describePairs(pairs)}); the collector refuses to start`,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
for (const pipeline of use.asReceiver) {
|
|
245
|
+
const to = pipelineSignal(pipeline);
|
|
246
|
+
if (inSignals.some((from) => supported(from, to))) continue;
|
|
247
|
+
issues.push({
|
|
248
|
+
code: "OTEL112",
|
|
249
|
+
severity: "error",
|
|
250
|
+
pipeline,
|
|
251
|
+
component: id,
|
|
252
|
+
message: `connector "${id}" is a receiver in ${to} pipeline "${pipeline}", but no pipeline feeding it carries a signal ${type} turns into ${to} (it supports ${describePairs(pairs)}); the collector refuses to start`,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return issues;
|
|
256
|
+
}
|
|
257
|
+
|
|
170
258
|
/**
|
|
171
259
|
* Check declared entities for what only the declaration knows (OTEL107-OTEL109):
|
|
172
260
|
* each component's own config rules, duplicate ids, and custom components'
|
package/src/validate.ts
CHANGED
|
@@ -18,17 +18,25 @@ export const REQUIRED_NAMES = [
|
|
|
18
18
|
"PrometheusReceiver",
|
|
19
19
|
"HostMetricsReceiver",
|
|
20
20
|
"FileLogReceiver",
|
|
21
|
+
"K8sClusterReceiver",
|
|
22
|
+
"KubeletStatsReceiver",
|
|
21
23
|
"BatchProcessor",
|
|
22
24
|
"MemoryLimiterProcessor",
|
|
23
25
|
"ResourceProcessor",
|
|
24
26
|
"AttributesProcessor",
|
|
25
27
|
"K8sAttributesProcessor",
|
|
26
28
|
"ResourceDetectionProcessor",
|
|
29
|
+
"FilterProcessor",
|
|
30
|
+
"TransformProcessor",
|
|
31
|
+
"RedactionProcessor",
|
|
32
|
+
"TailSamplingProcessor",
|
|
33
|
+
"ProbabilisticSamplerProcessor",
|
|
27
34
|
"OtlpExporter",
|
|
28
35
|
"OtlpHttpExporter",
|
|
29
36
|
"DebugExporter",
|
|
30
37
|
"PrometheusExporter",
|
|
31
38
|
"GoogleCloudExporter",
|
|
39
|
+
"LoadBalancingExporter",
|
|
32
40
|
"HealthCheckExtension",
|
|
33
41
|
"PprofExtension",
|
|
34
42
|
"ZPagesExtension",
|