@intentius/chant-lexicon-otel 0.106.4 → 0.108.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 +1 -1
- package/dist/collector.d.ts +6 -0
- package/dist/collector.d.ts.map +1 -1
- package/dist/composites/catalog.d.ts.map +1 -1
- package/dist/composites/genai-pipeline.d.ts +33 -0
- package/dist/composites/genai-pipeline.d.ts.map +1 -0
- package/dist/composites/index.d.ts +8 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/otlp-collector.d.ts +43 -0
- package/dist/composites/otlp-collector.d.ts.map +1 -0
- package/dist/composites/red-metrics.d.ts +77 -0
- package/dist/composites/red-metrics.d.ts.map +1 -0
- package/dist/composites/tail-sampling-tier.d.ts +90 -0
- package/dist/composites/tail-sampling-tier.d.ts.map +1 -0
- package/dist/configmap.d.ts +16 -0
- package/dist/configmap.d.ts.map +1 -1
- package/dist/genai.d.ts +19 -0
- package/dist/genai.d.ts.map +1 -1
- package/dist/import/embedded.d.ts +8 -0
- package/dist/import/embedded.d.ts.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +3 -3
- package/dist/lint/post-synth/otel-helpers.d.ts +9 -2
- package/dist/lint/post-synth/otel-helpers.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/metric-names.d.ts +68 -0
- package/dist/metric-names.d.ts.map +1 -1
- package/dist/op/activities/collector-audit.d.ts +95 -0
- package/dist/op/activities/collector-audit.d.ts.map +1 -0
- package/dist/op/activities/collector-health.d.ts +74 -0
- package/dist/op/activities/collector-health.d.ts.map +1 -0
- package/dist/op/activities/exec.d.ts +19 -0
- package/dist/op/activities/exec.d.ts.map +1 -0
- package/dist/op/activities/github.d.ts +55 -0
- package/dist/op/activities/github.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +20 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/otelcol.d.ts +96 -0
- package/dist/op/activities/otelcol.d.ts.map +1 -0
- package/dist/op/activity-contracts.d.ts +96 -0
- package/dist/op/activity-contracts.d.ts.map +1 -0
- package/dist/op/audit-op.d.ts +35 -0
- package/dist/op/audit-op.d.ts.map +1 -0
- package/dist/op/builders.d.ts +43 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/platform.d.ts +14 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/rules/otel-helpers.ts +18 -5
- package/package.json +14 -3
- package/src/collector.ts +9 -0
- package/src/composites/catalog.test.ts +1 -1
- package/src/composites/catalog.ts +292 -0
- package/src/composites/genai-pipeline.test.ts +53 -0
- package/src/composites/genai-pipeline.ts +40 -0
- package/src/composites/index.ts +8 -0
- package/src/composites/otlp-collector.test.ts +43 -0
- package/src/composites/otlp-collector.ts +70 -0
- package/src/composites/red-metrics.test.ts +131 -0
- package/src/composites/red-metrics.ts +148 -0
- package/src/composites/tail-sampling-tier.test.ts +100 -0
- package/src/composites/tail-sampling-tier.ts +182 -0
- package/src/configmap-operator.test.ts +44 -0
- package/src/configmap.ts +35 -0
- package/src/detect.ts +13 -1
- package/src/genai.ts +72 -59
- package/src/import/embedded.test.ts +36 -0
- package/src/import/embedded.ts +28 -4
- package/src/index.ts +57 -2
- package/src/lint/post-synth/otel-helpers.ts +18 -5
- package/src/metric-names.ts +141 -0
- package/src/op/activities/collector-audit.test.ts +166 -0
- package/src/op/activities/collector-audit.ts +265 -0
- package/src/op/activities/collector-health.test.ts +115 -0
- package/src/op/activities/collector-health.ts +211 -0
- package/src/op/activities/exec.ts +33 -0
- package/src/op/activities/github.ts +127 -0
- package/src/op/activities/index.ts +19 -0
- package/src/op/activities/otelcol.test.ts +162 -0
- package/src/op/activities/otelcol.ts +233 -0
- package/src/op/activity-contracts.test.ts +103 -0
- package/src/op/activity-contracts.ts +92 -0
- package/src/op/audit-op.ts +53 -0
- package/src/op/builders.ts +52 -0
- package/src/op/testdata/otelcol-components-v0.130.0.yaml +82 -0
- package/src/platform.ts +45 -8
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step builders for this lexicon's Op activities (#3369), following
|
|
3
|
+
* the helm and fly builders: each one's options ARE the activity's own
|
|
4
|
+
* `*Args` interface (minus its `_`-prefixed test seams), so the builder and
|
|
5
|
+
* the implementation cannot drift, and every field also takes a
|
|
6
|
+
* `StepOutputRef`. `profile` and `id` go to the step, never into args, so
|
|
7
|
+
* `.out` works once an id is given.
|
|
8
|
+
*/
|
|
9
|
+
import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
|
|
10
|
+
import type { OtelcolValidateArgs, OtelcolComponentsArgs } from "./activities/otelcol.js";
|
|
11
|
+
import type { CollectorHealthObserveArgs } from "./activities/collector-health.js";
|
|
12
|
+
import type { CollectorAuditArgs } from "./activities/collector-audit.js";
|
|
13
|
+
type StepOpts = {
|
|
14
|
+
profile?: ActivityStep["profile"];
|
|
15
|
+
id?: string;
|
|
16
|
+
};
|
|
17
|
+
/** An activity's args as an author writes them: without the test seams. */
|
|
18
|
+
type Authored<T> = Omit<T, `_${string}`>;
|
|
19
|
+
/**
|
|
20
|
+
* Run `otelcol validate` over a collector config file. Refuses when the
|
|
21
|
+
* binary is not `COLLECTOR_PIN`'s version, unless `version` names the one it
|
|
22
|
+
* must be. Defaults to the `fastIdempotent` profile.
|
|
23
|
+
*/
|
|
24
|
+
export declare const otelcolValidate: (args: WithStepRefs<Authored<OtelcolValidateArgs>> & StepOpts) => NamedActivityStep;
|
|
25
|
+
/**
|
|
26
|
+
* Check a collector config uses only components the binary was built with,
|
|
27
|
+
* from `otelcol components`. Defaults to the `fastIdempotent` profile.
|
|
28
|
+
*/
|
|
29
|
+
export declare const otelcolComponents: (args: WithStepRefs<Authored<OtelcolComponentsArgs>> & StepOpts) => NamedActivityStep;
|
|
30
|
+
/**
|
|
31
|
+
* Observe running collectors for a `ConvergeOp({ observe })`: one resource
|
|
32
|
+
* per collector, from the health_check, zpages and internal-telemetry
|
|
33
|
+
* endpoints its config declares. No `health_check` in `service.extensions`
|
|
34
|
+
* is `unknown`. Defaults to the `fastIdempotent` profile.
|
|
35
|
+
*/
|
|
36
|
+
export declare const collectorHealthObserve: (args: WithStepRefs<Authored<CollectorHealthObserveArgs>> & StepOpts) => NamedActivityStep;
|
|
37
|
+
/**
|
|
38
|
+
* Audit the lexicon's pins against upstream releases (the step of
|
|
39
|
+
* `CollectorAuditOp`). Defaults to the `fastIdempotent` profile.
|
|
40
|
+
*/
|
|
41
|
+
export declare const collectorAudit: (args?: WithStepRefs<Authored<CollectorAuditArgs>> & StepOpts) => NamedActivityStep;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=builders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA8B,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC/H,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACnE,2EAA2E;AAC3E,KAAK,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC,CAAC;AASzC;;;;GAIG;AACH,eAAO,MAAM,eAAe,oEAX8B,iBAWmC,CAAC;AAE9F;;;GAGG;AACH,eAAO,MAAM,iBAAiB,sEAjB4B,iBAiByC,CAAC;AAEpG;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,2EAzBuB,iBAyBwD,CAAC;AAEnH;;;GAGG;AACH,eAAO,MAAM,cAAc,UAAU,YAAY,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,GAAG,QAAQ,KAAQ,iBAC9B,CAAC"}
|
package/dist/platform.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Declarable } from "@intentius/chant/declarable";
|
|
12
12
|
import { type OTelComponent } from "./define.js";
|
|
13
|
+
import { type PipelineEntity } from "./pipeline.js";
|
|
13
14
|
import { type CollectorConfig, type Signal } from "./model.js";
|
|
14
15
|
/** The contrib collector image at the version the built-in components are typed against. */
|
|
15
16
|
export declare const COLLECTOR_IMAGE: string;
|
|
@@ -23,6 +24,19 @@ export interface OtlpCollectorOptions {
|
|
|
23
24
|
/** Serve `health_check` on 0.0.0.0:13133. Default: true. */
|
|
24
25
|
healthCheck?: boolean;
|
|
25
26
|
}
|
|
27
|
+
/** The parts of `otlpCollector()`'s config, by name. */
|
|
28
|
+
export interface OtlpCollectorParts {
|
|
29
|
+
otlp: OTelComponent<"receiver", "otlp", object>;
|
|
30
|
+
memoryLimiter: OTelComponent<"processor", "memory_limiter", object>;
|
|
31
|
+
batch: OTelComponent<"processor", "batch", object>;
|
|
32
|
+
exporters: OTelComponent<"exporter", string, any>[];
|
|
33
|
+
/** Absent with `healthCheck: false`. */
|
|
34
|
+
health?: OTelComponent<"extension", "health_check", object>;
|
|
35
|
+
/** One pipeline per signal asked for. */
|
|
36
|
+
pipelines: Partial<Record<Signal, PipelineEntity>>;
|
|
37
|
+
}
|
|
38
|
+
/** `otlpCollector()`'s config by part, for the `OtlpCollector` composite. A signal listed twice gets one pipeline. */
|
|
39
|
+
export declare function otlpCollectorParts(options?: OtlpCollectorOptions): OtlpCollectorParts;
|
|
26
40
|
/**
|
|
27
41
|
* The entities of a small OTLP collector: an `otlp` receiver on 4317 (gRPC)
|
|
28
42
|
* and 4318 (HTTP), `memory_limiter` then `batch`, the given exporters, and a
|
package/dist/platform.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAK7D,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAA6B,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAGvF,4FAA4F;AAC5F,eAAO,MAAM,eAAe,QAAoF,CAAC;AAEjH,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,SAAS,CAAC,EAAE,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;IACrD,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wDAAwD;AACxD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,aAAa,EAAE,aAAa,CAAC,WAAW,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IACpE,KAAK,EAAE,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEnD,SAAS,EAAE,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;IACpD,wCAAwC;IACxC,MAAM,CAAC,EAAE,aAAa,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAC5D,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CACpD;AAmBD,sHAAsH;AACtH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,GAAG,kBAAkB,CAezF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,UAAU,EAAE,CAS9E;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,4GAA4G;IAC5G,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CAiC9E"}
|
|
@@ -8,7 +8,7 @@ import type { SerializerResult } from "@intentius/chant/serializer";
|
|
|
8
8
|
import { loadAll } from "js-yaml";
|
|
9
9
|
import type { Declarable } from "@intentius/chant/declarable";
|
|
10
10
|
import { looksLikeCollectorConfig, type CollectorConfig } from "../../model";
|
|
11
|
-
import { configMapCollectorConfigs, describeConfigMapConfig } from "../../configmap";
|
|
11
|
+
import { configMapCollectorConfigs, describeConfigMapConfig, describeOperatorCollectorConfig, operatorCollectorConfig } from "../../configmap";
|
|
12
12
|
import { validateCollectorConfig, validateCollectorEntities, type CollectorIssueCode, type CollectorIssue } from "../../validate-config";
|
|
13
13
|
import { attributionIssues } from "../../attribution";
|
|
14
14
|
|
|
@@ -19,13 +19,16 @@ export interface FoundCollectorConfig {
|
|
|
19
19
|
config: CollectorConfig;
|
|
20
20
|
/** Set when the config is a value in a Kubernetes ConfigMap (chant #2930). */
|
|
21
21
|
configMap?: { namespace: string; name: string; key: string };
|
|
22
|
+
/** Set when the config is the `spec.config` of an OpenTelemetry Operator `OpenTelemetryCollector` (chant #3367). */
|
|
23
|
+
operator?: { namespace: string; name: string };
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Every collector config in the output: the otel lexicon's own, any YAML
|
|
26
28
|
* document shaped like one, and any ConfigMap data value that parses as one
|
|
27
29
|
* (how `OtelCollector`, `OtelCollectorGateway` and `GkeOtelCollector` carry
|
|
28
|
-
* theirs)
|
|
30
|
+
* theirs), and the `spec.config` of an OpenTelemetry Operator
|
|
31
|
+
* `OpenTelemetryCollector` (chant #3367). Parsed with js-yaml rather than `ctx.docs`, because collector
|
|
29
32
|
* configs are written with flow lists (`[otlp, batch]`) that core's small
|
|
30
33
|
* YAML reader keeps as strings.
|
|
31
34
|
*
|
|
@@ -57,6 +60,8 @@ export function collectorConfigs(ctx: PostSynthContext): FoundCollectorConfig[]
|
|
|
57
60
|
for (const { config, ...configMap } of configMapCollectorConfigs(doc)) {
|
|
58
61
|
out.push({ source, config, configMap });
|
|
59
62
|
}
|
|
63
|
+
const cr = operatorCollectorConfig(doc);
|
|
64
|
+
if (cr) out.push({ source, config: cr.config, operator: { namespace: cr.namespace, name: cr.name } });
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
}
|
|
@@ -64,7 +69,11 @@ export function collectorConfigs(ctx: PostSynthContext): FoundCollectorConfig[]
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
function toDiagnostic(issue: CollectorIssue, found?: Omit<FoundCollectorConfig, "config">): PostSynthDiagnostic {
|
|
67
|
-
const where = found?.configMap
|
|
72
|
+
const where = found?.configMap
|
|
73
|
+
? describeConfigMapConfig(found.configMap)
|
|
74
|
+
: found?.operator
|
|
75
|
+
? describeOperatorCollectorConfig(found.operator)
|
|
76
|
+
: found && found.source !== "otel" ? found.source : undefined;
|
|
68
77
|
return {
|
|
69
78
|
checkId: issue.code,
|
|
70
79
|
severity: issue.severity,
|
|
@@ -87,11 +96,15 @@ function configIssues(ctx: PostSynthContext, config: CollectorConfig): Collector
|
|
|
87
96
|
/**
|
|
88
97
|
* Every config-level diagnostic (OTEL101-OTEL106, OTEL112-OTEL127 and any later
|
|
89
98
|
* config check) over the collector configs in the output. `configMapsOnly`
|
|
90
|
-
* keeps the configs held in ConfigMaps
|
|
99
|
+
* keeps the configs held in ConfigMaps. `hostedOnly` keeps those and the `spec.config` of an operator `OpenTelemetryCollector`, which is what WK8604 reads.
|
|
91
100
|
*/
|
|
92
|
-
export function collectorConfigDiagnostics(
|
|
101
|
+
export function collectorConfigDiagnostics(
|
|
102
|
+
ctx: PostSynthContext,
|
|
103
|
+
opts: { configMapsOnly?: boolean; hostedOnly?: boolean } = {},
|
|
104
|
+
): PostSynthDiagnostic[] {
|
|
93
105
|
return collectorConfigs(ctx)
|
|
94
106
|
.filter((found) => !opts.configMapsOnly || found.configMap)
|
|
107
|
+
.filter((found) => !opts.hostedOnly || found.configMap || found.operator)
|
|
95
108
|
.flatMap(({ config, ...found }) => configIssues(ctx, config).map((i) => toDiagnostic(i, found)));
|
|
96
109
|
}
|
|
97
110
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-otel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.108.0",
|
|
4
4
|
"description": "OpenTelemetry Collector lexicon for chant — typed receivers, processors, exporters, connectors, extensions and pipelines, serialized to collector YAML",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -41,6 +41,16 @@
|
|
|
41
41
|
"types": "./dist/*.d.ts",
|
|
42
42
|
"default": "./src/*.ts"
|
|
43
43
|
},
|
|
44
|
+
"./op/activities": {
|
|
45
|
+
"development": "./src/op/activities/index.ts",
|
|
46
|
+
"types": "./dist/op/activities/index.d.ts",
|
|
47
|
+
"default": "./src/op/activities/index.ts"
|
|
48
|
+
},
|
|
49
|
+
"./op/activity-contracts": {
|
|
50
|
+
"development": "./src/op/activity-contracts.ts",
|
|
51
|
+
"types": "./dist/op/activity-contracts.d.ts",
|
|
52
|
+
"default": "./src/op/activity-contracts.ts"
|
|
53
|
+
},
|
|
44
54
|
"./lint/post-synth": {
|
|
45
55
|
"development": "./src/lint/post-synth/index.ts",
|
|
46
56
|
"types": "./dist/lint/post-synth/index.d.ts",
|
|
@@ -59,7 +69,8 @@
|
|
|
59
69
|
"build": "../../scripts/tsc7.sh -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && find dist -type f \\( -name \"*.js\" -o -name \"*.js.map\" \\) -delete"
|
|
60
70
|
},
|
|
61
71
|
"dependencies": {
|
|
62
|
-
"js-yaml": "^4.3.1"
|
|
72
|
+
"js-yaml": "^4.3.1",
|
|
73
|
+
"zod": "^4.3.6"
|
|
63
74
|
},
|
|
64
75
|
"devDependencies": {
|
|
65
76
|
"@intentius/chant": "*",
|
|
@@ -68,7 +79,7 @@
|
|
|
68
79
|
"typescript": "^5.9.3"
|
|
69
80
|
},
|
|
70
81
|
"peerDependencies": {
|
|
71
|
-
"@intentius/chant": "^0.
|
|
82
|
+
"@intentius/chant": "^0.108.0",
|
|
72
83
|
"typescript": "^5.9.3"
|
|
73
84
|
}
|
|
74
85
|
}
|
package/src/collector.ts
CHANGED
|
@@ -153,3 +153,12 @@ export function collectorYaml(entities: Iterable<Declarable> | Map<string, Decla
|
|
|
153
153
|
const built = buildCollectorConfig(entities);
|
|
154
154
|
return emitCollectorYaml(built.config, { header: built.header });
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The collector config object for a set of declared entities, for a host that
|
|
159
|
+
* holds the config as an object rather than as text: the OpenTelemetry
|
|
160
|
+
* Operator's `OpenTelemetryCollector` `spec.config` (v1beta1).
|
|
161
|
+
*/
|
|
162
|
+
export function collectorConfig(entities: Iterable<Declarable> | Map<string, Declarable>): CollectorConfig {
|
|
163
|
+
return buildCollectorConfig(entities).config;
|
|
164
|
+
}
|
|
@@ -19,7 +19,7 @@ const catalogued = compositeCatalog.map((entry) => entry.name).sort();
|
|
|
19
19
|
|
|
20
20
|
describe("the otel composite catalog", () => {
|
|
21
21
|
test("every exported composite has an entry, and every entry names an exported composite", () => {
|
|
22
|
-
expect(exported).toEqual(["NodeAgent"]);
|
|
22
|
+
expect(exported).toEqual(["GenAiPipeline", "NodeAgent", "OtlpCollector", "RedMetrics", "TailSamplingTier"]);
|
|
23
23
|
expect(catalogued, "regenerate with `npm run generate:composite-catalogs -- otel`").toEqual(exported);
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -4,6 +4,131 @@
|
|
|
4
4
|
import type { CompositeEntry } from "@intentius/chant/lexicon";
|
|
5
5
|
|
|
6
6
|
export const compositeCatalog: CompositeEntry[] = [
|
|
7
|
+
{
|
|
8
|
+
"name": "GenAiPipeline",
|
|
9
|
+
"lexicon": "otel",
|
|
10
|
+
"description": "The collector config of an OTLP collector for GenAI workloads, from the GenAI preset.",
|
|
11
|
+
"bundles": [
|
|
12
|
+
"BatchProcessor",
|
|
13
|
+
"DebugExporter",
|
|
14
|
+
"DeltaToCumulativeProcessor",
|
|
15
|
+
"FilterProcessor",
|
|
16
|
+
"ForwardConnector",
|
|
17
|
+
"HealthCheckExtension",
|
|
18
|
+
"MemoryLimiterProcessor",
|
|
19
|
+
"OtlpReceiver",
|
|
20
|
+
"Pipeline",
|
|
21
|
+
"RedactionProcessor",
|
|
22
|
+
"SignalToMetricsConnector",
|
|
23
|
+
"SpanMetricsConnector",
|
|
24
|
+
"SumConnector",
|
|
25
|
+
"TransformProcessor"
|
|
26
|
+
],
|
|
27
|
+
"params": [
|
|
28
|
+
{
|
|
29
|
+
"name": "traceExporters",
|
|
30
|
+
"type": "Exporter[]",
|
|
31
|
+
"required": false,
|
|
32
|
+
"description": "Where traces go."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "metricExporters",
|
|
36
|
+
"type": "Exporter[]",
|
|
37
|
+
"required": false,
|
|
38
|
+
"description": "Where the span and token metrics go, and with `clientMetrics` the SDK's metrics too."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "logExporters",
|
|
42
|
+
"type": "Exporter[]",
|
|
43
|
+
"required": false,
|
|
44
|
+
"description": "Where logs (and events sent as logs) go."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "logs",
|
|
48
|
+
"type": "boolean",
|
|
49
|
+
"required": false,
|
|
50
|
+
"description": "Give logs a pipeline, so event-based content is removed too."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "sampling",
|
|
54
|
+
"type": "Processor[]",
|
|
55
|
+
"required": false,
|
|
56
|
+
"description": "Processors that thin exported traces, such as `tail_sampling`."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "healthCheck",
|
|
60
|
+
"type": "boolean",
|
|
61
|
+
"required": false,
|
|
62
|
+
"description": "Serve `health_check` on 0.0.0.0:13133."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "deltaToCumulative",
|
|
66
|
+
"type": "boolean | \"auto\"",
|
|
67
|
+
"required": false,
|
|
68
|
+
"description": "Put a `deltatocumulative/genai` processor in front of `batch` on `metrics/genai`, so the delta token sums of the `sum` connector, and with `clientMetrics."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "keepContent",
|
|
72
|
+
"type": "boolean",
|
|
73
|
+
"required": false,
|
|
74
|
+
"description": "Keep content attributes and bodies."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "contentAttributes",
|
|
78
|
+
"type": "string[]",
|
|
79
|
+
"required": false,
|
|
80
|
+
"description": "More attribute keys that hold content, deleted along with the convention ones."
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "maskValues",
|
|
84
|
+
"type": "string[]",
|
|
85
|
+
"required": false,
|
|
86
|
+
"description": "RE2 patterns masked in every attribute value (redaction `blocked_values`), whether content is kept or not."
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "hashFunction",
|
|
90
|
+
"type": "RedactionProcessorConfig[\"hash_function\"]",
|
|
91
|
+
"required": false,
|
|
92
|
+
"description": "Hash masked values with this function instead of writing `****`."
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "buckets",
|
|
96
|
+
"type": "Duration[]",
|
|
97
|
+
"required": false,
|
|
98
|
+
"description": "Duration histogram buckets."
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "metricsFlushInterval",
|
|
102
|
+
"type": "Duration",
|
|
103
|
+
"required": false,
|
|
104
|
+
"description": "How often span and token metrics are flushed."
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"name": "namespace",
|
|
108
|
+
"type": "string",
|
|
109
|
+
"required": false,
|
|
110
|
+
"description": "Prefix of the emitted metric names."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "dimensions",
|
|
114
|
+
"type": "SpanMetricsDimension[]",
|
|
115
|
+
"required": false,
|
|
116
|
+
"description": "Dimensions added to the span metrics beyond the GenAI ones."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "providerDimensions",
|
|
120
|
+
"type": "boolean",
|
|
121
|
+
"required": false,
|
|
122
|
+
"description": "Add `gen_ai.provider.name` and `gen_ai.response.model` to `genai.calls` and `genai.duration`."
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "clientMetrics",
|
|
126
|
+
"type": "GenAiClientMetricsSource",
|
|
127
|
+
"required": false,
|
|
128
|
+
"description": "Also produce the conventions' client metrics, `gen_ai.client.operation.duration` and `gen_ai.client.token.usage`."
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
},
|
|
7
132
|
{
|
|
8
133
|
"name": "NodeAgent",
|
|
9
134
|
"lexicon": "otel",
|
|
@@ -77,5 +202,172 @@ export const compositeCatalog: CompositeEntry[] = [
|
|
|
77
202
|
"description": "Serve `health_check` on 0.0.0.0:13133 (default: on)."
|
|
78
203
|
}
|
|
79
204
|
]
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"name": "OtlpCollector",
|
|
208
|
+
"lexicon": "otel",
|
|
209
|
+
"description": "A small OTLP collector config: OTLP in, `memory_limiter` and `batch`, the given exporters out, for each signal.",
|
|
210
|
+
"bundles": [
|
|
211
|
+
"BatchProcessor",
|
|
212
|
+
"DebugExporter",
|
|
213
|
+
"HealthCheckExtension",
|
|
214
|
+
"MemoryLimiterProcessor",
|
|
215
|
+
"OtlpReceiver",
|
|
216
|
+
"Pipeline"
|
|
217
|
+
],
|
|
218
|
+
"params": [
|
|
219
|
+
{
|
|
220
|
+
"name": "exporters",
|
|
221
|
+
"type": "OTelComponent<\"exporter\", string, any>[]",
|
|
222
|
+
"required": false,
|
|
223
|
+
"description": "Where telemetry goes."
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "signals",
|
|
227
|
+
"type": "Signal[]",
|
|
228
|
+
"required": false,
|
|
229
|
+
"description": "Which signals get a pipeline."
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"name": "healthCheck",
|
|
233
|
+
"type": "boolean",
|
|
234
|
+
"required": false,
|
|
235
|
+
"description": "Serve `health_check` on 0.0.0.0:13133."
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"name": "RedMetrics",
|
|
241
|
+
"lexicon": "otel",
|
|
242
|
+
"description": "RED metrics from traces: `spanmetrics` and `servicegraph` connectors feeding a `prometheus` exporter.",
|
|
243
|
+
"bundles": [
|
|
244
|
+
"BatchProcessor",
|
|
245
|
+
"MemoryLimiterProcessor",
|
|
246
|
+
"OtlpReceiver",
|
|
247
|
+
"Pipeline",
|
|
248
|
+
"PrometheusExporter",
|
|
249
|
+
"ServiceGraphConnector",
|
|
250
|
+
"SpanMetricsConnector"
|
|
251
|
+
],
|
|
252
|
+
"params": [
|
|
253
|
+
{
|
|
254
|
+
"name": "receivers",
|
|
255
|
+
"type": "TraceSource[]",
|
|
256
|
+
"required": false,
|
|
257
|
+
"description": "Where spans come from: receivers, or a connector from another traces pipeline."
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"name": "traceExporters",
|
|
261
|
+
"type": "Exporter[]",
|
|
262
|
+
"required": false,
|
|
263
|
+
"description": "Where traces go besides the connectors, e.g. a tracing backend."
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"name": "exporter",
|
|
267
|
+
"type": "OTelComponent<\"exporter\", \"prometheus\", PrometheusExporterConfig>",
|
|
268
|
+
"required": false,
|
|
269
|
+
"description": "The `prometheus` exporter the metrics are served on."
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"name": "spanMetrics",
|
|
273
|
+
"type": "SpanMetricsConnectorConfig",
|
|
274
|
+
"required": false,
|
|
275
|
+
"description": "The `spanmetrics` connector's config: namespace, dimensions, histogram unit and buckets (default: the connector's defaults)."
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"name": "serviceGraph",
|
|
279
|
+
"type": "boolean | ServiceGraphConnectorConfig",
|
|
280
|
+
"required": false,
|
|
281
|
+
"description": "Service-to-service edge metrics from a `servicegraph` connector (default: on)."
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"name": "memoryLimitMib",
|
|
285
|
+
"type": "number",
|
|
286
|
+
"required": false,
|
|
287
|
+
"description": "`memory_limiter`'s hard limit in MiB (default: 80% of the container's memory, with a 20% spike limit)."
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"name": "name",
|
|
291
|
+
"type": "string",
|
|
292
|
+
"required": false,
|
|
293
|
+
"description": "The instance name of the connectors, the exporter and the two pipelines (default `red`)."
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name": "TailSamplingTier",
|
|
299
|
+
"lexicon": "otel",
|
|
300
|
+
"description": "The collector config of a tail sampling tier: whole traces in, the ones a policy keeps out.",
|
|
301
|
+
"bundles": [
|
|
302
|
+
"BatchProcessor",
|
|
303
|
+
"DebugExporter",
|
|
304
|
+
"HealthCheckExtension",
|
|
305
|
+
"MemoryLimiterProcessor",
|
|
306
|
+
"OtlpReceiver",
|
|
307
|
+
"Pipeline",
|
|
308
|
+
"TailSamplingProcessor"
|
|
309
|
+
],
|
|
310
|
+
"params": [
|
|
311
|
+
{
|
|
312
|
+
"name": "exporters",
|
|
313
|
+
"type": "Exporter[]",
|
|
314
|
+
"required": false,
|
|
315
|
+
"description": "Where the kept traces go."
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"name": "receivers",
|
|
319
|
+
"type": "TraceSource[]",
|
|
320
|
+
"required": false,
|
|
321
|
+
"description": "Where spans come from."
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"name": "decisionWait",
|
|
325
|
+
"type": "Duration",
|
|
326
|
+
"required": false,
|
|
327
|
+
"description": "How long after a trace's first span the decision is made (default `10s`)."
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"name": "errors",
|
|
331
|
+
"type": "boolean",
|
|
332
|
+
"required": false,
|
|
333
|
+
"description": "Keep every trace with a span ended in error (default: on)."
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"name": "slowerThanMs",
|
|
337
|
+
"type": "number | false",
|
|
338
|
+
"required": false,
|
|
339
|
+
"description": "Keep every trace that took at least this many milliseconds (default 1000; `false` for none)."
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"name": "percentage",
|
|
343
|
+
"type": "number | false",
|
|
344
|
+
"required": false,
|
|
345
|
+
"description": "Keep this percentage of all other traces, by trace id hash (default 10; `false` for none)."
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"name": "policies",
|
|
349
|
+
"type": "TailSamplingPolicy[]",
|
|
350
|
+
"required": false,
|
|
351
|
+
"description": "More policies, evaluated after the ones above."
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"name": "numTraces",
|
|
355
|
+
"type": "number",
|
|
356
|
+
"required": false,
|
|
357
|
+
"description": "How many traces to hold in memory at once (default: the collector's 50000)."
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"name": "memoryLimitMib",
|
|
361
|
+
"type": "number",
|
|
362
|
+
"required": false,
|
|
363
|
+
"description": "`memory_limiter`'s hard limit in MiB (default: 80% of the container's memory, with a 20% spike limit)."
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"name": "healthCheck",
|
|
367
|
+
"type": "boolean",
|
|
368
|
+
"required": false,
|
|
369
|
+
"description": "Serve `health_check` on 0.0.0.0:13133 (default: on)."
|
|
370
|
+
}
|
|
371
|
+
]
|
|
80
372
|
}
|
|
81
373
|
];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GenAiPipeline`: the composite declares exactly the config
|
|
3
|
+
* `genAiPipeline()` returns, with each entity under a member name.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, test } from "vitest";
|
|
6
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
7
|
+
import { GenAiPipeline } from "./index";
|
|
8
|
+
import { genAiPipeline, type GenAiPipelineOptions } from "../genai";
|
|
9
|
+
import { PrometheusExporter } from "../components/exporters";
|
|
10
|
+
import { TailSamplingProcessor } from "../components/sampling";
|
|
11
|
+
import { collectorYaml } from "../collector";
|
|
12
|
+
|
|
13
|
+
const yamlOf = (entities: Declarable[]) => collectorYaml(entities);
|
|
14
|
+
|
|
15
|
+
describe("GenAiPipeline", () => {
|
|
16
|
+
const sampling = [new TailSamplingProcessor({ decision_wait: "10s", policies: [{ name: "errors", type: "status_code", status_code: { status_codes: ["ERROR"] } }] })];
|
|
17
|
+
const cases: Array<[string, GenAiPipelineOptions]> = [
|
|
18
|
+
["the defaults", {}],
|
|
19
|
+
["client metrics derived to a prometheus exporter", { clientMetrics: "derive", metricExporters: [new PrometheusExporter({ endpoint: "0.0.0.0:8889" })] }],
|
|
20
|
+
["sampling, no logs, no health check", { sampling, logs: false, healthCheck: false }],
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
test.each(cases)("%s: the same config as genAiPipeline()", (_label, options) => {
|
|
24
|
+
const composite = GenAiPipeline(options);
|
|
25
|
+
expect(yamlOf(Object.values(composite.members) as Declarable[])).toBe(yamlOf(genAiPipeline(options)));
|
|
26
|
+
expect(Object.values(composite.members)).toHaveLength(genAiPipeline(options).length);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("the members are named after their parts, and the parts that are off are absent", () => {
|
|
30
|
+
expect(Object.keys(GenAiPipeline({}).members)).toEqual(["otlp", "traces", "genAiTraces", "genAiMetrics", "logs", "health"]);
|
|
31
|
+
expect(Object.keys(GenAiPipeline({ clientMetrics: "passthrough" }).members)).toContain("sdkMetrics");
|
|
32
|
+
expect(Object.keys(GenAiPipeline({ sampling, logs: false, healthCheck: false }).members)).toEqual([
|
|
33
|
+
"otlp",
|
|
34
|
+
"traces",
|
|
35
|
+
"sampled",
|
|
36
|
+
"genAiTraces",
|
|
37
|
+
"genAiMetrics",
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("genAiPipeline() still returns its entities in the order it always has: receiver, pipelines, extension", () => {
|
|
42
|
+
const ids = genAiPipeline().map((e) => (e as { pipelineId?: string; componentId?: string }).pipelineId ?? (e as { componentId?: string }).componentId);
|
|
43
|
+
expect(ids).toEqual(["otlp", "traces", "traces/genai", "metrics/genai", "logs", "health_check"]);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("the pipeline ids are the preset's", () => {
|
|
47
|
+
const g = GenAiPipeline({ sampling });
|
|
48
|
+
expect(g.traces.pipelineId).toBe("traces");
|
|
49
|
+
expect(g.sampled?.pipelineId).toBe("traces/sampled");
|
|
50
|
+
expect(g.genAiTraces.pipelineId).toBe("traces/genai");
|
|
51
|
+
expect(g.genAiMetrics.pipelineId).toBe("metrics/genai");
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GenAiPipeline`: `genAiPipeline()` as a composite.
|
|
3
|
+
*
|
|
4
|
+
* The same collector config `genAiPipeline(options)` returns as a list (an
|
|
5
|
+
* `otlp` receiver, content removal on traces and logs, a `traces/genai`
|
|
6
|
+
* branch that turns GenAI spans into metrics before any sampling, and a
|
|
7
|
+
* `metrics/genai` pipeline that exports them), with each entity under a
|
|
8
|
+
* member name, so a project exports one declaration and reads the parts by
|
|
9
|
+
* name. The options are `genAiPipeline()`'s; every one has its default.
|
|
10
|
+
*
|
|
11
|
+
* The prometheus lexicon's `GenAiRules` reads the metric names from
|
|
12
|
+
* `genAiMetrics(options)` with the same options.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Composite, type CompositeInstance } from "@intentius/chant/composite";
|
|
16
|
+
import { genAiPipelineParts, type GenAiPipelineOptions, type GenAiPipelineParts } from "../genai";
|
|
17
|
+
|
|
18
|
+
export type GenAiPipelineProps = GenAiPipelineOptions;
|
|
19
|
+
|
|
20
|
+
/** The members: `otlp`, `traces`, `sampled` (with `sampling`), `genAiTraces`, `genAiMetrics`, `sdkMetrics` (with `clientMetrics`), `logs` and `health` (unless off). */
|
|
21
|
+
export type GenAiPipelineMembers = GenAiPipelineParts;
|
|
22
|
+
|
|
23
|
+
export type GenAiPipelineInstance = CompositeInstance<GenAiPipelineMembers> & GenAiPipelineMembers;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The collector config of an OTLP collector for GenAI workloads, from the
|
|
27
|
+
* GenAI preset.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { GenAiPipeline, PrometheusExporter } from "@intentius/chant-lexicon-otel";
|
|
32
|
+
*
|
|
33
|
+
* const scrape = new PrometheusExporter({ endpoint: "0.0.0.0:8889" });
|
|
34
|
+
* export const genai = GenAiPipeline({ metricExporters: [scrape], clientMetrics: "derive" });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export const GenAiPipeline = Composite<GenAiPipelineProps, GenAiPipelineMembers>(
|
|
38
|
+
(props) => genAiPipelineParts(props ?? {}),
|
|
39
|
+
"GenAiPipeline",
|
|
40
|
+
);
|
package/src/composites/index.ts
CHANGED
|
@@ -4,3 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
export { NodeAgent, nodeAgentPropsProblem } from "./node-agent";
|
|
6
6
|
export type { NodeAgentProps, NodeAgentMembers, NodeAgentInstance } from "./node-agent";
|
|
7
|
+
export { RedMetrics, redMetricsNames, redMetricsPropsProblem } from "./red-metrics";
|
|
8
|
+
export type { RedMetricsProps, RedMetricsMembers, RedMetricsInstance, RedMetricsNames } from "./red-metrics";
|
|
9
|
+
export { GenAiPipeline } from "./genai-pipeline";
|
|
10
|
+
export type { GenAiPipelineProps, GenAiPipelineMembers, GenAiPipelineInstance } from "./genai-pipeline";
|
|
11
|
+
export { OtlpCollector, otlpCollectorPropsProblem } from "./otlp-collector";
|
|
12
|
+
export type { OtlpCollectorProps, OtlpCollectorMembers, OtlpCollectorInstance } from "./otlp-collector";
|
|
13
|
+
export { TailSamplingTier, tailSamplingTierPropsProblem, tailSamplingLoadBalancer } from "./tail-sampling-tier";
|
|
14
|
+
export type { TailSamplingTierProps, TailSamplingTierMembers, TailSamplingTierInstance } from "./tail-sampling-tier";
|