@intentius/chant-lexicon-otel 0.81.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 +49 -0
- package/dist/catalog.d.ts +18 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/codegen/docs-cli.d.ts +3 -0
- package/dist/codegen/docs-cli.d.ts.map +1 -0
- package/dist/codegen/docs.d.ts +8 -0
- package/dist/codegen/docs.d.ts.map +1 -0
- package/dist/codegen/generate-cli.d.ts +3 -0
- package/dist/codegen/generate-cli.d.ts.map +1 -0
- package/dist/codegen/generate.d.ts +19 -0
- package/dist/codegen/generate.d.ts.map +1 -0
- package/dist/codegen/package.d.ts +7 -0
- package/dist/codegen/package.d.ts.map +1 -0
- package/dist/collector.d.ts +29 -0
- package/dist/collector.d.ts.map +1 -0
- package/dist/components/common.d.ts +144 -0
- package/dist/components/common.d.ts.map +1 -0
- package/dist/components/exporters.d.ts +86 -0
- package/dist/components/exporters.d.ts.map +1 -0
- package/dist/components/extensions.d.ts +32 -0
- package/dist/components/extensions.d.ts.map +1 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/processors.d.ts +118 -0
- package/dist/components/processors.d.ts.map +1 -0
- package/dist/components/receivers.d.ts +118 -0
- package/dist/components/receivers.d.ts.map +1 -0
- package/dist/define.d.ts +136 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/detect.d.ts +2 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/integrity.json +25 -0
- package/dist/lint/audit-catalog.d.ts +13 -0
- package/dist/lint/audit-catalog.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts +3 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -0
- package/dist/lint/post-synth/otel-helpers.d.ts +22 -0
- package/dist/lint/post-synth/otel-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/otel101.d.ts +8 -0
- package/dist/lint/post-synth/otel101.d.ts.map +1 -0
- package/dist/lint/post-synth/otel102.d.ts +8 -0
- package/dist/lint/post-synth/otel102.d.ts.map +1 -0
- package/dist/lint/post-synth/otel103.d.ts +8 -0
- package/dist/lint/post-synth/otel103.d.ts.map +1 -0
- package/dist/lint/post-synth/otel104.d.ts +8 -0
- package/dist/lint/post-synth/otel104.d.ts.map +1 -0
- package/dist/lint/post-synth/otel105.d.ts +8 -0
- package/dist/lint/post-synth/otel105.d.ts.map +1 -0
- package/dist/lint/post-synth/otel106.d.ts +8 -0
- package/dist/lint/post-synth/otel106.d.ts.map +1 -0
- package/dist/lint/post-synth/otel107.d.ts +8 -0
- package/dist/lint/post-synth/otel107.d.ts.map +1 -0
- package/dist/lint/post-synth/otel108.d.ts +8 -0
- package/dist/lint/post-synth/otel108.d.ts.map +1 -0
- package/dist/lint/post-synth/otel109.d.ts +8 -0
- package/dist/lint/post-synth/otel109.d.ts.map +1 -0
- package/dist/lint/rules/component-id-syntax.d.ts +14 -0
- package/dist/lint/rules/component-id-syntax.d.ts.map +1 -0
- package/dist/lint/rules/index.d.ts +6 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/literal-credential.d.ts +13 -0
- package/dist/lint/rules/literal-credential.d.ts.map +1 -0
- package/dist/lint/rules/otel-ast.d.ts +14 -0
- package/dist/lint/rules/otel-ast.d.ts.map +1 -0
- package/dist/lsp/completions.d.ts +4 -0
- package/dist/lsp/completions.d.ts.map +1 -0
- package/dist/lsp/hover.d.ts +4 -0
- package/dist/lsp/hover.d.ts.map +1 -0
- package/dist/manifest.json +8 -0
- package/dist/meta.json +102 -0
- package/dist/model.d.ts +53 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/okf/index.md +40 -0
- package/dist/okf/rules/OTEL001.md +15 -0
- package/dist/okf/rules/OTEL002.md +11 -0
- package/dist/okf/rules/OTEL101.md +11 -0
- package/dist/okf/rules/OTEL102.md +11 -0
- package/dist/okf/rules/OTEL103.md +11 -0
- package/dist/okf/rules/OTEL104.md +11 -0
- package/dist/okf/rules/OTEL105.md +11 -0
- package/dist/okf/rules/OTEL106.md +11 -0
- package/dist/okf/rules/OTEL107.md +11 -0
- package/dist/okf/rules/OTEL108.md +11 -0
- package/dist/okf/rules/OTEL109.md +11 -0
- package/dist/okf/types/AttributesProcessor.md +9 -0
- package/dist/okf/types/BatchProcessor.md +9 -0
- package/dist/okf/types/DebugExporter.md +9 -0
- package/dist/okf/types/FileLogReceiver.md +9 -0
- package/dist/okf/types/GoogleCloudExporter.md +9 -0
- package/dist/okf/types/HealthCheckExtension.md +9 -0
- package/dist/okf/types/HostMetricsReceiver.md +9 -0
- package/dist/okf/types/K8sAttributesProcessor.md +9 -0
- package/dist/okf/types/MemoryLimiterProcessor.md +9 -0
- package/dist/okf/types/OtlpExporter.md +9 -0
- package/dist/okf/types/OtlpHttpExporter.md +9 -0
- package/dist/okf/types/OtlpReceiver.md +9 -0
- package/dist/okf/types/Pipeline.md +13 -0
- package/dist/okf/types/PprofExtension.md +9 -0
- package/dist/okf/types/PrometheusExporter.md +9 -0
- package/dist/okf/types/PrometheusReceiver.md +9 -0
- package/dist/okf/types/ResourceDetectionProcessor.md +9 -0
- package/dist/okf/types/ResourceProcessor.md +9 -0
- package/dist/okf/types/Service.md +9 -0
- package/dist/okf/types/ZPagesExtension.md +9 -0
- package/dist/package-cli.d.ts +3 -0
- package/dist/package-cli.d.ts.map +1 -0
- package/dist/pipeline.d.ts +66 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/platform.d.ts +57 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/rules/component-id-syntax.ts +68 -0
- package/dist/rules/literal-credential.ts +62 -0
- package/dist/rules/otel-ast.ts +30 -0
- package/dist/rules/otel-helpers.ts +70 -0
- package/dist/rules/otel101.ts +17 -0
- package/dist/rules/otel102.ts +17 -0
- package/dist/rules/otel103.ts +17 -0
- package/dist/rules/otel104.ts +17 -0
- package/dist/rules/otel105.ts +17 -0
- package/dist/rules/otel106.ts +17 -0
- package/dist/rules/otel107.ts +17 -0
- package/dist/rules/otel108.ts +17 -0
- package/dist/rules/otel109.ts +17 -0
- package/dist/serializer.d.ts +16 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/skill-defs.d.ts +3 -0
- package/dist/skill-defs.d.ts.map +1 -0
- package/dist/skills/chant-otel-custom-components.md +51 -0
- package/dist/skills/chant-otel-platforms.md +34 -0
- package/dist/skills/chant-otel.md +60 -0
- package/dist/topology.d.ts +56 -0
- package/dist/topology.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/validate-cli.d.ts +3 -0
- package/dist/validate-cli.d.ts.map +1 -0
- package/dist/validate-config.d.ts +30 -0
- package/dist/validate-config.d.ts.map +1 -0
- package/dist/validate.d.ts +11 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/yaml.d.ts +27 -0
- package/dist/yaml.d.ts.map +1 -0
- package/package.json +74 -0
- package/src/catalog.ts +56 -0
- package/src/codegen/docs-cli.ts +4 -0
- package/src/codegen/docs.ts +90 -0
- package/src/codegen/generate-cli.ts +8 -0
- package/src/codegen/generate.ts +50 -0
- package/src/codegen/package.ts +41 -0
- package/src/collector.ts +147 -0
- package/src/components/common.ts +151 -0
- package/src/components/exporters.ts +141 -0
- package/src/components/extensions.ts +51 -0
- package/src/components/index.ts +5 -0
- package/src/components/processors.ts +208 -0
- package/src/components/receivers.ts +177 -0
- package/src/define.test.ts +131 -0
- package/src/define.ts +249 -0
- package/src/detect.ts +11 -0
- package/src/generated/lexicon-otel.json +102 -0
- package/src/index.ts +73 -0
- package/src/lint/audit-catalog.ts +102 -0
- package/src/lint/post-synth/index.ts +23 -0
- package/src/lint/post-synth/otel-helpers.ts +70 -0
- package/src/lint/post-synth/otel101.ts +17 -0
- package/src/lint/post-synth/otel102.ts +17 -0
- package/src/lint/post-synth/otel103.ts +17 -0
- package/src/lint/post-synth/otel104.ts +17 -0
- package/src/lint/post-synth/otel105.ts +17 -0
- package/src/lint/post-synth/otel106.ts +17 -0
- package/src/lint/post-synth/otel107.ts +17 -0
- package/src/lint/post-synth/otel108.ts +17 -0
- package/src/lint/post-synth/otel109.ts +17 -0
- package/src/lint/post-synth/post-synth.test.ts +184 -0
- package/src/lint/rules/component-id-syntax.ts +68 -0
- package/src/lint/rules/index.ts +9 -0
- package/src/lint/rules/literal-credential.ts +62 -0
- package/src/lint/rules/otel-ast.ts +30 -0
- package/src/lint/rules/rules.test.ts +70 -0
- package/src/lsp/completions.test.ts +23 -0
- package/src/lsp/completions.ts +15 -0
- package/src/lsp/hover.test.ts +20 -0
- package/src/lsp/hover.ts +30 -0
- package/src/model.ts +88 -0
- package/src/package-cli.ts +17 -0
- package/src/pipeline.ts +89 -0
- package/src/platform.test.ts +79 -0
- package/src/platform.ts +143 -0
- package/src/plugin.test.ts +55 -0
- package/src/plugin.ts +111 -0
- package/src/serializer.test.ts +187 -0
- package/src/serializer.ts +31 -0
- package/src/skill-defs.ts +36 -0
- package/src/skills/chant-otel-custom-components.md +51 -0
- package/src/skills/chant-otel-platforms.md +34 -0
- package/src/skills/chant-otel.md +60 -0
- package/src/topology.test.ts +80 -0
- package/src/topology.ts +122 -0
- package/src/validate-cli.ts +7 -0
- package/src/validate-config.ts +232 -0
- package/src/validate.ts +82 -0
- package/src/yaml.test.ts +56 -0
- package/src/yaml.ts +145 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where telemetry goes, as plain data.
|
|
3
|
+
*
|
|
4
|
+
* `collectorTopology()` reads a collector config (declared, or parsed from a
|
|
5
|
+
* YAML file) and returns its pipelines, its components with their endpoints
|
|
6
|
+
* and schema pins, and for each exporter the pipelines and signals it
|
|
7
|
+
* carries. It is the surface a reader such as `chant workspace graph` uses to
|
|
8
|
+
* say where a member's telemetry is sent, and what a declared telemetry
|
|
9
|
+
* endpoint link can point at.
|
|
10
|
+
*/
|
|
11
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
12
|
+
import { type SchemaPin } from "./define.js";
|
|
13
|
+
import { type CollectorConfig, type ComponentKind } from "./model.js";
|
|
14
|
+
export interface TopologyPipeline {
|
|
15
|
+
/** The id under `service.pipelines`, e.g. `traces` or `traces/backend`. */
|
|
16
|
+
id: string;
|
|
17
|
+
/** `traces`, `metrics` or `logs`. */
|
|
18
|
+
signal: string;
|
|
19
|
+
receivers: string[];
|
|
20
|
+
processors: string[];
|
|
21
|
+
exporters: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface TopologyComponent {
|
|
24
|
+
/** The collector id, `type` or `type/name`. */
|
|
25
|
+
id: string;
|
|
26
|
+
kind: ComponentKind;
|
|
27
|
+
type: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
/** True for a component this package ships; false for a custom one, or one this process has no definition for. */
|
|
30
|
+
builtin: boolean;
|
|
31
|
+
/** The schema pin of its definition, when this process has the definition. */
|
|
32
|
+
schema?: SchemaPin;
|
|
33
|
+
/** Addresses it listens on or sends to, as the config states them. Empty when the config names none. */
|
|
34
|
+
endpoints: string[];
|
|
35
|
+
/** The pipelines that use it. For an extension, empty. */
|
|
36
|
+
pipelines: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface TopologyExporter {
|
|
39
|
+
id: string;
|
|
40
|
+
type: string;
|
|
41
|
+
endpoints: string[];
|
|
42
|
+
pipelines: string[];
|
|
43
|
+
/** The signals that reach it, deduplicated, in pipeline order. */
|
|
44
|
+
signals: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface CollectorTopology {
|
|
47
|
+
pipelines: TopologyPipeline[];
|
|
48
|
+
components: TopologyComponent[];
|
|
49
|
+
/** The exporters again, grouped for the question "where does this telemetry go". */
|
|
50
|
+
exporters: TopologyExporter[];
|
|
51
|
+
}
|
|
52
|
+
/** The topology of a collector config. */
|
|
53
|
+
export declare function collectorTopology(config: CollectorConfig): CollectorTopology;
|
|
54
|
+
/** The topology of declared entities, i.e. of the config the serializer would emit for them. */
|
|
55
|
+
export declare function collectorTopologyOf(entities: Iterable<Declarable> | Map<string, Declarable>): CollectorTopology;
|
|
56
|
+
//# sourceMappingURL=topology.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAgD,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAEjH,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kHAAkH;IAClH,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,wGAAwG;IACxG,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,oFAAoF;IACpF,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAeD,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CA4C5E;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,iBAAiB,CAE/G"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-cli.d.ts","sourceRoot":"","sources":["../src/validate-cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collector config checks, as plain functions over `CollectorConfig` and over
|
|
3
|
+
* declared entities.
|
|
4
|
+
*
|
|
5
|
+
* The post-synth checks in `lint/post-synth/` are thin wrappers around these,
|
|
6
|
+
* so the same rules can run anywhere a config exists: on a build's output, on
|
|
7
|
+
* a composite's generated YAML, or on a collector file parsed by some other
|
|
8
|
+
* tool.
|
|
9
|
+
*/
|
|
10
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
11
|
+
import { type CollectorConfig } from "./model.js";
|
|
12
|
+
export type CollectorIssueCode = "OTEL101" | "OTEL102" | "OTEL103" | "OTEL104" | "OTEL105" | "OTEL106" | "OTEL107" | "OTEL108" | "OTEL109";
|
|
13
|
+
export interface CollectorIssue {
|
|
14
|
+
code: CollectorIssueCode;
|
|
15
|
+
severity: "error" | "warning";
|
|
16
|
+
message: string;
|
|
17
|
+
/** The pipeline id the issue is about, when it is about one. */
|
|
18
|
+
pipeline?: string;
|
|
19
|
+
/** The component id the issue is about, when it is about one. */
|
|
20
|
+
component?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Check a collector config's references and pipeline shape (OTEL101-OTEL106). */
|
|
23
|
+
export declare function validateCollectorConfig(config: CollectorConfig): CollectorIssue[];
|
|
24
|
+
/**
|
|
25
|
+
* Check declared entities for what only the declaration knows (OTEL107-OTEL109):
|
|
26
|
+
* each component's own config rules, duplicate ids, and custom components'
|
|
27
|
+
* schema pins.
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateCollectorEntities(entities: Iterable<Declarable> | Map<string, Declarable>): CollectorIssue[];
|
|
30
|
+
//# sourceMappingURL=validate-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../src/validate-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,EAA0C,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAGvF,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,kFAAkF;AAClF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,EAAE,CA2HjF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,cAAc,EAAE,CAyDpH"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate the otel lexicon's own artifacts: every built-in class is in the
|
|
3
|
+
* registry, every built-in definition carries the collector pin, and every
|
|
4
|
+
* built-in constructs and serializes.
|
|
5
|
+
*/
|
|
6
|
+
import type { ValidateResult } from "@intentius/chant/codegen/validate";
|
|
7
|
+
export type { ValidateCheck, ValidateResult } from "@intentius/chant/codegen/validate";
|
|
8
|
+
/** Every entity class the package must keep exporting. */
|
|
9
|
+
export declare const REQUIRED_NAMES: string[];
|
|
10
|
+
export declare function validate(): Promise<ValidateResult>;
|
|
11
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAMvF,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEvF,0DAA0D;AAC1D,eAAO,MAAM,cAAc,UAqB1B,CAAC;AAEF,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CA2CxD"}
|
package/dist/yaml.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The collector YAML emitter.
|
|
3
|
+
*
|
|
4
|
+
* Its style is the one collector configs are usually written in, and the one
|
|
5
|
+
* the k8s lexicon's `GkeOtelCollector` wrote by hand before it moved onto this
|
|
6
|
+
* lexicon:
|
|
7
|
+
*
|
|
8
|
+
* - top-level sections in the order receivers, processors, exporters,
|
|
9
|
+
* connectors, extensions, service, separated by a blank line;
|
|
10
|
+
* - two-space indent;
|
|
11
|
+
* - a list of scalars in flow style (`receivers: [otlp, batch]`), any other
|
|
12
|
+
* list in block style with `- ` indented under its key;
|
|
13
|
+
* - strings plain where YAML reads them back as the same string, double-quoted
|
|
14
|
+
* otherwise (`"true"`, `"8080"`, `"a: b"`, `"${env:X}"` inside a flow list).
|
|
15
|
+
*
|
|
16
|
+
* The output always parses back to the value it was given.
|
|
17
|
+
*/
|
|
18
|
+
import type { CollectorConfig } from "./model.js";
|
|
19
|
+
/** True when `s` can be written unquoted and still read back as the string `s`. */
|
|
20
|
+
export declare function isPlainSafe(s: string, flow: boolean): boolean;
|
|
21
|
+
export interface EmitOptions {
|
|
22
|
+
/** Comment lines (without `# `) written above the config. */
|
|
23
|
+
header?: string[];
|
|
24
|
+
}
|
|
25
|
+
/** Print a collector config as YAML. Empty sections are left out. */
|
|
26
|
+
export declare function emitCollectorYaml(config: CollectorConfig, options?: EmitOptions): string;
|
|
27
|
+
//# sourceMappingURL=yaml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../src/yaml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAe/C,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAa7D;AAyED,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAkB5F"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intentius/chant-lexicon-otel",
|
|
3
|
+
"version": "0.81.0",
|
|
4
|
+
"description": "OpenTelemetry Collector lexicon for chant — typed receivers, processors, exporters, extensions and pipelines, serialized to collector YAML",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://intentius.io/chant",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/INTENTIUS/chant.git",
|
|
10
|
+
"directory": "lexicons/otel"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/INTENTIUS/chant/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"infrastructure-as-code",
|
|
17
|
+
"iac",
|
|
18
|
+
"typescript",
|
|
19
|
+
"opentelemetry",
|
|
20
|
+
"otel",
|
|
21
|
+
"collector",
|
|
22
|
+
"observability",
|
|
23
|
+
"chant"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"files": [
|
|
27
|
+
"src/",
|
|
28
|
+
"dist/"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"development": "./src/index.ts",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"default": "./src/index.ts"
|
|
38
|
+
},
|
|
39
|
+
"./*": {
|
|
40
|
+
"development": "./src/*.ts",
|
|
41
|
+
"types": "./dist/*.d.ts",
|
|
42
|
+
"default": "./src/*.ts"
|
|
43
|
+
},
|
|
44
|
+
"./lint/post-synth": {
|
|
45
|
+
"development": "./src/lint/post-synth/index.ts",
|
|
46
|
+
"types": "./dist/lint/post-synth/index.d.ts",
|
|
47
|
+
"default": "./src/lint/post-synth/index.ts"
|
|
48
|
+
},
|
|
49
|
+
"./manifest": "./dist/manifest.json",
|
|
50
|
+
"./meta": "./dist/meta.json",
|
|
51
|
+
"./types": "./dist/types/index.d.ts"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"generate": "tsx src/codegen/generate-cli.ts",
|
|
55
|
+
"bundle": "tsx src/package-cli.ts",
|
|
56
|
+
"validate": "tsx src/validate-cli.ts",
|
|
57
|
+
"docs": "tsx src/codegen/docs-cli.ts",
|
|
58
|
+
"prepack": "npm run generate && npm run bundle && npm run validate && npm run build",
|
|
59
|
+
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && find dist -type f \\( -name \"*.js\" -o -name \"*.js.map\" \\) -delete"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"js-yaml": "^4.3.1"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@intentius/chant": "*",
|
|
66
|
+
"@types/js-yaml": "^4.0.9",
|
|
67
|
+
"tsc-alias": "^1.8.17",
|
|
68
|
+
"typescript": "^5.9.3"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"@intentius/chant": "^0.81.0",
|
|
72
|
+
"typescript": "^5.9.3"
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/catalog.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in entity catalog: every class this package exports, keyed by
|
|
3
|
+
* class name. It feeds the packaged registry (`dist/meta.json`), LSP
|
|
4
|
+
* completions and hover, and the docs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { LexiconEntry } from "@intentius/chant/lsp/lexicon-providers";
|
|
8
|
+
import { componentEntityType, type ComponentClass } from "./define";
|
|
9
|
+
import * as components from "./components";
|
|
10
|
+
import { PIPELINE_TYPE, SERVICE_TYPE } from "./pipeline";
|
|
11
|
+
|
|
12
|
+
export interface CatalogEntry {
|
|
13
|
+
className: string;
|
|
14
|
+
entityType: string;
|
|
15
|
+
kind: "receiver" | "processor" | "exporter" | "extension" | "pipeline" | "service";
|
|
16
|
+
/** The collector type, for components. */
|
|
17
|
+
type?: string;
|
|
18
|
+
description: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isComponentClass(v: unknown): v is ComponentClass {
|
|
22
|
+
return typeof v === "function" && typeof (v as { definition?: unknown }).definition === "object";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const BUILTIN_CATALOG: CatalogEntry[] = [
|
|
26
|
+
...(Object.entries(components) as Array<[string, unknown]>)
|
|
27
|
+
.filter((e): e is [string, ComponentClass] => isComponentClass(e[1]))
|
|
28
|
+
.map(([className, cls]) => ({
|
|
29
|
+
className,
|
|
30
|
+
entityType: componentEntityType(cls.definition.kind, cls.definition.type),
|
|
31
|
+
kind: cls.definition.kind,
|
|
32
|
+
type: cls.definition.type,
|
|
33
|
+
description: cls.definition.description ?? "",
|
|
34
|
+
})),
|
|
35
|
+
{
|
|
36
|
+
className: "Pipeline",
|
|
37
|
+
entityType: PIPELINE_TYPE,
|
|
38
|
+
kind: "pipeline",
|
|
39
|
+
description: "One pipeline under service.pipelines: receivers, then processors, then exporters, for one signal",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
className: "Service",
|
|
43
|
+
entityType: SERVICE_TYPE,
|
|
44
|
+
kind: "service",
|
|
45
|
+
description: "service.extensions and service.telemetry",
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/** The catalog as a chant lexicon registry, keyed by class name. */
|
|
50
|
+
export function lexiconRegistry(): Record<string, LexiconEntry> {
|
|
51
|
+
const out: Record<string, LexiconEntry> = {};
|
|
52
|
+
for (const e of [...BUILTIN_CATALOG].sort((a, b) => a.className.localeCompare(b.className))) {
|
|
53
|
+
out[e.className] = { resourceType: e.entityType, kind: "resource", lexicon: "otel" };
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Documentation generation for the otel lexicon: the generated reference
|
|
3
|
+
* pages from the core docs pipeline, plus the authored pages in docs/pages/.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import { docsPipeline, writeDocsSite, type DocsConfig } from "@intentius/chant/codegen/docs";
|
|
9
|
+
|
|
10
|
+
function serviceFromType(resourceType: string): string {
|
|
11
|
+
const parts = resourceType.split("::");
|
|
12
|
+
return parts.length >= 2 ? parts[1] : "OTel";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const overview = `The otel lexicon types [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/)
|
|
16
|
+
config: receivers, processors, exporters, extensions and the pipelines that
|
|
17
|
+
connect them. \`chant build\` emits one collector config file, the YAML
|
|
18
|
+
\`otelcol --config\` reads as it is.
|
|
19
|
+
|
|
20
|
+
\`\`\`ts
|
|
21
|
+
import { OtlpReceiver, BatchProcessor, OtlpExporter, Pipeline } from "@intentius/chant-lexicon-otel";
|
|
22
|
+
|
|
23
|
+
export const otlp = new OtlpReceiver({ protocols: { grpc: { endpoint: "0.0.0.0:4317" } } });
|
|
24
|
+
export const batch = new BatchProcessor({ timeout: "5s" });
|
|
25
|
+
export const backend = new OtlpExporter({ name: "backend", endpoint: "tempo.observability:4317" });
|
|
26
|
+
|
|
27
|
+
export const traces = new Pipeline({
|
|
28
|
+
signal: "traces",
|
|
29
|
+
receivers: [otlp],
|
|
30
|
+
processors: [batch],
|
|
31
|
+
exporters: [backend],
|
|
32
|
+
});
|
|
33
|
+
\`\`\`
|
|
34
|
+
|
|
35
|
+
The built-in component set is otlp, prometheus, hostmetrics and filelog
|
|
36
|
+
receivers; batch, memory_limiter, resource, attributes, k8sattributes and
|
|
37
|
+
resourcedetection processors; otlp, otlphttp, debug, prometheus and
|
|
38
|
+
googlecloud exporters; and the health_check, pprof and zpages extensions.
|
|
39
|
+
Their config types follow the collector-contrib release named on the
|
|
40
|
+
Custom components page. A component chant doesn't ship is added with
|
|
41
|
+
\`defineComponent\`, and it is serialized and checked the same way as the
|
|
42
|
+
built-ins.
|
|
43
|
+
|
|
44
|
+
Checks catch a pipeline that uses a component nobody declared (OTEL101), a
|
|
45
|
+
pipeline with no receivers or exporters (OTEL102), a declared component no
|
|
46
|
+
pipeline uses (OTEL103), and a literal credential in source (OTEL002).
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const outputFormat = `The otel lexicon serializes every otel entity in a build into **one
|
|
50
|
+
collector config file** in YAML, the file \`otelcol --config\` reads.
|
|
51
|
+
|
|
52
|
+
- Sections come out as receivers, processors, exporters, extensions, service,
|
|
53
|
+
separated by a blank line. Empty sections are left out.
|
|
54
|
+
- A component's id is its collector type, or \`type/name\` when its \`name\` is
|
|
55
|
+
set. The export name in source never appears in the output.
|
|
56
|
+
- A list of scalars is written in flow style (\`receivers: [otlp]\`), any
|
|
57
|
+
other list in block style. Strings are plain where YAML reads them back
|
|
58
|
+
unchanged and double-quoted otherwise.
|
|
59
|
+
- Declared extensions are enabled in declaration order unless a \`Service\`
|
|
60
|
+
lists \`extensions\`.
|
|
61
|
+
- Each custom component adds a \`# chant:\` comment line above the config
|
|
62
|
+
naming its schema pin. Built-ins add none.
|
|
63
|
+
- A collector config has no metadata channel, so no ownership marker is
|
|
64
|
+
stamped.
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
export async function generateDocs(opts?: { verbose?: boolean }): Promise<void> {
|
|
68
|
+
const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
|
|
69
|
+
|
|
70
|
+
const config: DocsConfig = {
|
|
71
|
+
name: "otel",
|
|
72
|
+
displayName: "OpenTelemetry Collector",
|
|
73
|
+
description: "Typed OpenTelemetry Collector config: receivers, processors, exporters and pipelines",
|
|
74
|
+
distDir: join(pkgDir, "dist"),
|
|
75
|
+
outDir: join(pkgDir, "docs"),
|
|
76
|
+
basePath: process.env.DOCS_BASE_PATH ?? "/chant/lexicons/otel/",
|
|
77
|
+
overview,
|
|
78
|
+
outputFormat,
|
|
79
|
+
serviceFromType,
|
|
80
|
+
srcDir: join(pkgDir, "src"),
|
|
81
|
+
examplesDir: join(pkgDir, "examples"),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const result = docsPipeline(config);
|
|
85
|
+
writeDocsSite(config, result);
|
|
86
|
+
|
|
87
|
+
if (opts?.verbose) {
|
|
88
|
+
console.error(`Generated ${result.pages.size} documentation pages`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The otel lexicon's "generation" step.
|
|
3
|
+
*
|
|
4
|
+
* There is no upstream schema to fetch: the collector defines each
|
|
5
|
+
* component's config as a Go struct, and publishes no machine-readable schema
|
|
6
|
+
* for the set as a whole. The built-in types are written by hand against the
|
|
7
|
+
* collector release named in `COLLECTOR_PIN` (src/define.ts), and this step
|
|
8
|
+
* derives the registry from them, so the packaged `dist/meta.json` can never
|
|
9
|
+
* disagree with the classes the package exports.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { dirname, join } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
15
|
+
import type { GenerateResult } from "@intentius/chant/codegen/generate";
|
|
16
|
+
import { BUILTIN_CATALOG, lexiconRegistry } from "../catalog";
|
|
17
|
+
|
|
18
|
+
export type { GenerateResult };
|
|
19
|
+
|
|
20
|
+
/** The packaged types entry re-exports the compiled declarations, which carry every config type. */
|
|
21
|
+
const TYPES_DTS = `// The otel lexicon's entity classes and config types are hand-written in
|
|
22
|
+
// src/ and compiled to dist/index.d.ts; this entry re-exports them.
|
|
23
|
+
export * from "../index";
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
export async function generate(opts?: { verbose?: boolean; force?: boolean }): Promise<GenerateResult> {
|
|
27
|
+
const registry = lexiconRegistry();
|
|
28
|
+
const lexiconJSON = `${JSON.stringify(registry, null, 2)}\n`;
|
|
29
|
+
const components = BUILTIN_CATALOG.filter((c) => c.type !== undefined).length;
|
|
30
|
+
if (opts?.verbose) {
|
|
31
|
+
console.error(`otel: ${components} built-in components, plus Pipeline and Service (${BUILTIN_CATALOG.length} entities)`);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
lexiconJSON,
|
|
35
|
+
typesDTS: TYPES_DTS,
|
|
36
|
+
indexTS: "",
|
|
37
|
+
resources: BUILTIN_CATALOG.length,
|
|
38
|
+
properties: 0,
|
|
39
|
+
enums: 0,
|
|
40
|
+
warnings: [],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Write the registry to src/generated/lexicon-otel.json, for tools that read it from there. */
|
|
45
|
+
export function writeGeneratedFiles(result: GenerateResult): void {
|
|
46
|
+
const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
|
|
47
|
+
const dir = join(pkgDir, "src", "generated");
|
|
48
|
+
mkdirSync(dir, { recursive: true });
|
|
49
|
+
writeFileSync(join(dir, "lexicon-otel.json"), result.lexiconJSON);
|
|
50
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* otel lexicon packaging, delegating to core's packagePipeline.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { join, dirname } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import {
|
|
9
|
+
packagePipeline,
|
|
10
|
+
collectSkills,
|
|
11
|
+
type PackageOptions,
|
|
12
|
+
type PackageResult,
|
|
13
|
+
} from "@intentius/chant/codegen/package";
|
|
14
|
+
import { generate } from "./generate";
|
|
15
|
+
import { otelSkills } from "../skill-defs";
|
|
16
|
+
|
|
17
|
+
export type { PackageOptions, PackageResult };
|
|
18
|
+
|
|
19
|
+
// src/codegen/package.ts -> src/
|
|
20
|
+
const srcDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
21
|
+
|
|
22
|
+
export async function packageLexicon(opts: PackageOptions = {}): Promise<PackageResult> {
|
|
23
|
+
const pkgJson = JSON.parse(readFileSync(join(srcDir, "..", "package.json"), "utf-8"));
|
|
24
|
+
return packagePipeline(
|
|
25
|
+
{
|
|
26
|
+
generate: (genOpts) => generate({ verbose: genOpts.verbose, force: genOpts.force }),
|
|
27
|
+
buildManifest: () => ({
|
|
28
|
+
name: "otel",
|
|
29
|
+
version: pkgJson.version ?? "0.0.1",
|
|
30
|
+
chantVersion: ">=0.1.0",
|
|
31
|
+
namespace: "OTel",
|
|
32
|
+
intrinsics: [],
|
|
33
|
+
pseudoParameters: {},
|
|
34
|
+
}),
|
|
35
|
+
srcDir,
|
|
36
|
+
collectSkills: () => collectSkills(otelSkills()),
|
|
37
|
+
version: pkgJson.version ?? "0.0.1",
|
|
38
|
+
},
|
|
39
|
+
opts,
|
|
40
|
+
);
|
|
41
|
+
}
|
package/src/collector.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declared entities -> `CollectorConfig` -> YAML.
|
|
3
|
+
*
|
|
4
|
+
* The serializer runs this over a build's entities, and a composite in another
|
|
5
|
+
* lexicon (the k8s `GkeOtelCollector`, which puts the YAML in a ConfigMap)
|
|
6
|
+
* runs it over the entities it creates. Both get the same config and the same
|
|
7
|
+
* text.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
11
|
+
import { definitionFor, isOTelComponent, type OTelComponent } from "./define";
|
|
12
|
+
import { SECTION_OF, type CollectorConfig, type PipelineConfig } from "./model";
|
|
13
|
+
import { isPipelineEntity, isServiceEntity, type ComponentRef, type PipelineEntity, type ServiceEntity } from "./pipeline";
|
|
14
|
+
import { emitCollectorYaml } from "./yaml";
|
|
15
|
+
|
|
16
|
+
export interface BuiltCollector {
|
|
17
|
+
config: CollectorConfig;
|
|
18
|
+
/** One line per custom component naming its schema pin. Becomes the YAML's `# chant:` header. */
|
|
19
|
+
header: string[];
|
|
20
|
+
/** Non-fatal problems, e.g. two components declaring the same id. */
|
|
21
|
+
warnings: string[];
|
|
22
|
+
components: OTelComponent[];
|
|
23
|
+
pipelines: PipelineEntity[];
|
|
24
|
+
service?: ServiceEntity;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function entityList(entities: Iterable<Declarable> | Map<string, Declarable>): Declarable[] {
|
|
28
|
+
return entities instanceof Map ? [...entities.values()] : [...entities];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A config value with component entities turned into ids and `undefined` keys dropped. */
|
|
32
|
+
function plain(value: unknown): unknown {
|
|
33
|
+
if (value === undefined) return undefined;
|
|
34
|
+
if (isOTelComponent(value)) return value.componentId;
|
|
35
|
+
if (Array.isArray(value)) return value.map(plain);
|
|
36
|
+
if (typeof value === "object" && value !== null) {
|
|
37
|
+
const toJSON = (value as { toJSON?: () => unknown }).toJSON;
|
|
38
|
+
if (typeof toJSON === "function") return plain(toJSON.call(value));
|
|
39
|
+
const out: Record<string, unknown> = {};
|
|
40
|
+
for (const [k, v] of Object.entries(value)) {
|
|
41
|
+
if (v !== undefined) out[k] = plain(v);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A component's config, as it appears under its id: its props without `name`. */
|
|
49
|
+
export function componentConfig(component: OTelComponent): Record<string, unknown> {
|
|
50
|
+
const { name: _name, ...rest } = (component.props ?? {}) as Record<string, unknown>;
|
|
51
|
+
return plain(rest) as Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function refId(ref: ComponentRef<never> | unknown): string {
|
|
55
|
+
if (isOTelComponent(ref)) return ref.componentId;
|
|
56
|
+
return String(ref);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Build the collector config for a set of declared entities. Non-otel entities are ignored. */
|
|
60
|
+
export function buildCollectorConfig(entities: Iterable<Declarable> | Map<string, Declarable>): BuiltCollector {
|
|
61
|
+
const all = entityList(entities).filter((e) => e && e.lexicon === "otel");
|
|
62
|
+
const warnings: string[] = [];
|
|
63
|
+
const components: OTelComponent[] = [];
|
|
64
|
+
const byId = new Map<string, OTelComponent>();
|
|
65
|
+
const pipelines: PipelineEntity[] = [];
|
|
66
|
+
let service: ServiceEntity | undefined;
|
|
67
|
+
|
|
68
|
+
const addComponent = (c: OTelComponent) => {
|
|
69
|
+
const key = `${c.componentKind}:${c.componentId}`;
|
|
70
|
+
const existing = byId.get(key);
|
|
71
|
+
if (existing === c) return;
|
|
72
|
+
if (existing) {
|
|
73
|
+
warnings.push(`otel: two ${c.componentKind}s declare the id "${c.componentId}"; the first one is emitted`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
byId.set(key, c);
|
|
77
|
+
components.push(c);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
for (const e of all) {
|
|
81
|
+
if (isOTelComponent(e)) addComponent(e);
|
|
82
|
+
else if (isPipelineEntity(e)) pipelines.push(e);
|
|
83
|
+
else if (isServiceEntity(e)) {
|
|
84
|
+
if (service) warnings.push("otel: more than one Service is declared; the first one is used");
|
|
85
|
+
else service = e;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// A component a pipeline or the service references by entity is part of the
|
|
90
|
+
// config even when the caller didn't list it: it carries its own config.
|
|
91
|
+
for (const p of pipelines) {
|
|
92
|
+
for (const ref of [...(p.props.receivers ?? []), ...(p.props.processors ?? []), ...(p.props.exporters ?? [])]) {
|
|
93
|
+
if (isOTelComponent(ref)) addComponent(ref);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const ref of service?.props.extensions ?? []) {
|
|
97
|
+
if (isOTelComponent(ref)) addComponent(ref);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const config: CollectorConfig = {};
|
|
101
|
+
for (const c of components) {
|
|
102
|
+
const section = SECTION_OF[c.componentKind];
|
|
103
|
+
const bucket = (config[section] ??= {});
|
|
104
|
+
bucket[c.componentId] = componentConfig(c);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const pipelineMap: Record<string, PipelineConfig> = {};
|
|
108
|
+
for (const p of pipelines) {
|
|
109
|
+
if (p.pipelineId in pipelineMap) {
|
|
110
|
+
warnings.push(`otel: two pipelines declare the id "${p.pipelineId}"; the first one is emitted`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const entry: PipelineConfig = { receivers: (p.props.receivers ?? []).map(refId) };
|
|
114
|
+
const processors = (p.props.processors ?? []).map(refId);
|
|
115
|
+
if (processors.length > 0) entry.processors = processors;
|
|
116
|
+
entry.exporters = (p.props.exporters ?? []).map(refId);
|
|
117
|
+
pipelineMap[p.pipelineId] = entry;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const extensions = service?.props.extensions
|
|
121
|
+
? service.props.extensions.map(refId)
|
|
122
|
+
: components.filter((c) => c.componentKind === "extension").map((c) => c.componentId);
|
|
123
|
+
|
|
124
|
+
if (pipelines.length > 0 || extensions.length > 0 || service?.props.telemetry) {
|
|
125
|
+
config.service = {};
|
|
126
|
+
if (extensions.length > 0) config.service.extensions = extensions;
|
|
127
|
+
if (service?.props.telemetry) config.service.telemetry = plain(service.props.telemetry) as Record<string, unknown>;
|
|
128
|
+
if (pipelines.length > 0) config.service.pipelines = pipelineMap;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const header: string[] = [];
|
|
132
|
+
for (const c of components) {
|
|
133
|
+
const def = definitionFor(c.entityType);
|
|
134
|
+
if (!def || def.builtin) continue;
|
|
135
|
+
const pin = def.pin;
|
|
136
|
+
const digest = pin?.digest ? ` ${pin.digest}` : "";
|
|
137
|
+
header.push(`chant: ${c.componentKind} ${c.componentId} schema ${pin?.source ?? "(unpinned)"}@${pin?.version ?? "(unpinned)"}${digest}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return { config, header, warnings, components, pipelines, service };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Collector YAML for a set of declared entities, exactly as the serializer emits it. */
|
|
144
|
+
export function collectorYaml(entities: Iterable<Declarable> | Map<string, Declarable>): string {
|
|
145
|
+
const built = buildCollectorConfig(entities);
|
|
146
|
+
return emitCollectorYaml(built.config, { header: built.header });
|
|
147
|
+
}
|