@intentius/chant-lexicon-otel 0.124.30 → 0.124.32
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/dist/attribution.js +391 -0
- package/dist/catalog.js +42 -0
- package/dist/codegen/docs-cli.js +3 -0
- package/dist/codegen/docs.js +101 -0
- package/dist/codegen/generate-cli.js +7 -0
- package/dist/codegen/generate.js +43 -0
- package/dist/codegen/package.js +28 -0
- package/dist/collector.js +150 -0
- package/dist/components/common.js +50 -0
- package/dist/components/connectors.js +242 -0
- package/dist/components/exporters.js +57 -0
- package/dist/components/extensions.js +58 -0
- package/dist/components/filtering.js +106 -0
- package/dist/components/index.js +9 -0
- package/dist/components/k8s-receivers.js +36 -0
- package/dist/components/processors.js +103 -0
- package/dist/components/receivers.js +61 -0
- package/dist/components/sampling.js +257 -0
- package/dist/composites/catalog.js +368 -0
- package/dist/composites/genai-pipeline.js +28 -0
- package/dist/composites/index.js +8 -0
- package/dist/composites/node-agent.js +156 -0
- package/dist/composites/otlp-collector.js +57 -0
- package/dist/composites/red-metrics.js +95 -0
- package/dist/composites/tail-sampling-tier.js +132 -0
- package/dist/config-hygiene.js +464 -0
- package/dist/configmap.js +86 -0
- package/dist/define.js +204 -0
- package/dist/detect.js +22 -0
- package/dist/genai.js +569 -0
- package/dist/import/embedded.js +57 -0
- package/dist/import/generator.js +459 -0
- package/dist/import/parser.js +199 -0
- package/dist/index.js +34 -0
- package/dist/init-templates.js +119 -0
- package/dist/integrity.json +2 -2
- package/dist/lint/audit-catalog.js +49 -0
- package/dist/lint/post-synth/index.js +52 -0
- package/dist/lint/post-synth/otel-helpers.js +103 -0
- package/dist/lint/post-synth/otel101.js +13 -0
- package/dist/lint/post-synth/otel102.js +13 -0
- package/dist/lint/post-synth/otel103.js +13 -0
- package/dist/lint/post-synth/otel104.js +13 -0
- package/dist/lint/post-synth/otel105.js +13 -0
- package/dist/lint/post-synth/otel106.js +13 -0
- package/dist/lint/post-synth/otel107.js +13 -0
- package/dist/lint/post-synth/otel108.js +13 -0
- package/dist/lint/post-synth/otel109.js +13 -0
- package/dist/lint/post-synth/otel112.js +13 -0
- package/dist/lint/post-synth/otel113.js +13 -0
- package/dist/lint/post-synth/otel114.js +13 -0
- package/dist/lint/post-synth/otel115.js +13 -0
- package/dist/lint/post-synth/otel116.js +13 -0
- package/dist/lint/post-synth/otel117.js +13 -0
- package/dist/lint/post-synth/otel118.js +13 -0
- package/dist/lint/post-synth/otel119.js +13 -0
- package/dist/lint/post-synth/otel120.js +13 -0
- package/dist/lint/post-synth/otel121.js +13 -0
- package/dist/lint/post-synth/otel122.js +13 -0
- package/dist/lint/post-synth/otel123.js +13 -0
- package/dist/lint/post-synth/otel124.js +13 -0
- package/dist/lint/post-synth/otel125.js +13 -0
- package/dist/lint/post-synth/otel126.js +13 -0
- package/dist/lint/post-synth/otel127.js +13 -0
- package/dist/lint/rules/component-id-syntax.js +66 -0
- package/dist/lint/rules/index.js +6 -0
- package/dist/lint/rules/literal-credential.js +91 -0
- package/dist/lint/rules/otel-ast.js +30 -0
- package/dist/lsp/completions.js +11 -0
- package/dist/lsp/hover.js +23 -0
- package/dist/manifest.json +1 -1
- package/dist/metric-names.js +244 -0
- package/dist/model.js +90 -0
- package/dist/op/activities/collector-audit.js +213 -0
- package/dist/op/activities/collector-health.js +176 -0
- package/dist/op/activities/exec.js +16 -0
- package/dist/op/activities/github.js +110 -0
- package/dist/op/activities/index.js +16 -0
- package/dist/op/activities/otelcol.js +173 -0
- package/dist/op/activity-contracts.js +64 -0
- package/dist/op/audit-op.js +33 -0
- package/dist/op/builders.js +38 -0
- package/dist/package-cli.js +14 -0
- package/dist/pipeline.js +31 -0
- package/dist/platform.js +144 -0
- package/dist/plugin.js +126 -0
- package/dist/semconv.js +50 -0
- package/dist/serializer.js +26 -0
- package/dist/skill-defs.js +34 -0
- package/dist/topology.js +104 -0
- package/dist/validate-cli.js +7 -0
- package/dist/validate-config.js +706 -0
- package/dist/validate.js +85 -0
- package/dist/yaml.js +157 -0
- package/package.json +8 -8
- package/src/codegen/package.ts +2 -2
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
export const compositeCatalog = [
|
|
2
|
+
{
|
|
3
|
+
"name": "GenAiPipeline",
|
|
4
|
+
"lexicon": "otel",
|
|
5
|
+
"description": "The collector config of an OTLP collector for GenAI workloads, from the GenAI preset.",
|
|
6
|
+
"bundles": [
|
|
7
|
+
"BatchProcessor",
|
|
8
|
+
"DebugExporter",
|
|
9
|
+
"DeltaToCumulativeProcessor",
|
|
10
|
+
"FilterProcessor",
|
|
11
|
+
"ForwardConnector",
|
|
12
|
+
"HealthCheckExtension",
|
|
13
|
+
"MemoryLimiterProcessor",
|
|
14
|
+
"OtlpReceiver",
|
|
15
|
+
"Pipeline",
|
|
16
|
+
"RedactionProcessor",
|
|
17
|
+
"SignalToMetricsConnector",
|
|
18
|
+
"SpanMetricsConnector",
|
|
19
|
+
"SumConnector",
|
|
20
|
+
"TransformProcessor"
|
|
21
|
+
],
|
|
22
|
+
"params": [
|
|
23
|
+
{
|
|
24
|
+
"name": "traceExporters",
|
|
25
|
+
"type": "Exporter[]",
|
|
26
|
+
"required": false,
|
|
27
|
+
"description": "Where traces go."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "metricExporters",
|
|
31
|
+
"type": "Exporter[]",
|
|
32
|
+
"required": false,
|
|
33
|
+
"description": "Where the span and token metrics go, and with `clientMetrics` the SDK's metrics too."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "logExporters",
|
|
37
|
+
"type": "Exporter[]",
|
|
38
|
+
"required": false,
|
|
39
|
+
"description": "Where logs (and events sent as logs) go."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "logs",
|
|
43
|
+
"type": "boolean",
|
|
44
|
+
"required": false,
|
|
45
|
+
"description": "Give logs a pipeline, so event-based content is removed too."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "sampling",
|
|
49
|
+
"type": "Processor[]",
|
|
50
|
+
"required": false,
|
|
51
|
+
"description": "Processors that thin exported traces, such as `tail_sampling`."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "healthCheck",
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"required": false,
|
|
57
|
+
"description": "Serve `health_check` on 0.0.0.0:13133."
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "deltaToCumulative",
|
|
61
|
+
"type": "boolean | \"auto\"",
|
|
62
|
+
"required": false,
|
|
63
|
+
"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."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "keepContent",
|
|
67
|
+
"type": "boolean",
|
|
68
|
+
"required": false,
|
|
69
|
+
"description": "Keep content attributes and bodies."
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "contentAttributes",
|
|
73
|
+
"type": "string[]",
|
|
74
|
+
"required": false,
|
|
75
|
+
"description": "More attribute keys that hold content, deleted along with the convention ones."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "maskValues",
|
|
79
|
+
"type": "string[]",
|
|
80
|
+
"required": false,
|
|
81
|
+
"description": "RE2 patterns masked in every attribute value (redaction `blocked_values`), whether content is kept or not."
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "hashFunction",
|
|
85
|
+
"type": "RedactionProcessorConfig[\"hash_function\"]",
|
|
86
|
+
"required": false,
|
|
87
|
+
"description": "Hash masked values with this function instead of writing `****`."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "buckets",
|
|
91
|
+
"type": "Duration[]",
|
|
92
|
+
"required": false,
|
|
93
|
+
"description": "Duration histogram buckets."
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "metricsFlushInterval",
|
|
97
|
+
"type": "Duration",
|
|
98
|
+
"required": false,
|
|
99
|
+
"description": "How often span and token metrics are flushed."
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "namespace",
|
|
103
|
+
"type": "string",
|
|
104
|
+
"required": false,
|
|
105
|
+
"description": "Prefix of the emitted metric names."
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "dimensions",
|
|
109
|
+
"type": "SpanMetricsDimension[]",
|
|
110
|
+
"required": false,
|
|
111
|
+
"description": "Dimensions added to the span metrics beyond the GenAI ones."
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "providerDimensions",
|
|
115
|
+
"type": "boolean",
|
|
116
|
+
"required": false,
|
|
117
|
+
"description": "Add `gen_ai.provider.name` and `gen_ai.response.model` to `genai.calls` and `genai.duration`."
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "clientMetrics",
|
|
121
|
+
"type": "GenAiClientMetricsSource",
|
|
122
|
+
"required": false,
|
|
123
|
+
"description": "Also produce the conventions' client metrics, `gen_ai.client.operation.duration` and `gen_ai.client.token.usage`."
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "NodeAgent",
|
|
129
|
+
"lexicon": "otel",
|
|
130
|
+
"description": "The collector config of a per-node Kubernetes agent.",
|
|
131
|
+
"bundles": [
|
|
132
|
+
"BatchProcessor",
|
|
133
|
+
"FileLogReceiver",
|
|
134
|
+
"HealthCheckExtension",
|
|
135
|
+
"HostMetricsReceiver",
|
|
136
|
+
"K8sAttributesProcessor",
|
|
137
|
+
"KubeletStatsReceiver",
|
|
138
|
+
"MemoryLimiterProcessor",
|
|
139
|
+
"OtlpReceiver",
|
|
140
|
+
"Pipeline",
|
|
141
|
+
"ResourceDetectionProcessor",
|
|
142
|
+
"ResourceProcessor"
|
|
143
|
+
],
|
|
144
|
+
"params": [
|
|
145
|
+
{
|
|
146
|
+
"name": "exporters",
|
|
147
|
+
"type": "Exporter[]",
|
|
148
|
+
"required": true,
|
|
149
|
+
"description": "Where traces and logs go: usually the gateway (the k8s lexicon's `gatewayExporter()`), or an OTLP backend."
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "metricExporters",
|
|
153
|
+
"type": "Exporter[]",
|
|
154
|
+
"required": false,
|
|
155
|
+
"description": "Where metrics go, e.g. a `prometheus` exporter for a scrape on each node."
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "clusterName",
|
|
159
|
+
"type": "string",
|
|
160
|
+
"required": false,
|
|
161
|
+
"description": "Sets `k8s.cluster.name` on everything the agent sends."
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "nodeNameEnv",
|
|
165
|
+
"type": "string",
|
|
166
|
+
"required": false,
|
|
167
|
+
"description": "The environment variable holding this node's name, set from `spec.nodeName` (default `K8S_NODE_NAME`)."
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"name": "hostMetrics",
|
|
171
|
+
"type": "boolean | { interval?: Duration; rootPath?: string }",
|
|
172
|
+
"required": false,
|
|
173
|
+
"description": "Node CPU, memory, load, filesystem and network from the host root at `/hostfs` (default: on, every 30s)."
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "containerLogs",
|
|
177
|
+
"type": "boolean | { selfContainer?: string }",
|
|
178
|
+
"required": false,
|
|
179
|
+
"description": "Container logs from `/var/log/pods` (default: on)."
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"name": "kubeletStats",
|
|
183
|
+
"type": "boolean | { interval?: Duration }",
|
|
184
|
+
"required": false,
|
|
185
|
+
"description": "Pod and container resource metrics from this node's kubelet (default: off)."
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "memoryLimitMib",
|
|
189
|
+
"type": "number",
|
|
190
|
+
"required": false,
|
|
191
|
+
"description": "`memory_limiter`'s hard limit in MiB (default 400; the spike limit is a quarter of it)."
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"name": "healthCheck",
|
|
195
|
+
"type": "boolean",
|
|
196
|
+
"required": false,
|
|
197
|
+
"description": "Serve `health_check` on 0.0.0.0:13133 (default: on)."
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"name": "OtlpCollector",
|
|
203
|
+
"lexicon": "otel",
|
|
204
|
+
"description": "A small OTLP collector config: OTLP in, `memory_limiter` and `batch`, the given exporters out, for each signal.",
|
|
205
|
+
"bundles": [
|
|
206
|
+
"BatchProcessor",
|
|
207
|
+
"DebugExporter",
|
|
208
|
+
"HealthCheckExtension",
|
|
209
|
+
"MemoryLimiterProcessor",
|
|
210
|
+
"OtlpReceiver",
|
|
211
|
+
"Pipeline"
|
|
212
|
+
],
|
|
213
|
+
"params": [
|
|
214
|
+
{
|
|
215
|
+
"name": "exporters",
|
|
216
|
+
"type": "OTelComponent<\"exporter\", string, any>[]",
|
|
217
|
+
"required": false,
|
|
218
|
+
"description": "Where telemetry goes."
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"name": "signals",
|
|
222
|
+
"type": "Signal[]",
|
|
223
|
+
"required": false,
|
|
224
|
+
"description": "Which signals get a pipeline."
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"name": "healthCheck",
|
|
228
|
+
"type": "boolean",
|
|
229
|
+
"required": false,
|
|
230
|
+
"description": "Serve `health_check` on 0.0.0.0:13133."
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "RedMetrics",
|
|
236
|
+
"lexicon": "otel",
|
|
237
|
+
"description": "RED metrics from traces: `spanmetrics` and `servicegraph` connectors feeding a `prometheus` exporter.",
|
|
238
|
+
"bundles": [
|
|
239
|
+
"BatchProcessor",
|
|
240
|
+
"MemoryLimiterProcessor",
|
|
241
|
+
"OtlpReceiver",
|
|
242
|
+
"Pipeline",
|
|
243
|
+
"PrometheusExporter",
|
|
244
|
+
"ServiceGraphConnector",
|
|
245
|
+
"SpanMetricsConnector"
|
|
246
|
+
],
|
|
247
|
+
"params": [
|
|
248
|
+
{
|
|
249
|
+
"name": "receivers",
|
|
250
|
+
"type": "TraceSource[]",
|
|
251
|
+
"required": false,
|
|
252
|
+
"description": "Where spans come from: receivers, or a connector from another traces pipeline."
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"name": "traceExporters",
|
|
256
|
+
"type": "Exporter[]",
|
|
257
|
+
"required": false,
|
|
258
|
+
"description": "Where traces go besides the connectors, e.g. a tracing backend."
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"name": "exporter",
|
|
262
|
+
"type": "OTelComponent<\"exporter\", \"prometheus\", PrometheusExporterConfig>",
|
|
263
|
+
"required": false,
|
|
264
|
+
"description": "The `prometheus` exporter the metrics are served on."
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"name": "spanMetrics",
|
|
268
|
+
"type": "SpanMetricsConnectorConfig",
|
|
269
|
+
"required": false,
|
|
270
|
+
"description": "The `spanmetrics` connector's config: namespace, dimensions, histogram unit and buckets (default: the connector's defaults)."
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"name": "serviceGraph",
|
|
274
|
+
"type": "boolean | ServiceGraphConnectorConfig",
|
|
275
|
+
"required": false,
|
|
276
|
+
"description": "Service-to-service edge metrics from a `servicegraph` connector (default: on)."
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"name": "memoryLimitMib",
|
|
280
|
+
"type": "number",
|
|
281
|
+
"required": false,
|
|
282
|
+
"description": "`memory_limiter`'s hard limit in MiB (default: 80% of the container's memory, with a 20% spike limit)."
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"name": "name",
|
|
286
|
+
"type": "string",
|
|
287
|
+
"required": false,
|
|
288
|
+
"description": "The instance name of the connectors, the exporter and the two pipelines (default `red`)."
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"name": "TailSamplingTier",
|
|
294
|
+
"lexicon": "otel",
|
|
295
|
+
"description": "The collector config of a tail sampling tier: whole traces in, the ones a policy keeps out.",
|
|
296
|
+
"bundles": [
|
|
297
|
+
"BatchProcessor",
|
|
298
|
+
"DebugExporter",
|
|
299
|
+
"HealthCheckExtension",
|
|
300
|
+
"MemoryLimiterProcessor",
|
|
301
|
+
"OtlpReceiver",
|
|
302
|
+
"Pipeline",
|
|
303
|
+
"TailSamplingProcessor"
|
|
304
|
+
],
|
|
305
|
+
"params": [
|
|
306
|
+
{
|
|
307
|
+
"name": "exporters",
|
|
308
|
+
"type": "Exporter[]",
|
|
309
|
+
"required": false,
|
|
310
|
+
"description": "Where the kept traces go."
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"name": "receivers",
|
|
314
|
+
"type": "TraceSource[]",
|
|
315
|
+
"required": false,
|
|
316
|
+
"description": "Where spans come from."
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"name": "decisionWait",
|
|
320
|
+
"type": "Duration",
|
|
321
|
+
"required": false,
|
|
322
|
+
"description": "How long after a trace's first span the decision is made (default `10s`)."
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"name": "errors",
|
|
326
|
+
"type": "boolean",
|
|
327
|
+
"required": false,
|
|
328
|
+
"description": "Keep every trace with a span ended in error (default: on)."
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"name": "slowerThanMs",
|
|
332
|
+
"type": "number | false",
|
|
333
|
+
"required": false,
|
|
334
|
+
"description": "Keep every trace that took at least this many milliseconds (default 1000; `false` for none)."
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"name": "percentage",
|
|
338
|
+
"type": "number | false",
|
|
339
|
+
"required": false,
|
|
340
|
+
"description": "Keep this percentage of all other traces, by trace id hash (default 10; `false` for none)."
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"name": "policies",
|
|
344
|
+
"type": "TailSamplingPolicy[]",
|
|
345
|
+
"required": false,
|
|
346
|
+
"description": "More policies, evaluated after the ones above."
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"name": "numTraces",
|
|
350
|
+
"type": "number",
|
|
351
|
+
"required": false,
|
|
352
|
+
"description": "How many traces to hold in memory at once (default: the collector's 50000)."
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"name": "memoryLimitMib",
|
|
356
|
+
"type": "number",
|
|
357
|
+
"required": false,
|
|
358
|
+
"description": "`memory_limiter`'s hard limit in MiB (default: 80% of the container's memory, with a 20% spike limit)."
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"name": "healthCheck",
|
|
362
|
+
"type": "boolean",
|
|
363
|
+
"required": false,
|
|
364
|
+
"description": "Serve `health_check` on 0.0.0.0:13133 (default: on)."
|
|
365
|
+
}
|
|
366
|
+
]
|
|
367
|
+
}
|
|
368
|
+
];
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
import { Composite } from "@intentius/chant/composite";
|
|
15
|
+
import { genAiPipelineParts } from "../genai.js";
|
|
16
|
+
/**
|
|
17
|
+
* The collector config of an OTLP collector for GenAI workloads, from the
|
|
18
|
+
* GenAI preset.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { GenAiPipeline, PrometheusExporter } from "@intentius/chant-lexicon-otel";
|
|
23
|
+
*
|
|
24
|
+
* const scrape = new PrometheusExporter({ endpoint: "0.0.0.0:8889" });
|
|
25
|
+
* export const genai = GenAiPipeline({ metricExporters: [scrape], clientMetrics: "derive" });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export const GenAiPipeline = Composite((props) => genAiPipelineParts(props ?? {}), "GenAiPipeline");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* otel lexicon composites: declarations that expand to a collector config's components and pipelines.
|
|
3
|
+
*/
|
|
4
|
+
export { NodeAgent, nodeAgentPropsProblem } from "./node-agent.js";
|
|
5
|
+
export { RedMetrics, redMetricsNames, redMetricsPropsProblem } from "./red-metrics.js";
|
|
6
|
+
export { GenAiPipeline } from "./genai-pipeline.js";
|
|
7
|
+
export { OtlpCollector, otlpCollectorPropsProblem } from "./otlp-collector.js";
|
|
8
|
+
export { TailSamplingTier, tailSamplingTierPropsProblem, tailSamplingLoadBalancer } from "./tail-sampling-tier.js";
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `NodeAgent`: the collector config a per-node agent runs on Kubernetes.
|
|
3
|
+
*
|
|
4
|
+
* One collector per node (a DaemonSet) takes OTLP from the pods on its node,
|
|
5
|
+
* reads the node's own telemetry, puts Kubernetes metadata on all of it, and
|
|
6
|
+
* hands it on, usually to a gateway tier. This composite declares that
|
|
7
|
+
* config:
|
|
8
|
+
*
|
|
9
|
+
* - receivers: `otlp` (gRPC on 4317, HTTP on 4318), and by default
|
|
10
|
+
* `hostmetrics` (CPU, memory, load, filesystem, network of the node, read
|
|
11
|
+
* under `/hostfs`) and `filelog` (container logs under `/var/log/pods`,
|
|
12
|
+
* parsed by the `container` operator). `kubeletstats` (pod and container
|
|
13
|
+
* resource metrics from the local kubelet) is opt-in.
|
|
14
|
+
* - processors, in order: `memory_limiter`; `k8sattributes`, filtered to
|
|
15
|
+
* pods on this node and matching by pod IP, pod UID or the connection;
|
|
16
|
+
* `resourcedetection` (`env`, `system`); a `resource` processor setting
|
|
17
|
+
* `k8s.cluster.name` when `clusterName` is given; `batch`.
|
|
18
|
+
* - a `traces`, a `metrics` and a `logs` pipeline, each through those
|
|
19
|
+
* processors to the given exporters.
|
|
20
|
+
* - a `health_check` extension on 0.0.0.0:13133.
|
|
21
|
+
*
|
|
22
|
+
* Tail sampling is left out on purpose: an agent sees only its node's
|
|
23
|
+
* spans of a trace, so a sampling decision there is made on partial traces.
|
|
24
|
+
* Sample on the gateway.
|
|
25
|
+
*
|
|
26
|
+
* What the pod has to provide: the node name in an environment variable
|
|
27
|
+
* (`K8S_NODE_NAME` by default, from `spec.nodeName`), the host root mounted
|
|
28
|
+
* read-only at `/hostfs` for `hostmetrics`, `/var/log/pods` mounted
|
|
29
|
+
* read-only for `filelog`, and a service account that may get, list and
|
|
30
|
+
* watch pods, namespaces and nodes (and replicasets, for
|
|
31
|
+
* `k8s.deployment.name`). The k8s lexicon's `OtelCollector` takes this
|
|
32
|
+
* composite's entities as its `config` and derives all of that from them:
|
|
33
|
+
* the variable, the read-only host mounts, group 0 for the root-owned log
|
|
34
|
+
* files, the RBAC and the ports.
|
|
35
|
+
*/
|
|
36
|
+
import { Composite } from "@intentius/chant/composite";
|
|
37
|
+
import { OtlpReceiver, HostMetricsReceiver, FileLogReceiver } from "../components/receivers.js";
|
|
38
|
+
import { KubeletStatsReceiver } from "../components/k8s-receivers.js";
|
|
39
|
+
import { BatchProcessor, K8sAttributesProcessor, MemoryLimiterProcessor, ResourceDetectionProcessor, ResourceProcessor, } from "../components/processors.js";
|
|
40
|
+
import { HealthCheckExtension } from "../components/extensions.js";
|
|
41
|
+
import { Pipeline } from "../pipeline.js";
|
|
42
|
+
const HOST_SCRAPERS = { cpu: {}, memory: {}, load: {}, filesystem: {}, network: {} };
|
|
43
|
+
/** Pod metadata for every signal. `k8s.pod.uid` is what the `container` log parser sets on log records. */
|
|
44
|
+
const POD_METADATA = {
|
|
45
|
+
metadata: ["k8s.namespace.name", "k8s.pod.name", "k8s.pod.uid", "k8s.deployment.name", "k8s.node.name"],
|
|
46
|
+
};
|
|
47
|
+
const POD_ASSOCIATION = [
|
|
48
|
+
{ sources: [{ from: "resource_attribute", name: "k8s.pod.ip" }] },
|
|
49
|
+
{ sources: [{ from: "resource_attribute", name: "k8s.pod.uid" }] },
|
|
50
|
+
{ sources: [{ from: "connection" }] },
|
|
51
|
+
];
|
|
52
|
+
function option(value, onByDefault) {
|
|
53
|
+
if (value === undefined)
|
|
54
|
+
return onByDefault ? {} : undefined;
|
|
55
|
+
if (value === false)
|
|
56
|
+
return undefined;
|
|
57
|
+
return value === true ? {} : value;
|
|
58
|
+
}
|
|
59
|
+
/** Why a set of `NodeAgent` props can't build, or undefined when they can. */
|
|
60
|
+
export function nodeAgentPropsProblem(props) {
|
|
61
|
+
if (!Array.isArray(props.exporters) || props.exporters.length === 0)
|
|
62
|
+
return "exporters must name at least one exporter";
|
|
63
|
+
if (props.metricExporters !== undefined && props.metricExporters.length === 0)
|
|
64
|
+
return "metricExporters must name at least one exporter when set";
|
|
65
|
+
if (props.memoryLimitMib !== undefined && !(Number.isInteger(props.memoryLimitMib) && props.memoryLimitMib > 0)) {
|
|
66
|
+
return "memoryLimitMib must be a positive whole number";
|
|
67
|
+
}
|
|
68
|
+
if (props.nodeNameEnv !== undefined && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(props.nodeNameEnv)) {
|
|
69
|
+
return `nodeNameEnv "${props.nodeNameEnv}" is not an environment variable name`;
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The collector config of a per-node Kubernetes agent: OTLP from the node's
|
|
75
|
+
* pods, host metrics and container logs from the node itself, Kubernetes
|
|
76
|
+
* metadata on everything, sent on to the given exporters.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { NodeAgent, OtlpExporter } from "@intentius/chant-lexicon-otel";
|
|
81
|
+
*
|
|
82
|
+
* const gateway = new OtlpExporter({ name: "gateway", endpoint: "otel-gateway.observability.svc:4317", tls: { insecure: true } });
|
|
83
|
+
* export const agent = NodeAgent({ exporters: [gateway], clusterName: "prod-eu-1" });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const NodeAgent = Composite((props) => {
|
|
87
|
+
const problem = nodeAgentPropsProblem(props);
|
|
88
|
+
if (problem)
|
|
89
|
+
throw new Error(`NodeAgent: ${problem}`);
|
|
90
|
+
const nodeNameEnv = props.nodeNameEnv ?? "K8S_NODE_NAME";
|
|
91
|
+
const limit = props.memoryLimitMib ?? 400;
|
|
92
|
+
const host = option(props.hostMetrics, true);
|
|
93
|
+
const logFiles = option(props.containerLogs, true);
|
|
94
|
+
const kubelet = option(props.kubeletStats, false);
|
|
95
|
+
const otlp = new OtlpReceiver({
|
|
96
|
+
protocols: { grpc: { endpoint: "0.0.0.0:4317" }, http: { endpoint: "0.0.0.0:4318" } },
|
|
97
|
+
});
|
|
98
|
+
const hostMetrics = host
|
|
99
|
+
? new HostMetricsReceiver({ collection_interval: host.interval ?? "30s", root_path: host.rootPath ?? "/hostfs", scrapers: HOST_SCRAPERS })
|
|
100
|
+
: undefined;
|
|
101
|
+
const containerLogs = logFiles
|
|
102
|
+
? new FileLogReceiver({
|
|
103
|
+
include: ["/var/log/pods/*/*/*.log"],
|
|
104
|
+
exclude: [`/var/log/pods/*/${logFiles.selfContainer ?? "otel-collector"}/*.log`],
|
|
105
|
+
start_at: "end",
|
|
106
|
+
include_file_path: true,
|
|
107
|
+
operators: [{ type: "container", id: "container-parser" }],
|
|
108
|
+
})
|
|
109
|
+
: undefined;
|
|
110
|
+
const kubeletStats = kubelet
|
|
111
|
+
? new KubeletStatsReceiver({
|
|
112
|
+
collection_interval: kubelet.interval ?? "30s",
|
|
113
|
+
auth_type: "serviceAccount",
|
|
114
|
+
endpoint: `https://\${env:${nodeNameEnv}}:10250`,
|
|
115
|
+
insecure_skip_verify: true,
|
|
116
|
+
node: `\${env:${nodeNameEnv}}`,
|
|
117
|
+
})
|
|
118
|
+
: undefined;
|
|
119
|
+
const memoryLimiter = new MemoryLimiterProcessor({ check_interval: "1s", limit_mib: limit, spike_limit_mib: Math.ceil(limit / 4) });
|
|
120
|
+
const k8sAttributes = new K8sAttributesProcessor({
|
|
121
|
+
auth_type: "serviceAccount",
|
|
122
|
+
filter: { node_from_env_var: nodeNameEnv },
|
|
123
|
+
extract: POD_METADATA,
|
|
124
|
+
pod_association: POD_ASSOCIATION,
|
|
125
|
+
});
|
|
126
|
+
const resourceDetection = new ResourceDetectionProcessor({ detectors: ["env", "system"], timeout: "5s", override: false });
|
|
127
|
+
const cluster = props.clusterName
|
|
128
|
+
? new ResourceProcessor({ attributes: [{ key: "k8s.cluster.name", value: props.clusterName, action: "upsert" }] })
|
|
129
|
+
: undefined;
|
|
130
|
+
const batch = new BatchProcessor({ timeout: "10s" });
|
|
131
|
+
const processors = [memoryLimiter, k8sAttributes, resourceDetection, ...(cluster ? [cluster] : []), batch];
|
|
132
|
+
const exporters = props.exporters;
|
|
133
|
+
const metricExporters = props.metricExporters ?? exporters;
|
|
134
|
+
const traces = new Pipeline({ signal: "traces", receivers: [otlp], processors, exporters });
|
|
135
|
+
const metrics = new Pipeline({
|
|
136
|
+
signal: "metrics",
|
|
137
|
+
receivers: [otlp, ...(hostMetrics ? [hostMetrics] : []), ...(kubeletStats ? [kubeletStats] : [])],
|
|
138
|
+
processors,
|
|
139
|
+
exporters: metricExporters,
|
|
140
|
+
});
|
|
141
|
+
const logs = new Pipeline({ signal: "logs", receivers: [...(containerLogs ? [containerLogs] : []), otlp], processors, exporters });
|
|
142
|
+
const health = props.healthCheck === false ? undefined : new HealthCheckExtension({ endpoint: "0.0.0.0:13133" });
|
|
143
|
+
// A composite member must be a declarable, so the components that are off are left out rather than undefined.
|
|
144
|
+
const members = { otlp, memoryLimiter, k8sAttributes, resourceDetection, batch, traces, metrics, logs };
|
|
145
|
+
if (hostMetrics)
|
|
146
|
+
members.hostMetrics = hostMetrics;
|
|
147
|
+
if (containerLogs)
|
|
148
|
+
members.containerLogs = containerLogs;
|
|
149
|
+
if (kubeletStats)
|
|
150
|
+
members.kubeletStats = kubeletStats;
|
|
151
|
+
if (cluster)
|
|
152
|
+
members.cluster = cluster;
|
|
153
|
+
if (health)
|
|
154
|
+
members.health = health;
|
|
155
|
+
return members;
|
|
156
|
+
}, "NodeAgent");
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `OtlpCollector`: `otlpCollector()` as a composite.
|
|
3
|
+
*
|
|
4
|
+
* The small OTLP collector the docker, k8s and fly platform composites start
|
|
5
|
+
* from: an `otlp` receiver on 4317 (gRPC) and 4318 (HTTP), `memory_limiter`
|
|
6
|
+
* then `batch`, the given exporters (default: one `debug` exporter), one
|
|
7
|
+
* pipeline per signal, and a `health_check` extension on 0.0.0.0:13133.
|
|
8
|
+
* Each part is a member, so a project exports one declaration and hands
|
|
9
|
+
* the parts on by name.
|
|
10
|
+
*/
|
|
11
|
+
import { Composite } from "@intentius/chant/composite";
|
|
12
|
+
import { otlpCollectorParts } from "../platform.js";
|
|
13
|
+
/** Why a set of `OtlpCollector` props can't build, or undefined when they can. */
|
|
14
|
+
export function otlpCollectorPropsProblem(props = {}) {
|
|
15
|
+
if (props.exporters !== undefined && props.exporters.length === 0)
|
|
16
|
+
return "exporters must name at least one exporter when set";
|
|
17
|
+
if (props.signals !== undefined) {
|
|
18
|
+
if (props.signals.length === 0)
|
|
19
|
+
return "signals must name at least one signal when set";
|
|
20
|
+
const bad = props.signals.find((s) => s !== "traces" && s !== "metrics" && s !== "logs");
|
|
21
|
+
if (bad !== undefined)
|
|
22
|
+
return `signals: "${String(bad)}" is not traces, metrics or logs`;
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A small OTLP collector config: OTLP in, `memory_limiter` and `batch`, the
|
|
28
|
+
* given exporters out, for each signal.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { OtlpCollector, OtlpExporter } from "@intentius/chant-lexicon-otel";
|
|
33
|
+
*
|
|
34
|
+
* const backend = new OtlpExporter({ name: "backend", endpoint: "collector.example.com:4317" });
|
|
35
|
+
* export const collector = OtlpCollector({ exporters: [backend], signals: ["traces", "logs"] });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export const OtlpCollector = Composite((input) => {
|
|
39
|
+
const props = input ?? {};
|
|
40
|
+
const problem = otlpCollectorPropsProblem(props);
|
|
41
|
+
if (problem)
|
|
42
|
+
throw new Error(`OtlpCollector: ${problem}`);
|
|
43
|
+
const p = otlpCollectorParts(props);
|
|
44
|
+
// A composite member must be a declarable, so the parts that are off are left out rather than undefined.
|
|
45
|
+
const members = { otlp: p.otlp, memoryLimiter: p.memoryLimiter, batch: p.batch };
|
|
46
|
+
if (props.exporters === undefined)
|
|
47
|
+
members.debug = p.exporters[0];
|
|
48
|
+
if (p.health)
|
|
49
|
+
members.health = p.health;
|
|
50
|
+
if (p.pipelines.traces)
|
|
51
|
+
members.traces = p.pipelines.traces;
|
|
52
|
+
if (p.pipelines.metrics)
|
|
53
|
+
members.metrics = p.pipelines.metrics;
|
|
54
|
+
if (p.pipelines.logs)
|
|
55
|
+
members.logs = p.pipelines.logs;
|
|
56
|
+
return members;
|
|
57
|
+
}, "OtlpCollector");
|